|
|
@@ -1,7 +1,9 @@
|
|
|
import { JSDOM } from 'jsdom'
|
|
|
import React from 'react'
|
|
|
-import {render, fireEvent, within, screen, waitFor} from '@testing-library/react'
|
|
|
+import {render, fireEvent, within, screen, waitFor, configure} from '@testing-library/react'
|
|
|
+import {userEvent} from '@testing-library/user-event'
|
|
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
|
+import { createBrowserRouter, RouterProvider, Navigate } from 'react-router'
|
|
|
import {
|
|
|
assertEquals,
|
|
|
assertExists,
|
|
|
@@ -12,25 +14,72 @@ import {
|
|
|
import axios from 'axios';
|
|
|
import { KnowInfoPage } from "./pages_know_info.tsx"
|
|
|
import { AuthProvider } from './hooks_sys.tsx'
|
|
|
+import { ProtectedRoute } from './components_protected_route.tsx'
|
|
|
+
|
|
|
+// 拦截React DOM中的attachEvent和detachEvent错误
|
|
|
+const originalError = console.error;
|
|
|
+console.error = (...args) => {
|
|
|
+ // 过滤掉attachEvent和detachEvent相关的错误
|
|
|
+ if (args[0] instanceof Error) {
|
|
|
+ if (args[0].message?.includes('attachEvent is not a function') ||
|
|
|
+ args[0].message?.includes('detachEvent is not a function')) {
|
|
|
+ return; // 不输出这些错误
|
|
|
+ }
|
|
|
+ } else if (typeof args[0] === 'string') {
|
|
|
+ if (args[0].includes('attachEvent is not a function') ||
|
|
|
+ args[0].includes('detachEvent is not a function')) {
|
|
|
+ return; // 不输出这些错误
|
|
|
+ }
|
|
|
+ }
|
|
|
+ originalError(...args);
|
|
|
+};
|
|
|
+
|
|
|
+// // 配置Testing Library的eventWrapper来处理这个问题
|
|
|
+// configure({
|
|
|
+// eventWrapper: (cb) => {
|
|
|
+// try {
|
|
|
+// return cb();
|
|
|
+// } catch (error) {
|
|
|
+// console.log('eventWrapper', cb)
|
|
|
+// // 忽略attachEvent和detachEvent相关的错误
|
|
|
+// if (error instanceof Error &&
|
|
|
+// (error.message?.includes('attachEvent is not a function') ||
|
|
|
+// error.message?.includes('detachEvent is not a function'))) {
|
|
|
+// // 忽略这个错误并返回一个默认值
|
|
|
+// return undefined;
|
|
|
+// }
|
|
|
+// // 其他错误正常抛出
|
|
|
+// throw error;
|
|
|
+// }
|
|
|
+// }
|
|
|
+// });
|
|
|
|
|
|
const queryClient = new QueryClient()
|
|
|
|
|
|
const dom = new JSDOM(`<body></body>`, {
|
|
|
runScripts: "dangerously",
|
|
|
pretendToBeVisual: true,
|
|
|
- url: "http://localhost"
|
|
|
+ url: "http://localhost",
|
|
|
});
|
|
|
|
|
|
// 模拟浏览器环境
|
|
|
globalThis.window = dom.window;
|
|
|
globalThis.document = dom.window.document;
|
|
|
|
|
|
+// 添加必要的 DOM 配置
|
|
|
+globalThis.Node = dom.window.Node;
|
|
|
+globalThis.Document = dom.window.Document;
|
|
|
+globalThis.HTMLInputElement = dom.window.HTMLInputElement;
|
|
|
+globalThis.HTMLButtonElement = dom.window.HTMLButtonElement;
|
|
|
+
|
|
|
// 定义浏览器环境所需的类
|
|
|
globalThis.Element = dom.window.Element;
|
|
|
globalThis.HTMLElement = dom.window.HTMLElement;
|
|
|
globalThis.ShadowRoot = dom.window.ShadowRoot;
|
|
|
globalThis.SVGElement = dom.window.SVGElement;
|
|
|
|
|
|
+
|
|
|
+
|
|
|
// 模拟 getComputedStyle
|
|
|
globalThis.getComputedStyle = (elt) => {
|
|
|
const style = new dom.window.CSSStyleDeclaration();
|
|
|
@@ -72,6 +121,22 @@ axios.defaults.baseURL = 'https://23957.dev.d8dcloud.com'
|
|
|
|
|
|
const customScreen = within(document.body);
|
|
|
|
|
|
+// 应用入口组件
|
|
|
+const App = () => {
|
|
|
+ // 路由配置
|
|
|
+ const router = createBrowserRouter([
|
|
|
+ {
|
|
|
+ path: '/',
|
|
|
+ element: (
|
|
|
+ <ProtectedRoute>
|
|
|
+ <KnowInfoPage />
|
|
|
+ </ProtectedRoute>
|
|
|
+ )
|
|
|
+ },
|
|
|
+ ]);
|
|
|
+ return <RouterProvider router={router} />
|
|
|
+};
|
|
|
+
|
|
|
// 使用异步测试处理组件渲染
|
|
|
Deno.test({
|
|
|
name: '知识库管理页面测试',
|
|
|
@@ -105,6 +170,8 @@ Deno.test({
|
|
|
globalThis.setInterval = originalSetInterval;
|
|
|
};
|
|
|
|
|
|
+
|
|
|
+
|
|
|
try {
|
|
|
// 渲染组件
|
|
|
const {
|
|
|
@@ -113,79 +180,116 @@ Deno.test({
|
|
|
} = render(
|
|
|
<QueryClientProvider client={queryClient}>
|
|
|
<AuthProvider>
|
|
|
- <KnowInfoPage />
|
|
|
+ <App />
|
|
|
</AuthProvider>
|
|
|
</QueryClientProvider>
|
|
|
);
|
|
|
|
|
|
// 测试1: 基本渲染
|
|
|
await t.step('应正确渲染页面元素', async () => {
|
|
|
- const title = await findByText(/知识库管理/i);
|
|
|
- assertExists(title, '未找到知识库管理标题');
|
|
|
+ await waitFor(async () => {
|
|
|
+ const title = await findByText(/知识库管理/i);
|
|
|
+ assertExists(title, '未找到知识库管理标题');
|
|
|
+ }, {
|
|
|
+ timeout: 1000 * 5,
|
|
|
+ });
|
|
|
});
|
|
|
|
|
|
- let i = 0
|
|
|
-
|
|
|
// 初始加载表格数据
|
|
|
- await waitFor(async () => {
|
|
|
- const table = await findByRole('table');
|
|
|
- const rows = await within(table).findAllByRole('row');
|
|
|
-
|
|
|
- // debug(rows[1])
|
|
|
- i++
|
|
|
- console.log('i', i)
|
|
|
- console.log('rows', rows.length)
|
|
|
+ await t.step('初始加载表格数据', async () => {
|
|
|
+ await waitFor(async () => {
|
|
|
+ const table = await findByRole('table');
|
|
|
+ const rows = await within(table).findAllByRole('row');
|
|
|
|
|
|
- // 应该大于2行
|
|
|
- // assert(rows.length > 2, '表格没有数据'); // 1是表头行 2是数据行
|
|
|
-
|
|
|
- if (rows.length <= 2) {
|
|
|
- throw new Error('表格没有数据');
|
|
|
- }
|
|
|
- }, {
|
|
|
- timeout: 1000 * 10,
|
|
|
+ // 应该大于2行
|
|
|
+ assert(rows.length > 2, '表格没有数据'); // 1是表头行 2是数据行
|
|
|
+
|
|
|
+ }, {
|
|
|
+ timeout: 1000 * 5,
|
|
|
+ });
|
|
|
});
|
|
|
|
|
|
// 测试2: 搜索表单功能
|
|
|
await t.step('搜索表单应正常工作', async () => {
|
|
|
+ // 确保在正确的测试环境中设置 userEvent
|
|
|
+ const user = userEvent.setup({
|
|
|
+ document: dom.window.document,
|
|
|
+ delay: 0
|
|
|
+ });
|
|
|
+
|
|
|
const searchInput = await findByPlaceholderText(/请输入文章标题/i) as HTMLInputElement;
|
|
|
const searchButton = await findByText(/搜 索/i);
|
|
|
+
|
|
|
+ assertExists(searchInput, '未找到搜索输入框');
|
|
|
+ assertExists(searchButton, '未找到搜索按钮');
|
|
|
|
|
|
// 输入搜索内容
|
|
|
- fireEvent.change(searchInput, { target: { value: '数据分析' } });
|
|
|
+ try {
|
|
|
+ await user.type(searchInput, '数据分析')
|
|
|
+ } catch (error: unknown) {
|
|
|
+ // console.error('输入搜索内容失败', error)
|
|
|
+ }
|
|
|
assertEquals(searchInput.value, '数据分析', '搜索输入框值未更新');
|
|
|
+
|
|
|
+ console.log('searchInput', searchInput.value)
|
|
|
+
|
|
|
+ debug(searchInput)
|
|
|
+ debug(searchButton)
|
|
|
|
|
|
// 提交搜索
|
|
|
- fireEvent.click(searchButton);
|
|
|
+ try {
|
|
|
+ await user.click(searchButton);
|
|
|
+ } catch (error: unknown) {
|
|
|
+ // console.error('点击搜索按钮失败', error)
|
|
|
+ }
|
|
|
|
|
|
- // // 验证是否触发了搜索
|
|
|
- // await waitFor(() => {
|
|
|
- // const loading = queryByText(/正在加载数据/i);
|
|
|
- // assertNotEquals(loading, null, '搜索未触发加载状态');
|
|
|
- // });
|
|
|
|
|
|
- // 等待搜索结果并验证
|
|
|
- await waitFor(async () => {
|
|
|
- const table = await findByRole('table');
|
|
|
- const rows = await within(table).findAllByRole('row');
|
|
|
+ let rows: HTMLElement[] = [];
|
|
|
|
|
|
- debug(rows)
|
|
|
+
|
|
|
+ const table = await findByRole('table');
|
|
|
+ assertExists(table, '未找到数据表格');
|
|
|
|
|
|
- console.log('rows', rows.length);
|
|
|
-
|
|
|
- // 检查至少有一行包含"数据分析"
|
|
|
- const hasMatch = rows.some(async row => {
|
|
|
- const cells = await within(row).findAllByRole('cell');
|
|
|
- return cells.some(cell => cell.textContent?.includes('数据分析'));
|
|
|
- });
|
|
|
+ // 等待表格刷新并验证
|
|
|
+ await waitFor(async () => {
|
|
|
+ rows = await within(table).findAllByRole('row');
|
|
|
+ console.log('等待表格刷新并验证', rows.length)
|
|
|
+ assert(rows.length === 2, '表格未刷新');
|
|
|
+ }, {
|
|
|
+ timeout: 1000 * 5,
|
|
|
+ onTimeout: () => new Error('等待表格刷新超时')
|
|
|
+ });
|
|
|
|
|
|
- console.log('hasMatch', hasMatch);
|
|
|
-
|
|
|
- assert(hasMatch, '搜索结果中没有找到包含"数据分析"的文章');
|
|
|
+ // 等待搜索结果并验证
|
|
|
+ await waitFor(async () => {
|
|
|
+ rows = await within(table).findAllByRole('row');
|
|
|
+ console.log('等待搜索结果并验证', rows.length)
|
|
|
+ assert(rows.length > 2, '表格没有数据');
|
|
|
}, {
|
|
|
- timeout: 5000,
|
|
|
+ timeout: 1000 * 5,
|
|
|
onTimeout: () => new Error('等待搜索结果超时')
|
|
|
});
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // 检查至少有一行包含"数据分析"
|
|
|
+ const matchResults = await Promise.all(rows.map(async row => {
|
|
|
+ try{
|
|
|
+ const cells = await within(row).findAllByRole('cell');
|
|
|
+ return cells.some(cell => {
|
|
|
+ return cell.textContent?.includes('数据分析')
|
|
|
+ });
|
|
|
+ } catch (error: unknown) {
|
|
|
+ // console.error('搜索结果获取失败', error)
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ }))
|
|
|
+ // console.log('matchResults', matchResults)
|
|
|
+ const hasMatch = matchResults.some(result => result);
|
|
|
+
|
|
|
+ console.log('hasMatch', hasMatch)
|
|
|
+
|
|
|
+ assert(hasMatch, '搜索结果中没有找到包含"数据分析"的文章');
|
|
|
});
|
|
|
|
|
|
// 测试3: 表格数据加载
|