Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin
This commit is contained in:
commit
69657a2127
@ -3,4 +3,4 @@ ports:
|
||||
onOpen: open-preview
|
||||
tasks:
|
||||
- init: corepack enable && pnpm install
|
||||
command: pnpm run dev
|
||||
command: pnpm run dev:play
|
||||
|
@ -133,6 +133,10 @@ pnpm build
|
||||
|
||||
<a style="display: block;width: 100px;height: 50px;line-height: 50px; color: #fff;text-align: center; background: #408aed;border-radius: 4px;" href="https://www.paypal.com/paypalme/cvvben">Paypal Me</a>
|
||||
|
||||
## スター歴史
|
||||
|
||||
[](https://star-history.com/#vbenjs/vue-vben-admin&Date)
|
||||
|
||||
## 貢献者
|
||||
|
||||
<a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors">
|
||||
|
@ -132,6 +132,10 @@ If you think this project is helpful to you, you can help the author buy a cup o
|
||||
|
||||
<a style="display: block;width: 100px;height: 50px;line-height: 50px; color: #fff;text-align: center; background: #408aed;border-radius: 4px;" href="https://www.paypal.com/paypalme/cvvben">Paypal Me</a>
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/#vbenjs/vue-vben-admin&Date)
|
||||
|
||||
## Contributor
|
||||
|
||||
<a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors">
|
||||
|
@ -150,6 +150,10 @@ pnpm build
|
||||
|
||||
[CHANGELOG](https://github.com/vbenjs/vue-vben-admin/releases)
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/#vbenjs/vue-vben-admin&Date)
|
||||
|
||||
## Contributor
|
||||
|
||||
<a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors">
|
||||
|
@ -46,8 +46,6 @@ The execution command is: `pnpm run [script]` or `npm run [script]`.
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
// Install dependencies
|
||||
"bootstrap": "pnpm install",
|
||||
// Build the project
|
||||
"build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 turbo build",
|
||||
// Build the project with analysis
|
||||
@ -107,9 +105,9 @@ The execution command is: `pnpm run [script]` or `npm run [script]`.
|
||||
// Package specification check
|
||||
"publint": "vsh publint",
|
||||
// Delete all node_modules, yarn.lock, package.lock.json, and reinstall dependencies
|
||||
"reinstall": "pnpm clean --del-lock && pnpm bootstrap",
|
||||
"reinstall": "pnpm clean --del-lock && pnpm install",
|
||||
// Run vitest unit tests
|
||||
"test:unit": "vitest",
|
||||
"test:unit": "vitest run --dom",
|
||||
// Update project dependencies
|
||||
"update:deps": " pnpm update --latest --recursive",
|
||||
// Changeset generation and versioning
|
||||
|
@ -46,8 +46,6 @@ npm 脚本是项目常见的配置,用于执行一些常见的任务,比如
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
// 安装依赖
|
||||
"bootstrap": "pnpm install",
|
||||
// 构建项目
|
||||
"build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 turbo build",
|
||||
// 构建项目并分析
|
||||
@ -107,9 +105,9 @@ npm 脚本是项目常见的配置,用于执行一些常见的任务,比如
|
||||
// 包规范检查
|
||||
"publint": "vsh publint",
|
||||
// 删除所有的node_modules、yarn.lock、package.lock.json,重新安装依赖
|
||||
"reinstall": "pnpm clean --del-lock && pnpm bootstrap",
|
||||
"reinstall": "pnpm clean --del-lock && pnpm install",
|
||||
// 运行 vitest 单元测试
|
||||
"test:unit": "vitest",
|
||||
"test:unit": "vitest run --dom",
|
||||
// 更新项目依赖
|
||||
"update:deps": " pnpm update --latest --recursive",
|
||||
// changeset生成提交集
|
||||
|
@ -24,6 +24,7 @@ export async function node(): Promise<Linter.Config[]> {
|
||||
'vite',
|
||||
'@vue/test-utils',
|
||||
'@vben/tailwind-config',
|
||||
'@playwright/test',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
@ -138,6 +138,14 @@ const customConfig: Linter.Config[] = [
|
||||
'unicorn/prefer-module': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/**/playwright.config.ts'],
|
||||
rules: {
|
||||
'n/prefer-global/buffer': 'off',
|
||||
'n/prefer-global/process': 'off',
|
||||
'no-console': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['internal/**/**'],
|
||||
rules: {
|
||||
|
16
package.json
16
package.json
@ -25,11 +25,10 @@
|
||||
},
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"bootstrap": "pnpm install",
|
||||
"build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 turbo build",
|
||||
"build:analyze": "turbo build:analyze",
|
||||
"build:docker": "./build-local-docker-image.sh",
|
||||
"build:antd": "pnpm run build --filter=@vben/web-antd",
|
||||
"build:docker": "./build-local-docker-image.sh",
|
||||
"build:docs": "pnpm run build --filter=@vben/docs",
|
||||
"build:ele": "pnpm run build --filter=@vben/web-ele",
|
||||
"build:naive": "pnpm run build --filter=@vben/web-naive",
|
||||
@ -55,15 +54,16 @@
|
||||
"prepare": "is-ci || husky",
|
||||
"preview": "turbo-run preview",
|
||||
"publint": "vsh publint",
|
||||
"reinstall": "pnpm clean --del-lock && pnpm bootstrap",
|
||||
"test:unit": "vitest",
|
||||
"reinstall": "pnpm clean --del-lock && pnpm install",
|
||||
"test:unit": "vitest run --dom",
|
||||
"test:e2e": "turbo run test:e2e",
|
||||
"update:deps": "pnpm update --latest --recursive",
|
||||
"version": "pnpm exec changeset version && pnpm install --no-frozen-lockfile"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@changesets/changelog-github": "catalog:",
|
||||
"@changesets/cli": "catalog:",
|
||||
"@types/jsdom": "catalog:",
|
||||
"@playwright/test": "catalog:",
|
||||
"@types/node": "catalog:",
|
||||
"@vben/commitlint-config": "workspace:*",
|
||||
"@vben/eslint-config": "workspace:*",
|
||||
@ -80,10 +80,11 @@
|
||||
"autoprefixer": "catalog:",
|
||||
"cross-env": "catalog:",
|
||||
"cspell": "catalog:",
|
||||
"happy-dom": "catalog:",
|
||||
"husky": "catalog:",
|
||||
"is-ci": "catalog:",
|
||||
"jsdom": "catalog:",
|
||||
"lint-staged": "catalog:",
|
||||
"playwright": "catalog:",
|
||||
"rimraf": "catalog:",
|
||||
"tailwindcss": "catalog:",
|
||||
"turbo": "catalog:",
|
||||
@ -113,8 +114,7 @@
|
||||
},
|
||||
"neverBuiltDependencies": [
|
||||
"canvas",
|
||||
"node-gyp",
|
||||
"playwright"
|
||||
"node-gyp"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
{
|
||||
"name": "@vben-core/shadcn-ui",
|
||||
"version": "5.3.0",
|
||||
"#main": "./dist/index.mjs",
|
||||
"#module": "./dist/index.mjs",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
@ -20,16 +22,14 @@
|
||||
"sideEffects": [
|
||||
"**/*.css"
|
||||
],
|
||||
"#main": "./dist/index.mjs",
|
||||
"main": "./src/index.ts",
|
||||
"#module": "./dist/index.mjs",
|
||||
"module": "./src/index.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./src/index.ts",
|
||||
"development": "./src/index.ts",
|
||||
"//default": "./dist/index.mjs",
|
||||
"default": "./src/index.ts"
|
||||
"default": "./src/index.ts",
|
||||
"//default": "./dist/index.mjs"
|
||||
}
|
||||
},
|
||||
"publishConfig": {
|
||||
|
@ -51,6 +51,7 @@ defineExpose({
|
||||
}"
|
||||
:style="style"
|
||||
class="bg-background dark:bg-accent absolute left-0 top-0 flex h-full cursor-move items-center justify-center px-3.5 shadow-md"
|
||||
name="captcha-action"
|
||||
>
|
||||
<Slot :is-passing="isPassing" class="text-foreground/60 size-4">
|
||||
<slot name="icon">
|
||||
|
@ -95,6 +95,7 @@ function goToLogin() {
|
||||
:class="{
|
||||
'cursor-wait': loading,
|
||||
}"
|
||||
aria-label="submit"
|
||||
class="mt-2 w-full"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
|
@ -137,6 +137,7 @@ defineExpose({ setFieldValue });
|
||||
'cursor-wait': loading,
|
||||
}"
|
||||
:loading="loading"
|
||||
aria-label="login"
|
||||
class="w-full"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
|
@ -97,6 +97,7 @@ function goToLogin() {
|
||||
'cursor-wait': loading,
|
||||
}"
|
||||
:loading="loading"
|
||||
aria-label="register"
|
||||
class="mt-2 w-full"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
|
@ -30,16 +30,21 @@ const props = withDefaults(
|
||||
},
|
||||
);
|
||||
|
||||
const keyword = ref('');
|
||||
const searchInputRef = ref<HTMLInputElement>();
|
||||
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
onCancel() {
|
||||
modalApi.close();
|
||||
},
|
||||
onOpenChange(isOpen: boolean) {
|
||||
if (!isOpen) {
|
||||
keyword.value = '';
|
||||
}
|
||||
},
|
||||
});
|
||||
const open = modalApi.useStore((state) => state.isOpen);
|
||||
|
||||
const keyword = ref('');
|
||||
const searchInputRef = ref<HTMLInputElement>();
|
||||
|
||||
function handleClose() {
|
||||
modalApi.close();
|
||||
keyword.value = '';
|
||||
|
20
playground/__tests__/e2e/auth-login.spec.ts
Normal file
20
playground/__tests__/e2e/auth-login.spec.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
import { authLogin } from './common/auth';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/');
|
||||
});
|
||||
|
||||
test.describe('Auth Login Page Tests', () => {
|
||||
test('check title and page elements', async ({ page }) => {
|
||||
// 获取页面标题并断言标题包含 'Vben Admin'
|
||||
const title = await page.title();
|
||||
expect(title).toContain('Vben Admin');
|
||||
});
|
||||
|
||||
// 测试用例: 成功登录
|
||||
test('should successfully login with valid credentials', async ({ page }) => {
|
||||
await authLogin(page);
|
||||
});
|
||||
});
|
46
playground/__tests__/e2e/common/auth.ts
Normal file
46
playground/__tests__/e2e/common/auth.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
export async function authLogin(page: Page) {
|
||||
// 确保登录表单正常
|
||||
const usernameInput = await page.locator(`input[name='username']`);
|
||||
await expect(usernameInput).toBeVisible();
|
||||
|
||||
const passwordInput = await page.locator(`input[name='password']`);
|
||||
await expect(passwordInput).toBeVisible();
|
||||
|
||||
const sliderCaptcha = await page.locator(`div[name='captcha']`);
|
||||
const sliderCaptchaAction = await page.locator(`div[name='captcha-action']`);
|
||||
await expect(sliderCaptcha).toBeVisible();
|
||||
await expect(sliderCaptchaAction).toBeVisible();
|
||||
|
||||
// 拖动验证码滑块
|
||||
// 获取拖动按钮的位置
|
||||
const sliderCaptchaBox = await sliderCaptcha.boundingBox();
|
||||
if (!sliderCaptchaBox) throw new Error('滑块未找到');
|
||||
|
||||
const actionBoundingBox = await sliderCaptchaAction.boundingBox();
|
||||
if (!actionBoundingBox) throw new Error('要拖动的按钮未找到');
|
||||
|
||||
// 计算起始位置和目标位置
|
||||
const startX = actionBoundingBox.x + actionBoundingBox.width / 2; // div 中心的 x 坐标
|
||||
const startY = actionBoundingBox.y + actionBoundingBox.height / 2; // div 中心的 y 坐标
|
||||
|
||||
const targetX = startX + sliderCaptchaBox.width + actionBoundingBox.width; // 向右拖动容器的宽度
|
||||
const targetY = startY; // y 坐标保持不变
|
||||
|
||||
// 模拟鼠标拖动
|
||||
await page.mouse.move(startX, startY); // 移动到 action 的中心
|
||||
await page.mouse.down(); // 按下鼠标
|
||||
await page.mouse.move(targetX, targetY, { steps: 20 }); // 拖动到目标位置
|
||||
await page.mouse.up(); // 松开鼠标
|
||||
|
||||
// 在拖动后进行断言,检查action是否在预期位置,
|
||||
const newActionBoundingBox = await sliderCaptchaAction.boundingBox();
|
||||
expect(newActionBoundingBox?.x).toBeGreaterThan(actionBoundingBox.x);
|
||||
|
||||
// 到这里已经校验成功,点击进行登录
|
||||
await page.waitForTimeout(300);
|
||||
await page.getByRole('button', { name: 'login' }).click();
|
||||
}
|
@ -20,7 +20,10 @@
|
||||
"build:analyze": "pnpm vite build --mode analyze",
|
||||
"dev": "pnpm vite --mode development",
|
||||
"preview": "vite preview",
|
||||
"typecheck": "vue-tsc --noEmit --skipLibCheck"
|
||||
"typecheck": "vue-tsc --noEmit --skipLibCheck",
|
||||
"test:e2e": "playwright test",
|
||||
"test:e2e-ui": "playwright test --ui",
|
||||
"test:e2e-codegen": "playwright codegen"
|
||||
},
|
||||
"imports": {
|
||||
"#/*": "./src/*"
|
||||
|
108
playground/playwright.config.ts
Normal file
108
playground/playwright.config.ts
Normal file
@ -0,0 +1,108 @@
|
||||
import type { PlaywrightTestConfig } from '@playwright/test';
|
||||
|
||||
import { devices } from '@playwright/test';
|
||||
|
||||
/**
|
||||
* Read environment variables from file.
|
||||
* https://github.com/motdotla/dotenv
|
||||
*/
|
||||
// require('dotenv').config();
|
||||
|
||||
/**
|
||||
* See https://playwright.dev/docs/test-configuration.
|
||||
*/
|
||||
const config: PlaywrightTestConfig = {
|
||||
expect: {
|
||||
/**
|
||||
* Maximum time expect() should wait for the condition to be met.
|
||||
* For example in `await expect(locator).toHaveText();`
|
||||
*/
|
||||
timeout: 5000,
|
||||
},
|
||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||
forbidOnly: !!process.env.CI,
|
||||
/* Folder for test artifacts such as screenshots, videos, traces, etc. */
|
||||
outputDir: 'node_modules/.e2e/test-results/',
|
||||
/* Configure projects for major browsers */
|
||||
projects: [
|
||||
{
|
||||
name: 'chromium',
|
||||
use: {
|
||||
...devices['Desktop Chrome'],
|
||||
},
|
||||
},
|
||||
// {
|
||||
// name: 'firefox',
|
||||
// use: {
|
||||
// ...devices['Desktop Firefox'],
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: 'webkit',
|
||||
// use: {
|
||||
// ...devices['Desktop Safari'],
|
||||
// },
|
||||
// },
|
||||
|
||||
/* Test against mobile viewports. */
|
||||
// {
|
||||
// name: 'Mobile Chrome',
|
||||
// use: {
|
||||
// ...devices['Pixel 5'],
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: 'Mobile Safari',
|
||||
// use: {
|
||||
// ...devices['iPhone 12'],
|
||||
// },
|
||||
// },
|
||||
|
||||
/* Test against branded browsers. */
|
||||
// {
|
||||
// name: 'Microsoft Edge',
|
||||
// use: {
|
||||
// channel: 'msedge',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: 'Google Chrome',
|
||||
// use: {
|
||||
// channel: 'chrome',
|
||||
// },
|
||||
// },
|
||||
],
|
||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||
reporter: [
|
||||
['list'],
|
||||
['html', { outputFolder: 'node_modules/.e2e/test-results' }],
|
||||
],
|
||||
/* Retry on CI only */
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
testDir: './__tests__/e2e',
|
||||
/* Maximum time one test can run for. */
|
||||
timeout: 30 * 1000,
|
||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||
use: {
|
||||
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
|
||||
actionTimeout: 0,
|
||||
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||
baseURL: 'http://localhost:5555',
|
||||
/* Only on CI systems run the tests headless */
|
||||
headless: !!process.env.CI,
|
||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||
trace: 'retain-on-failure',
|
||||
},
|
||||
|
||||
/* Run your local dev server before starting the tests */
|
||||
webServer: {
|
||||
command: process.env.CI ? 'pnpm preview --port 5555' : 'pnpm dev',
|
||||
port: 5555,
|
||||
reuseExistingServer: !process.env.CI,
|
||||
},
|
||||
|
||||
/* Opt out of parallel tests on CI. */
|
||||
workers: process.env.CI ? 1 : undefined,
|
||||
};
|
||||
|
||||
export default config;
|
373
pnpm-lock.yaml
373
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
@ -29,6 +29,7 @@ catalog:
|
||||
'@jspm/generator': ^2.3.1
|
||||
'@manypkg/get-packages': ^2.2.2
|
||||
'@nolebase/vitepress-plugin-git-changelog': ^2.5.0
|
||||
'@playwright/test': ^1.47.2
|
||||
'@radix-icons/vue': ^1.0.0
|
||||
'@stylistic/stylelint-plugin': ^3.0.1
|
||||
'@tailwindcss/nesting': 0.0.0-insiders.565cd3e
|
||||
@ -39,7 +40,6 @@ catalog:
|
||||
'@types/chalk': ^2.2.0
|
||||
'@types/eslint': ^9.6.1
|
||||
'@types/html-minifier-terser': ^7.0.2
|
||||
'@types/jsdom': ^21.1.7
|
||||
'@types/jsonwebtoken': ^9.0.7
|
||||
'@types/lodash.clonedeep': ^4.5.9
|
||||
'@types/node': ^22.5.5
|
||||
@ -103,10 +103,10 @@ catalog:
|
||||
get-port: ^7.1.0
|
||||
globals: ^15.9.0
|
||||
h3: ^1.12.0
|
||||
happy-dom: ^15.7.4
|
||||
html-minifier-terser: ^7.2.0
|
||||
husky: ^9.1.6
|
||||
is-ci: ^3.0.1
|
||||
jsdom: ^25.0.1
|
||||
jsonc-eslint-parser: ^2.4.0
|
||||
jsonwebtoken: ^9.0.2
|
||||
lint-staged: ^15.2.10
|
||||
@ -121,6 +121,7 @@ catalog:
|
||||
pinia: 2.2.2
|
||||
pinia-plugin-persistedstate: ^4.0.2
|
||||
pkg-types: ^1.2.0
|
||||
playwright: ^1.47.2
|
||||
postcss: ^8.4.47
|
||||
postcss-antd-fixes: ^0.2.0
|
||||
postcss-html: ^1.7.0
|
||||
|
@ -33,6 +33,7 @@
|
||||
"stub": {
|
||||
"cache": false
|
||||
},
|
||||
"test:e2e": {},
|
||||
"dev": {
|
||||
"dependsOn": [],
|
||||
"outputs": [],
|
||||
|
@ -1,10 +1,11 @@
|
||||
import Vue from '@vitejs/plugin-vue';
|
||||
import VueJsx from '@vitejs/plugin-vue-jsx';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
import { configDefaults, defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [Vue(), VueJsx()],
|
||||
test: {
|
||||
environment: 'jsdom',
|
||||
environment: 'happy-dom',
|
||||
exclude: [...configDefaults.exclude, '**/e2e/**'],
|
||||
},
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user