From 823582cc7901bc4ff5b2686ad3f47d14d7ecb9fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?wifi=E6=AD=AAf?= <1402772884@qq.com> Date: Thu, 20 Feb 2025 17:49:52 +0800 Subject: [PATCH] =?UTF-8?q?test(mini-markdown-editor):=20=E7=AB=AF?= =?UTF-8?q?=E5=88=B0=E7=AB=AF=E6=B5=8B=E8=AF=95=E7=8E=AF=E5=A2=83=E6=90=AD?= =?UTF-8?q?=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/mini-markdown-editor/.gitignore | 5 +- packages/mini-markdown-editor/README.md | 5 ++ packages/mini-markdown-editor/package.json | 15 ++-- .../mini-markdown-editor/playwright.config.ts | 45 +++++++++++ .../mini-markdown-editor/test/e2e/README.md | 27 +++++++ ...13\350\257\225\347\216\257\345\242\203.md" | 77 +++++++++++++++++++ .../test/e2e/editor.test.ts | 49 ++++++++++++ .../test/setup.ts => test/unit/unit-setup.ts} | 0 .../mini-markdown-editor/tsconfig.app.json | 2 +- packages/mini-markdown-editor/vite.config.ts | 7 +- pnpm-lock.yaml | 38 ++++++++- 11 files changed, 259 insertions(+), 11 deletions(-) create mode 100644 packages/mini-markdown-editor/playwright.config.ts create mode 100644 packages/mini-markdown-editor/test/e2e/README.md create mode 100644 "packages/mini-markdown-editor/test/e2e/docs/\345\246\202\344\275\225\346\220\255\345\273\272Playwright\346\265\213\350\257\225\347\216\257\345\242\203.md" create mode 100644 packages/mini-markdown-editor/test/e2e/editor.test.ts rename packages/mini-markdown-editor/{src/test/setup.ts => test/unit/unit-setup.ts} (100%) diff --git a/packages/mini-markdown-editor/.gitignore b/packages/mini-markdown-editor/.gitignore index 2ce4953..c65d0ef 100644 --- a/packages/mini-markdown-editor/.gitignore +++ b/packages/mini-markdown-editor/.gitignore @@ -22,4 +22,7 @@ dist-ssr *.njsproj *.sln *.sw? -coverage \ No newline at end of file +coverage + +test-results +playwright-report \ No newline at end of file diff --git a/packages/mini-markdown-editor/README.md b/packages/mini-markdown-editor/README.md index 67f4156..d224f19 100644 --- a/packages/mini-markdown-editor/README.md +++ b/packages/mini-markdown-editor/README.md @@ -37,4 +37,9 @@ pnpm test:watch ## 测试覆盖率 pnpm coverage + +# e2e 测试 +pnpm e2e +pnpm e2e:ui +pnpm e2e:debug ``` diff --git a/packages/mini-markdown-editor/package.json b/packages/mini-markdown-editor/package.json index 8e96ddf..789c47c 100644 --- a/packages/mini-markdown-editor/package.json +++ b/packages/mini-markdown-editor/package.json @@ -42,7 +42,10 @@ "preview": "vite preview", "test": "vitest", "test:watch": "vitest --watch", - "coverage": "vitest run --coverage" + "coverage": "vitest run --coverage", + "e2e": "playwright test", + "e2e:ui": "playwright test --ui", + "e2e:debug": "playwright test --debug" }, "dependencies": { "@emoji-mart/data": "^1.2.1", @@ -51,12 +54,12 @@ "antd": "^5.23.2", "emoji-mart": "^5.6.0", "events": "^3.3.0", + "highlight.js": "^11.11.1", "html2pdf.js": "^0.10.2", "immer": "^10.1.1", "nanoid": "^5.0.9", "react-hotkeys-hook": "^4.6.1", - "zustand": "^5.0.3", - "highlight.js": "^11.11.1" + "zustand": "^5.0.3" }, "devDependencies": { "@codemirror/commands": "^6.8.0", @@ -64,6 +67,7 @@ "@codemirror/language-data": "^6.5.1", "@eslint/js": "^9.17.0", "@mini-markdown-rc/ast-parser": "workspace:*", + "@playwright/test": "^1.50.1", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.2.0", @@ -79,6 +83,7 @@ "eslint-plugin-react-refresh": "^0.4.16", "globals": "^15.14.0", "jsdom": "^26.0.0", + "playwright": "^1.50.1", "react": "^18.3.1", "react-dom": "^18.3.1", "styled-components": "^6.1.14", @@ -94,8 +99,8 @@ "@codemirror/language-data": "^6.5.1", "@uiw/codemirror-extensions-events": "^4.23.7", "@uiw/react-codemirror": "^4.23.7", + "highlight.js": "^11.11.1", "react": "^18.3.1", - "react-dom": "^18.3.1", - "highlight.js": "^11.11.1" + "react-dom": "^18.3.1" } } \ No newline at end of file diff --git a/packages/mini-markdown-editor/playwright.config.ts b/packages/mini-markdown-editor/playwright.config.ts new file mode 100644 index 0000000..c4280fb --- /dev/null +++ b/packages/mini-markdown-editor/playwright.config.ts @@ -0,0 +1,45 @@ +import { defineConfig, devices } from "@playwright/test"; + +export default defineConfig({ + name: "editor-e2e-test", + testDir: "./test/e2e", + fullyParallel: true, // 运行所有测试文件,而不仅仅是当前文件 + /** + * .only 表示只有 "test case 2" 才会运行,其他用例不会运行 + * test.only('test case 2', async ({ page }) => { + await page.goto('http://example.com'); + await expect(page).toHaveTitle('Example Domain'); + }); + */ + forbidOnly: !!process.env.CI, // 禁止使用 .only 标记,确保所有测试都能被完整执行 + retries: process.env.CI ? 2 : 0, // 在 CI 环境下重试失败的测试用例两次 + workers: process.env.CI ? 1 : undefined, // 在 CI 环境下使用 1 个 worker,避免资源冲突 + reporter: "html", // 生成 HTML 报告 + use: { + // 浏览器配置 + baseURL: "http://localhost:5173", + headless: true, // 在 CI 环境下使用无头浏览器,提高性能 + trace: "on-first-retry", // 在 CI 环境下生成 trace 文件,用于调试 + }, + projects: [ + // 配置多个浏览器环境 + { + name: "chromium", + use: { ...devices["Desktop Chrome"] }, // devices 一个预定义的设备配置集合,包含了各种常见浏览器和设备的配置 + }, + // { + // name: "firefox", + // use: { ...devices["Desktop Firefox"] }, + // }, + // { + // name: "webkit", + // use: { ...devices["Desktop Safari"] }, + // }, + ], + webServer: { + // 启动一个本地服务器,用于提供测试数据 + command: "pnpm dev", // 启动命令 + port: 5173, + reuseExistingServer: !process.env.CI, // 避免在CI中重复启动服务器 + }, +}); diff --git a/packages/mini-markdown-editor/test/e2e/README.md b/packages/mini-markdown-editor/test/e2e/README.md new file mode 100644 index 0000000..a4c807b --- /dev/null +++ b/packages/mini-markdown-editor/test/e2e/README.md @@ -0,0 +1,27 @@ +# e2e 端到端测试 + +## 如何运行 + +```bash +# 运行所有端到端测试 +pnpm e2e +# 运行 UI 端到端测试 +pnpm e2e:ui +# 调试模式运行测试 +pnpm e2e:debug +``` + +> 注意:测试端口为`5173` + +`e2e` 和 `e2e:ui` 的区别: + +e2e: +- 在命令行中运行所有 E2E 测试,输出结果到终端。 +- 适合在 CI/CD 环境或自动化脚本中使用,不需要图形界面。 + +e2e:ui: +- 启动 Playwright 的 UI 测试运行器,提供图形化界面来管理和运行测试。 + +## 如何搭建Playwright测试环境? + +[如何搭建Playwright测试环境](./docs/如何搭建Playwright测试环境.md) \ No newline at end of file diff --git "a/packages/mini-markdown-editor/test/e2e/docs/\345\246\202\344\275\225\346\220\255\345\273\272Playwright\346\265\213\350\257\225\347\216\257\345\242\203.md" "b/packages/mini-markdown-editor/test/e2e/docs/\345\246\202\344\275\225\346\220\255\345\273\272Playwright\346\265\213\350\257\225\347\216\257\345\242\203.md" new file mode 100644 index 0000000..6847896 --- /dev/null +++ "b/packages/mini-markdown-editor/test/e2e/docs/\345\246\202\344\275\225\346\220\255\345\273\272Playwright\346\265\213\350\257\225\347\216\257\345\242\203.md" @@ -0,0 +1,77 @@ +# e2e 端到端测试 + +## 步骤 + +### 一、创建项目 + +> 核心包:`playwright` 和 `@playwright/test` + +```bash +# 会下载浏览器内核 +npm init playwright +``` + +### 二、手动创建 + +1. 安装依赖 + +```bash +pnpm add -D playwright @playwright/test +``` + +2. 初始化 `Playwright` 配置 + +```bash +# 会下载浏览器内核 +npx playwright install +``` + +3. 创建 Playwright 配置文件(`playwright.config.ts`) + +```ts +import { defineConfig, devices } from '@playwright/test'; + +export default defineConfig({ + testDir: './e2e', + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + workers: process.env.CI ? 1 : undefined, + reporter: 'html', + use: { + baseURL: 'http://localhost:5173', + trace: 'on-first-retry', + }, + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + ], + webServer: { + command: 'pnpm dev', + port: 5173, + reuseExistingServer: !process.env.CI, + }, +}); +``` + +### 三、运行测试 + +```bash +npx playwright test +npx playwright test --ui +npx playwright test --debug +``` + +### 四、VSCode 中运行测试 + +安装插件:`Playwright Test for VSCode` diff --git a/packages/mini-markdown-editor/test/e2e/editor.test.ts b/packages/mini-markdown-editor/test/e2e/editor.test.ts new file mode 100644 index 0000000..0abbc3d --- /dev/null +++ b/packages/mini-markdown-editor/test/e2e/editor.test.ts @@ -0,0 +1,49 @@ +import { test, expect } from "@playwright/test"; + +test.describe("Markdown Editor E2E Tests", () => { + test.beforeEach(async ({ page }) => { + await page.goto("/"); + }); + + test("基础编辑功能测试", async ({ page }) => { + // 测试编辑器是否正确加载 + await expect(page.locator(".markdown-editor-content")).toBeVisible(); + + // 测试输入文本 + const editor = page.locator(".markdown-editor-content"); + await editor.click(); + await page.keyboard.type("# Hello World"); + + // 验证预览区域是否正确渲染 + await expect(page.locator(".markdown-editor-preview h1")).toContainText("Hello World"); + }); + + // test('工具栏功能测试', async ({ page }) => { + // const editor = page.locator('.markdown-editor-content'); + // await editor.click(); + + // // 测试加粗功能 + // await page.getByRole('button', { name: '加粗' }).click(); + // await page.keyboard.type('Bold Text'); + // await expect(editor).toContainText('**Bold Text**'); + // }); + + // test('主题切换测试', async ({ page }) => { + // // 切换到暗色主题 + // await page.getByRole('button', { name: '主题切换light' }).click(); + // await expect(page.locator('body')).toHaveClass(/dark/); + // }); + + // test('文件导出测试', async ({ page }) => { + // // 输入一些内容 + // const editor = page.locator('.markdown-editor-content'); + // await editor.click(); + // await page.keyboard.type('# Test Export'); + + // // 点击导出按钮 + // await page.getByRole('button', { name: '导出' }).click(); + + // // 验证导出对话框是否出现 + // await expect(page.getByText('导出文件类型')).toBeVisible(); + // }); +}); diff --git a/packages/mini-markdown-editor/src/test/setup.ts b/packages/mini-markdown-editor/test/unit/unit-setup.ts similarity index 100% rename from packages/mini-markdown-editor/src/test/setup.ts rename to packages/mini-markdown-editor/test/unit/unit-setup.ts diff --git a/packages/mini-markdown-editor/tsconfig.app.json b/packages/mini-markdown-editor/tsconfig.app.json index 223357c..f1a7504 100644 --- a/packages/mini-markdown-editor/tsconfig.app.json +++ b/packages/mini-markdown-editor/tsconfig.app.json @@ -28,5 +28,5 @@ "@/*": ["./src/*"] } }, - "include": ["src"] + "include": ["src", "test"] } diff --git a/packages/mini-markdown-editor/vite.config.ts b/packages/mini-markdown-editor/vite.config.ts index 362ecdd..40c3739 100644 --- a/packages/mini-markdown-editor/vite.config.ts +++ b/packages/mini-markdown-editor/vite.config.ts @@ -1,5 +1,5 @@ /// -//^与测试用同一配置 +// 与测试用同一配置 import { defineConfig, PluginOption } from "vite"; import react from "@vitejs/plugin-react"; @@ -46,11 +46,12 @@ export default defineConfig(({ mode }) => { }, }, - //测试 + // 单元测试 test: { + name: "editor-unit-test", environment: "jsdom", globals: true, - setupFiles: "./src/test/setup.ts", + setupFiles: "./test/unit/unit-setup.ts", include: ["src/**/*.{test,spec}.{js,ts,jsx,tsx}"], coverage: { include: ["src/components/**", "src/hooks/**", "src/utils/**", "src/store/**"], diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 852c5a0..c004857 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -91,6 +91,7 @@ importers: '@emoji-mart/react': ^1.1.1 '@eslint/js': ^9.17.0 '@mini-markdown-rc/ast-parser': workspace:* + '@playwright/test': ^1.50.1 '@testing-library/dom': ^10.4.0 '@testing-library/jest-dom': ^6.6.3 '@testing-library/react': ^16.2.0 @@ -114,6 +115,7 @@ importers: immer: ^10.1.1 jsdom: ^26.0.0 nanoid: ^5.0.9 + playwright: ^1.50.1 react: ^18.3.1 react-dom: ^18.3.1 react-hotkeys-hook: ^4.6.1 @@ -143,6 +145,7 @@ importers: '@codemirror/language-data': 6.5.1 '@eslint/js': 9.20.0 '@mini-markdown-rc/ast-parser': link:../mini-markdown-ast-parser + '@playwright/test': 1.50.1 '@testing-library/dom': 10.4.0 '@testing-library/jest-dom': 6.6.3 '@testing-library/react': 16.2.0_inz42gi7k5vot3il2lm5miuvfu @@ -158,6 +161,7 @@ importers: eslint-plugin-react-refresh: 0.4.19_eslint@9.18.0 globals: 15.15.0 jsdom: 26.0.0 + playwright: 1.50.1 react: 18.3.1 react-dom: 18.3.1_react@18.3.1 styled-components: 6.1.15_nnrd3gsncyragczmpvfhocinkq @@ -2175,6 +2179,14 @@ packages: dev: true optional: true + /@playwright/test/1.50.1: + resolution: {integrity: sha512-Jii3aBg+CEDpgnuDxEp/h7BimHcUTDlpEtce89xEumlJ5ef2hqepZ+PWp1DDpYC/VO9fmWVI1IlEaoI5fK9FXQ==} + engines: {node: '>=18'} + hasBin: true + dependencies: + playwright: 1.50.1 + dev: true + /@rc-component/async-validator/5.0.4: resolution: {integrity: sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==} engines: {node: '>=14.x'} @@ -3503,7 +3515,7 @@ packages: '@babel/plugin-transform-react-jsx-source': 7.25.9_@babel+core@7.26.9 '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 6.1.0_sass@1.85.0 + vite: 6.1.0 transitivePeerDependencies: - supports-color dev: true @@ -5679,6 +5691,14 @@ packages: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} dev: true + /fsevents/2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + /fsevents/2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -8398,6 +8418,22 @@ packages: pathe: 2.0.3 dev: true + /playwright-core/1.50.1: + resolution: {integrity: sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ==} + engines: {node: '>=18'} + hasBin: true + dev: true + + /playwright/1.50.1: + resolution: {integrity: sha512-G8rwsOQJ63XG6BbKj2w5rHeavFjy5zynBA9zsJMMtBoe/Uf757oG12NXz6e6OirF7RCrTVAKFXbLmn1RbL7Qaw==} + engines: {node: '>=18'} + hasBin: true + dependencies: + playwright-core: 1.50.1 + optionalDependencies: + fsevents: 2.3.2 + dev: true + /possible-typed-array-names/1.1.0: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} -- Gitee