新增受保护路由组件以增强认证逻辑,更新知识库管理页面的测试用例以集成用户事件,提升测试的准确性和稳定性。同时,优化相关依赖项配置,确保与最新库版本兼容,提升代码可维护性和用户体验。

This commit is contained in:
zyh
2025-04-11 13:44:22 +00:00
parent c0a623bf23
commit 6d53da5880
7 changed files with 262 additions and 104 deletions

View File

@@ -0,0 +1,36 @@
import React, { useEffect } from 'react';
import {
useNavigate,
} from 'react-router';
import { useAuth } from './hooks_sys.tsx';
export const ProtectedRoute = ({ children }: { children: React.ReactNode }) => {
const { isAuthenticated, isLoading } = useAuth();
const navigate = useNavigate();
useEffect(() => {
// 只有在加载完成且未认证时才重定向
if (!isLoading && !isAuthenticated) {
navigate('/admin/login', { replace: true });
}
}, [isAuthenticated, isLoading, navigate]);
// 显示加载状态,直到认证检查完成
if (isLoading) {
return (
<div className="flex justify-center items-center h-screen">
<div className="loader ease-linear rounded-full border-4 border-t-4 border-gray-200 h-12 w-12"></div>
</div>
);
}
// 如果未认证且不再加载中,不显示任何内容(等待重定向)
if (!isAuthenticated) {
return null;
}
return children;
};

View File

@@ -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)
// 应该大于2行
// assert(rows.length > 2, '表格没有数据'); // 1是表头行 2是数据行
if (rows.length <= 2) {
throw new Error('表格没有数据');
}
}, {
timeout: 1000 * 10,
});
// 测试2: 搜索表单功能
await t.step('搜索表单应正常工作', async () => {
const searchInput = await findByPlaceholderText(/请输入文章标题/i) as HTMLInputElement;
const searchButton = await findByText(/搜 索/i);
// 输入搜索内容
fireEvent.change(searchInput, { target: { value: '数据分析' } });
assertEquals(searchInput.value, '数据分析', '搜索输入框值未更新');
// 提交搜索
fireEvent.click(searchButton);
// // 验证是否触发了搜索
// await waitFor(() => {
// const loading = queryByText(/正在加载数据/i);
// assertNotEquals(loading, null, '搜索未触发加载状态');
// });
// 等待搜索结果并验证
await t.step('初始加载表格数据', async () => {
await waitFor(async () => {
const table = await findByRole('table');
const rows = await within(table).findAllByRole('row');
debug(rows)
console.log('rows', rows.length);
// 应该大于2行
assert(rows.length > 2, '表格没有数据'); // 1是表头行 2是数据行
// 检查至少有一行包含"数据分析"
const hasMatch = rows.some(async row => {
const cells = await within(row).findAllByRole('cell');
return cells.some(cell => cell.textContent?.includes('数据分析'));
});
console.log('hasMatch', hasMatch);
assert(hasMatch, '搜索结果中没有找到包含"数据分析"的文章');
}, {
timeout: 5000,
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, '未找到搜索按钮');
// 输入搜索内容
try {
await user.type(searchInput, '数据分析')
} catch (error: unknown) {
// console.error('输入搜索内容失败', error)
}
assertEquals(searchInput.value, '数据分析', '搜索输入框值未更新');
console.log('searchInput', searchInput.value)
debug(searchInput)
debug(searchButton)
// 提交搜索
try {
await user.click(searchButton);
} catch (error: unknown) {
// console.error('点击搜索按钮失败', error)
}
let rows: HTMLElement[] = [];
const table = await findByRole('table');
assertExists(table, '未找到数据表格');
// 等待表格刷新并验证
await waitFor(async () => {
rows = await within(table).findAllByRole('row');
console.log('等待表格刷新并验证', rows.length)
assert(rows.length === 2, '表格未刷新');
}, {
timeout: 1000 * 5,
onTimeout: () => new Error('等待表格刷新超时')
});
// 等待搜索结果并验证
await waitFor(async () => {
rows = await within(table).findAllByRole('row');
console.log('等待搜索结果并验证', rows.length)
assert(rows.length > 2, '表格没有数据');
}, {
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: 表格数据加载

View File

@@ -148,6 +148,7 @@ export const KnowInfoPage = () => {
// 处理搜索
const handleSearch = async (values: any) => {
try {
console.log('handleSearch', values)
queryClient.removeQueries({ queryKey: ['knowInfos'] });
setSearchParams({
title: values.title || '',
@@ -286,7 +287,7 @@ export const KnowInfoPage = () => {
<Button type="primary" htmlType="submit">
</Button>
<Button onClick={() => {
<Button htmlType="reset" onClick={() => {
setSearchParams({
title: '',
category: '',

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect, createContext, useContext } from 'react';
import React, { useState, useEffect} from 'react';
import { createRoot } from 'react-dom/client';
import {
createBrowserRouter,
@@ -18,7 +18,6 @@ import {
Switch, Badge, Image, Upload, Divider, Descriptions,
Popconfirm, Tag, Statistic, DatePicker, Radio, Progress, Tabs, List, Alert, Collapse, Empty, Drawer
} from 'antd';
import zhCN from "antd/locale/zh_CN";
import {
MenuFoldOutlined,
MenuUnfoldOutlined,
@@ -31,8 +30,6 @@ import {
BookOutlined,
FileOutlined,
PieChartOutlined,
UploadOutlined,
GlobalOutlined,
VerticalAlignTopOutlined,
CloseOutlined,
SearchOutlined
@@ -40,27 +37,15 @@ import {
import {
QueryClient,
QueryClientProvider,
useQuery,
useMutation,
useQueryClient
} from '@tanstack/react-query';
import axios from 'axios';
import dayjs from 'dayjs';
import weekday from 'dayjs/plugin/weekday';
import localeData from 'dayjs/plugin/localeData';
import { uploadMinIOWithPolicy } from '@d8d-appcontainer/api';
import type { MinioUploadPolicy } from '@d8d-appcontainer/types';
import { Line, Pie, Column } from "@ant-design/plots";
import 'dayjs/locale/zh-cn';
import type {
GlobalConfig
} from '../share/types.ts';
import {
EnableStatus, DeleteStatus, ThemeMode, FontSize, CompactMode
} from '../share/types.ts';
import { getEnumOptions } from './utils.ts';
import {
AuthProvider,
@@ -81,7 +66,7 @@ import {ThemeSettingsPage} from './pages_theme_settings.tsx'
import { ChartDashboardPage } from './pages_chart.tsx';
import { LoginMapPage } from './pages_map.tsx';
import { LoginPage } from './pages_login_reg.tsx';
import { ProtectedRoute } from './components_protected_route.tsx';
// 配置 dayjs 插件
dayjs.extend(weekday);
@@ -440,34 +425,7 @@ const MainLayout = () => {
);
};
// 受保护的路由组件
const ProtectedRoute = ({ children }: { children: React.ReactNode }) => {
const { isAuthenticated, isLoading } = useAuth();
const navigate = useNavigate();
useEffect(() => {
// 只有在加载完成且未认证时才重定向
if (!isLoading && !isAuthenticated) {
navigate('/admin/login', { replace: true });
}
}, [isAuthenticated, isLoading, navigate]);
// 显示加载状态,直到认证检查完成
if (isLoading) {
return (
<div className="flex justify-center items-center h-screen">
<div className="loader ease-linear rounded-full border-4 border-t-4 border-gray-200 h-12 w-12"></div>
</div>
);
}
// 如果未认证且不再加载中,不显示任何内容(等待重定向)
if (!isAuthenticated) {
return null;
}
return children;
};
// 错误页面组件
const ErrorPage = () => {

View File

@@ -30,6 +30,7 @@
"@heroicons/react/24/outline": "https://esm.d8d.fun/@heroicons/react@2.1.1/24/outline?dev&deps=react@19.0.0,react-dom@19.0.0",
"@heroicons/react/24/solid": "https://esm.d8d.fun/@heroicons/react@2.1.1/24/solid?dev&deps=react@19.0.0,react-dom@19.0.0",
"@testing-library/react": "https://esm.d8d.fun/@testing-library/react@16.3.0?dev&deps=react@19.0.0,react-dom@19.0.0",
"@testing-library/user-event":"npm:@testing-library/user-event@14.6.1",
"jsdom":"npm:jsdom@26.0.0"
},
"compilerOptions": {

13
deno.lock generated
View File

@@ -6,6 +6,7 @@
"npm:@testing-library/react@*": "16.3.0_@testing-library+dom@10.4.0_react@19.1.0_react-dom@19.1.0__react@19.1.0",
"npm:@testing-library/react@16.3.0": "16.3.0_@testing-library+dom@10.4.0_react@19.1.0_react-dom@19.1.0__react@19.1.0",
"npm:@testing-library/user-event@*": "14.6.1_@testing-library+dom@10.4.0",
"npm:@testing-library/user-event@14.6.1": "14.6.1_@testing-library+dom@10.4.0",
"npm:@types/node@*": "22.12.0",
"npm:antd@*": "5.24.6_react@19.1.0_react-dom@19.1.0__react@19.1.0_dayjs@1.11.13",
"npm:global-jsdom@*": "26.0.0_jsdom@26.0.0",
@@ -1377,6 +1378,7 @@
"https://esm.d8d.fun/@deno/shim-deno@~0.18.0?target=denonext": "https://esm.d8d.fun/@deno/shim-deno@0.18.2?target=denonext",
"https://esm.d8d.fun/@socket.io/component-emitter@~3.1.0?target=denonext": "https://esm.d8d.fun/@socket.io/component-emitter@3.1.2?target=denonext",
"https://esm.d8d.fun/@testing-library/dom": "https://esm.d8d.fun/@testing-library/dom@10.4.0",
"https://esm.d8d.fun/@testing-library/dom@%3E=7.21.4?target=denonext": "https://esm.d8d.fun/@testing-library/dom@10.4.0?target=denonext",
"https://esm.d8d.fun/@testing-library/dom@^10.0.0?target=denonext": "https://esm.d8d.fun/@testing-library/dom@10.4.0?target=denonext",
"https://esm.d8d.fun/@testing-library/dom@^10.0.0?target=denonext&dev": "https://esm.d8d.fun/@testing-library/dom@10.4.0?target=denonext&dev",
"https://esm.d8d.fun/@testing-library/react?deps=react@19.0.0,react-dom@19.0.0": "https://esm.d8d.fun/@testing-library/react@16.3.0?deps=react@19.0.0,react-dom@19.0.0",
@@ -1427,6 +1429,7 @@
"https://esm.d8d.fun/@types/react-dom@~19.0.4/client.d.ts": "https://esm.d8d.fun/@types/react-dom@19.0.6/client.d.ts",
"https://esm.d8d.fun/@types/react-dom@~19.0.4/index.d.ts": "https://esm.d8d.fun/@types/react-dom@19.0.6/index.d.ts",
"https://esm.d8d.fun/@types/react-dom@~19.0.6/client.d.ts": "https://esm.d8d.fun/@types/react-dom@19.0.6/client.d.ts",
"https://esm.d8d.fun/@types/react-dom@~19.0.6/index.d.ts": "https://esm.d8d.fun/@types/react-dom@19.0.6/index.d.ts",
"https://esm.d8d.fun/@types/react-dom@~19.1.2/client.d.ts": "https://esm.d8d.fun/@types/react-dom@19.1.2/client.d.ts",
"https://esm.d8d.fun/@types/react-dom@~19.1.2/index.d.ts": "https://esm.d8d.fun/@types/react-dom@19.1.2/index.d.ts",
"https://esm.d8d.fun/@types/react-dom@~19.1.2/test-utils/index.d.ts": "https://esm.d8d.fun/@types/react-dom@19.1.2/test-utils/index.d.ts",
@@ -2777,8 +2780,12 @@
"https://esm.d8d.fun/@deno/shim-deno@0.18.2/denonext/shim-deno.mjs": "819d8ac34fdaf60658cf03d137f14adaff3f13a279ffd79cd8797d84a6ac46ab",
"https://esm.d8d.fun/@deno/shim-deno@0.18.2?target=denonext": "ffa3ca347bb6b6530720158f307a2e31b16728fbb52e6432254a07d52fcbc404",
"https://esm.d8d.fun/@heroicons/react@2.1.1/24/outline?deps=react@19.0.0,react-dom@19.0.0": "5e99f4d40ce60c55b5cf421c3cf3f13df1707cf53152e447b2332570412cd77a",
"https://esm.d8d.fun/@heroicons/react@2.1.1/24/outline?dev&deps=react@19.0.0,react-dom@19.0.0": "6b98b262ef98bf59857e12d089c9506e0a4f9982fb335ce22ff1f9f76ac4245a",
"https://esm.d8d.fun/@heroicons/react@2.1.1/24/solid?deps=react@19.0.0,react-dom@19.0.0": "e3940182b574da537337b1e90a1b7f380e17050457423e13d5ac8c7bc88a3cc0",
"https://esm.d8d.fun/@heroicons/react@2.1.1/24/solid?dev&deps=react@19.0.0,react-dom@19.0.0": "6c56d2e8d159ed0238518cd0dea1f1dfd3c05866a732e98f636bafa1b171153d",
"https://esm.d8d.fun/@heroicons/react@2.1.1/X-ZHJlYWN0LWRvbUAxOS4wLjAscmVhY3RAMTkuMC4w/denonext/24/outline.development.mjs": "1045f8e5320626992f4a069bd24ae6c1f341d386d768bbf4904608bad876b0f3",
"https://esm.d8d.fun/@heroicons/react@2.1.1/X-ZHJlYWN0LWRvbUAxOS4wLjAscmVhY3RAMTkuMC4w/denonext/24/outline.mjs": "640f934a0c987f682032049e5d4a455567db676de47bca0d44e76b72023661f7",
"https://esm.d8d.fun/@heroicons/react@2.1.1/X-ZHJlYWN0LWRvbUAxOS4wLjAscmVhY3RAMTkuMC4w/denonext/24/solid.development.mjs": "00ca0e838f7d4df154ab86d24e36adbf88708606adf3ea2cc7cc56e59026540d",
"https://esm.d8d.fun/@heroicons/react@2.1.1/X-ZHJlYWN0LWRvbUAxOS4wLjAscmVhY3RAMTkuMC4w/denonext/24/solid.mjs": "dcbd0c377d92857b6eb23c7dbb2ee6e650b12aa6ae1ef7fcc10dc1964df8ba47",
"https://esm.d8d.fun/@socket.io/component-emitter@3.1.2/denonext/component-emitter.mjs": "3c6c5f2d64d4933b577a7117df1d8855c51ff01ab3dea8f42af1adcb1a5989e7",
"https://esm.d8d.fun/@socket.io/component-emitter@3.1.2?target=denonext": "f6ff0f94ae3c9850a2c3a925cc2b236ec03a80fc2298d0ca48c2a90b10487db3",
@@ -2803,6 +2810,8 @@
"https://esm.d8d.fun/@testing-library/react@16.3.0?dev&deps=react@19.0.0,react-dom@19.0.0": "45f68d1334937328f1f41c9785e1beb85d912fff54fbb32eed597a4f262475a4",
"https://esm.d8d.fun/@testing-library/react@16.3.0?dev&deps=react@19.0.0,react-dom@19.0.0&export=": "45f68d1334937328f1f41c9785e1beb85d912fff54fbb32eed597a4f262475a4",
"https://esm.d8d.fun/@testing-library/react@16.3.0?dev&deps=react@19.0.0,react-dom@19.0.0&export=document": "45f68d1334937328f1f41c9785e1beb85d912fff54fbb32eed597a4f262475a4",
"https://esm.d8d.fun/@testing-library/user-event@14.6.1": "3f7d71e48391de42ba52305286ecb9e6d3764e34867baec0a3575d24ed699dda",
"https://esm.d8d.fun/@testing-library/user-event@14.6.1/denonext/user-event.mjs": "5c0a61f970c02d481dff4294bd64d739f049ea44e9b57f9c14450933a47252cb",
"https://esm.d8d.fun/agent-base@7.1.3/denonext/agent-base.development.mjs": "0f740785213e5c410760457aa209a0f224da6d5cc65124626b7a1a344c0504f4",
"https://esm.d8d.fun/agent-base@7.1.3/denonext/agent-base.mjs": "65d873bec0946614e2e33c0c3c1c958ee346695facfdeb51e2dda348e700bd57",
"https://esm.d8d.fun/agent-base@7.1.3?target=denonext": "c76a77281d852899060a3ecf8bed33525c5f252f53dfac18e2f0ae5957b22910",
@@ -3262,6 +3271,7 @@
"https://esm.d8d.fun/react-dom@19.0.0/denonext/client.mjs": "af662fd134eea98f37fdcea6142accd0f8a7d2e13c1c3c9e98dc37a8c7aad46b",
"https://esm.d8d.fun/react-dom@19.0.0/denonext/react-dom.development.mjs": "617b31a0b5be498d4ae231b7deee56d3efde81cd6a4cbec2da66291b08cac51c",
"https://esm.d8d.fun/react-dom@19.0.0/denonext/react-dom.mjs": "a2f7bc344e1d5b7ca47e68665291e206ae4db17ee84f234f3d3e2533b9119f63",
"https://esm.d8d.fun/react-dom@19.0.0?dev": "a80f467a0d1c4e36b15ff59a33c55646a33d35e761ea218b8354ea26980f34d2",
"https://esm.d8d.fun/react-dom@19.1.0/client?target=denonext": "a84db2e3e86b71bf712d55f37603df8be4a624d7e93b63795524ec0554b1a6af",
"https://esm.d8d.fun/react-dom@19.1.0/client?target=denonext&dev": "ac56773a1d6cde780e97c8337f3a66e5200d623fb90b93076f0fe6675f945306",
"https://esm.d8d.fun/react-dom@19.1.0/denonext/client.development.mjs": "ae802423d440da19a3d9dec9e500e8c80f20f085f7ce6e8f06a26cf9e616ee3c",
@@ -3274,8 +3284,10 @@
"https://esm.d8d.fun/react-dom@19.1.0/test-utils?target=denonext&dev": "10082781244c8cce4b151b990b6475c52d5b83e422a09b66936da87cbdd8e35e",
"https://esm.d8d.fun/react-dom@19.1.0?target=denonext": "0af10bc13bc7ef60cd74313dc427d357184e28c86cc878340add5cde7ba00120",
"https://esm.d8d.fun/react-dom@19.1.0?target=denonext&dev": "cd750cefba42a1c5575f80e70fba6a2f1fdf3dac780cf380dbe5ffc005b04bd2",
"https://esm.d8d.fun/react-hook-form@7.55.0/X-ZHJlYWN0LWRvbUAxOS4wLjAscmVhY3RAMTkuMC4w/denonext/react-hook-form.development.mjs": "b58c0d230f984a8dc8302b5dfddd173f03308faa92b432cd21edaa823fe43d8c",
"https://esm.d8d.fun/react-hook-form@7.55.0/X-ZHJlYWN0LWRvbUAxOS4wLjAscmVhY3RAMTkuMC4w/denonext/react-hook-form.mjs": "788ec1a54e10051f539ba435aa513802c823bad03e11e2534b1b17df99189a87",
"https://esm.d8d.fun/react-hook-form@7.55.0?deps=react@19.0.0,react-dom@19.0.0": "8ed376b3af6e11be43538b15e654692d5995232523a6dc16ce7f81263b1a3614",
"https://esm.d8d.fun/react-hook-form@7.55.0?dev&deps=react@19.0.0,react-dom@19.0.0": "f4fc9cd4c769d32b703007cf3353ab2e0ddcd3de90a5536fc03fdcf7396fbcf4",
"https://esm.d8d.fun/react-is@17.0.2/denonext/react-is.development.mjs": "4b640b0b829848a8150fcae01bc5c44894f71490a58e2de7b346b44e35c29af6",
"https://esm.d8d.fun/react-is@17.0.2/denonext/react-is.mjs": "6b144222bce64ee266c22c6c06d7620f948997404e9bf285c48ee265446193d5",
"https://esm.d8d.fun/react-is@17.0.2?target=denonext": "d8b7baf6cea6e132411aa2e4d69366fe0b7c911c7481d31f790b8f159311c7a3",
@@ -3443,6 +3455,7 @@
},
"workspace": {
"dependencies": [
"npm:@testing-library/user-event@14.6.1",
"npm:jsdom@26.0.0"
]
}

45
test.log Normal file
View File

@@ -0,0 +1,45 @@
running 1 test from ./client/admin/pages_know_info.test.tsx
知识库管理页面测试 ...
应正确渲染页面元素 ... ok (1s)
初始加载表格数据 ... ok (940ms)
搜索表单应正常工作 ...
------- output -------
searchInput 数据分析
<input
class="ant-input css-dev-only-do-not-override-1a3rktk ant-input-outlined ant-input-status-success"
id="title"
placeholder="请输入文章标题"
type="text"
value="数据分析"
/>
<span>
搜 索
</span>
handleSearch { title: "数据分析", category: undefined }
等待表格刷新并验证 2
等待搜索结果并验证 2
等待搜索结果并验证 2
等待搜索结果并验证 2
等待搜索结果并验证 2
等待搜索结果并验证 2
等待搜索结果并验证 2
等待搜索结果并验证 2
等待搜索结果并验证 2
等待搜索结果并验证 2
等待搜索结果并验证 2
等待搜索结果并验证 2
等待搜索结果并验证 2
等待搜索结果并验证 2
等待搜索结果并验证 2
等待搜索结果并验证 2
等待搜索结果并验证 3
hasMatch true
----- output end -----
搜索表单应正常工作 ... ok (2s)
表格应加载并显示数据 ... ok (28ms)
应能打开添加文章模态框 ... ok (241ms)
应能完整添加一篇文章 ... ok (153ms)
知识库管理页面测试 ... ok (4s)
ok | 1 passed (6 steps) | 0 failed (4s)