platform-migration.test.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. import fs from 'fs';
  2. import path from 'path';
  3. import { fileURLToPath } from 'url';
  4. const __filename = fileURLToPath(import.meta.url);
  5. const __dirname = path.dirname(__filename);
  6. // 测试配置
  7. const TEST_CONFIG = {
  8. sourceDir: path.join(__dirname, '..', 'src'),
  9. platformsDir: path.join(__dirname, '..', 'src', 'pages', 'platforms'),
  10. zhipuDir: path.join(__dirname, '..', 'src', 'pages', 'platforms', 'zhipu'),
  11. deepseekDir: path.join(__dirname, '..', 'src', 'pages', 'deepseek'),
  12. routerFile: path.join(__dirname, '..', 'src', 'router.tsx'),
  13. apiFile: path.join(__dirname, '..', 'src', 'apis', 'index.ts'),
  14. };
  15. // 测试结果收集器
  16. class TestResultCollector {
  17. constructor() {
  18. this.results = [];
  19. this.passed = 0;
  20. this.failed = 0;
  21. }
  22. addResult(testName, passed, details = '') {
  23. const result = { testName, passed, details, timestamp: new Date() };
  24. this.results.push(result);
  25. if (passed) {
  26. this.passed++;
  27. } else {
  28. this.failed++;
  29. }
  30. }
  31. getSummary() {
  32. return {
  33. total: this.results.length,
  34. passed: this.passed,
  35. failed: this.failed,
  36. successRate: this.results.length > 0 ? (this.passed / this.results.length * 100).toFixed(2) : 0
  37. };
  38. }
  39. printResults() {
  40. console.log('\n📊 测试结果汇总:');
  41. console.log(` 总测试数: ${this.results.length}`);
  42. console.log(` 通过: ${this.passed}`);
  43. console.log(` 失败: ${this.failed}`);
  44. console.log(` 成功率: ${this.getSummary().successRate}%`);
  45. console.log('\n📋 详细结果:');
  46. this.results.forEach((result, index) => {
  47. const status = result.passed ? '✅' : '❌';
  48. console.log(` ${index + 1}. ${status} ${result.testName}`);
  49. if (!result.passed && result.details) {
  50. console.log(` 详情: ${result.details}`);
  51. }
  52. });
  53. }
  54. }
  55. // 测试工具函数
  56. class TestUtils {
  57. static fileExists(filePath) {
  58. try {
  59. return fs.existsSync(filePath);
  60. } catch (error) {
  61. return false;
  62. }
  63. }
  64. static readFile(filePath) {
  65. try {
  66. return fs.readFileSync(filePath, 'utf8');
  67. } catch (error) {
  68. return null;
  69. }
  70. }
  71. static listDirectories(dirPath) {
  72. try {
  73. return fs.readdirSync(dirPath, { withFileTypes: true })
  74. .filter(dirent => dirent.isDirectory())
  75. .map(dirent => dirent.name);
  76. } catch (error) {
  77. return [];
  78. }
  79. }
  80. static countOccurrences(text, pattern) {
  81. const matches = text.match(new RegExp(pattern, 'g'));
  82. return matches ? matches.length : 0;
  83. }
  84. }
  85. // 测试用例
  86. class PlatformMigrationTests {
  87. constructor() {
  88. this.collector = new TestResultCollector();
  89. }
  90. // 测试1: 验证目录结构
  91. testDirectoryStructure() {
  92. console.log('\n🏗️ 测试目录结构...');
  93. // 测试 platforms 目录存在
  94. const platformsExists = TestUtils.fileExists(TEST_CONFIG.platformsDir);
  95. this.collector.addResult(
  96. 'platforms 目录存在',
  97. platformsExists,
  98. platformsExists ? '' : `目录不存在: ${TEST_CONFIG.platformsDir}`
  99. );
  100. // 测试 zhipu 目录存在
  101. const zhipuExists = TestUtils.fileExists(TEST_CONFIG.zhipuDir);
  102. this.collector.addResult(
  103. 'zhipu 目录存在',
  104. zhipuExists,
  105. zhipuExists ? '' : `目录不存在: ${TEST_CONFIG.zhipuDir}`
  106. );
  107. // 测试 zhipu 子目录
  108. if (zhipuExists) {
  109. const zhipuSubDirs = TestUtils.listDirectories(TEST_CONFIG.zhipuDir);
  110. const expectedDirs = ['questionAnswer', 'knowledgeLib', 'dataExport'];
  111. const missingDirs = expectedDirs.filter(dir => !zhipuSubDirs.includes(dir));
  112. this.collector.addResult(
  113. 'zhipu 子目录完整',
  114. missingDirs.length === 0,
  115. missingDirs.length > 0 ? `缺少目录: ${missingDirs.join(', ')}` : ''
  116. );
  117. }
  118. // 测试 deepseek 目录仍然存在
  119. const deepseekExists = TestUtils.fileExists(TEST_CONFIG.deepseekDir);
  120. this.collector.addResult(
  121. 'deepseek 目录保持存在',
  122. deepseekExists,
  123. deepseekExists ? '' : `目录不存在: ${TEST_CONFIG.deepseekDir}`
  124. );
  125. }
  126. // 测试2: 验证路由配置
  127. testRouterConfiguration() {
  128. console.log('\n🛣️ 测试路由配置...');
  129. const routerContent = TestUtils.readFile(TEST_CONFIG.routerFile);
  130. if (!routerContent) {
  131. this.collector.addResult('路由文件可读', false, '无法读取路由文件');
  132. return;
  133. }
  134. // 测试 zhipu 路由路径
  135. const zhipuPathCount = TestUtils.countOccurrences(routerContent, '/zhipu/');
  136. this.collector.addResult(
  137. 'zhipu 路由路径配置',
  138. zhipuPathCount >= 3,
  139. zhipuPathCount < 3 ? `期望至少3个zhipu路径,实际找到${zhipuPathCount}个` : ''
  140. );
  141. // 测试 zhipu 导入路径
  142. const zhipuImportCount = TestUtils.countOccurrences(routerContent, '@/pages/platforms/zhipu/');
  143. this.collector.addResult(
  144. 'zhipu 导入路径配置',
  145. zhipuImportCount >= 5,
  146. zhipuImportCount < 5 ? `期望至少5个zhipu导入路径,实际找到${zhipuImportCount}个` : ''
  147. );
  148. // 测试没有遗留的旧路径
  149. const oldPathCount = TestUtils.countOccurrences(routerContent, '@/pages/(questionAnswer|knowledgeLib|dataExport)');
  150. this.collector.addResult(
  151. '没有遗留旧路径',
  152. oldPathCount === 0,
  153. oldPathCount > 0 ? `发现${oldPathCount}个遗留的旧路径引用` : ''
  154. );
  155. // 测试 deepseek 路径仍然正确
  156. const deepseekPathCount = TestUtils.countOccurrences(routerContent, '/deepseek/');
  157. this.collector.addResult(
  158. 'deepseek 路由路径保持',
  159. deepseekPathCount >= 3,
  160. deepseekPathCount < 3 ? `期望至少3个deepseek路径,实际找到${deepseekPathCount}个` : ''
  161. );
  162. }
  163. // 测试3: 验证文件完整性
  164. testFileIntegrity() {
  165. console.log('\n📁 测试文件完整性...');
  166. // 测试关键文件存在
  167. const criticalFiles = [
  168. path.join(TEST_CONFIG.zhipuDir, 'questionAnswer', 'list', 'index.tsx'),
  169. path.join(TEST_CONFIG.zhipuDir, 'questionAnswer', 'info', 'index.tsx'),
  170. path.join(TEST_CONFIG.zhipuDir, 'knowledgeLib', 'list', 'index.tsx'),
  171. path.join(TEST_CONFIG.zhipuDir, 'knowledgeLib', 'detail', 'index.tsx'),
  172. path.join(TEST_CONFIG.zhipuDir, 'dataExport', 'index.tsx'),
  173. ];
  174. criticalFiles.forEach(filePath => {
  175. const exists = TestUtils.fileExists(filePath);
  176. const fileName = path.basename(filePath);
  177. this.collector.addResult(
  178. `文件存在: ${fileName}`,
  179. exists,
  180. exists ? '' : `文件不存在: ${filePath}`
  181. );
  182. });
  183. // 测试文件内容可读
  184. const testFile = path.join(TEST_CONFIG.zhipuDir, 'questionAnswer', 'list', 'index.tsx');
  185. const content = TestUtils.readFile(testFile);
  186. this.collector.addResult(
  187. '文件内容可读',
  188. content !== null,
  189. content === null ? `无法读取文件内容: ${testFile}` : ''
  190. );
  191. }
  192. // 测试4: 验证导入路径
  193. testImportPaths() {
  194. console.log('\n📦 测试导入路径...');
  195. // 检查是否有任何文件引用了旧的路径
  196. const oldImportPatterns = [
  197. '@/pages/questionAnswer',
  198. '@/pages/knowledgeLib',
  199. '@/pages/dataExport'
  200. ];
  201. oldImportPatterns.forEach(pattern => {
  202. const files = this.findFilesWithPattern(pattern);
  203. this.collector.addResult(
  204. `没有遗留 ${pattern} 导入`,
  205. files.length === 0,
  206. files.length > 0 ? `发现${files.length}个文件包含旧导入: ${files.slice(0, 3).join(', ')}` : ''
  207. );
  208. });
  209. // 检查新的导入路径
  210. const newImportPatterns = [
  211. '@/pages/platforms/zhipu/questionAnswer',
  212. '@/pages/platforms/zhipu/knowledgeLib',
  213. '@/pages/platforms/zhipu/dataExport'
  214. ];
  215. newImportPatterns.forEach(pattern => {
  216. const files = this.findFilesWithPattern(pattern);
  217. this.collector.addResult(
  218. `新导入路径 ${pattern} 被使用`,
  219. files.length > 0,
  220. files.length === 0 ? `没有找到使用新导入路径的文件` : ''
  221. );
  222. });
  223. }
  224. // 测试5: 验证构建兼容性
  225. testBuildCompatibility() {
  226. console.log('\n🔨 测试构建兼容性...');
  227. // 检查 TypeScript 配置
  228. const tsConfigPath = path.join(__dirname, '..', 'tsconfig.json');
  229. const tsConfigExists = TestUtils.fileExists(tsConfigPath);
  230. this.collector.addResult(
  231. 'TypeScript 配置存在',
  232. tsConfigExists,
  233. tsConfigExists ? '' : 'tsconfig.json 不存在'
  234. );
  235. // 检查 Vite 配置
  236. const viteConfigPath = path.join(__dirname, '..', 'vite.config.ts');
  237. const viteConfigExists = TestUtils.fileExists(viteConfigPath);
  238. this.collector.addResult(
  239. 'Vite 配置存在',
  240. viteConfigExists,
  241. viteConfigExists ? '' : 'vite.config.ts 不存在'
  242. );
  243. // 检查 package.json
  244. const packageJsonPath = path.join(__dirname, '..', 'package.json');
  245. const packageJsonExists = TestUtils.fileExists(packageJsonPath);
  246. this.collector.addResult(
  247. 'package.json 存在',
  248. packageJsonExists,
  249. packageJsonExists ? '' : 'package.json 不存在'
  250. );
  251. }
  252. // 辅助方法:查找包含特定模式的文件
  253. findFilesWithPattern(pattern) {
  254. const files = [];
  255. this.searchInDirectory(TEST_CONFIG.sourceDir, pattern, files);
  256. return files;
  257. }
  258. searchInDirectory(dir, pattern, files) {
  259. try {
  260. const items = fs.readdirSync(dir);
  261. items.forEach(item => {
  262. const fullPath = path.join(dir, item);
  263. const stat = fs.statSync(fullPath);
  264. if (stat.isDirectory()) {
  265. this.searchInDirectory(fullPath, pattern, files);
  266. } else if (stat.isFile() && /\.(ts|tsx|js|jsx)$/.test(item)) {
  267. const content = TestUtils.readFile(fullPath);
  268. if (content && content.includes(pattern)) {
  269. files.push(path.relative(TEST_CONFIG.sourceDir, fullPath));
  270. }
  271. }
  272. });
  273. } catch (error) {
  274. // 忽略错误,继续搜索
  275. }
  276. }
  277. // 运行所有测试
  278. runAllTests() {
  279. console.log('🚀 开始平台迁移测试...\n');
  280. this.testDirectoryStructure();
  281. this.testRouterConfiguration();
  282. this.testFileIntegrity();
  283. this.testImportPaths();
  284. this.testBuildCompatibility();
  285. // 输出结果
  286. this.collector.printResults();
  287. // 返回测试结果
  288. const summary = this.collector.getSummary();
  289. if (summary.failed > 0) {
  290. console.log('\n⚠️ 部分测试失败,请检查上述问题。');
  291. process.exit(1);
  292. } else {
  293. console.log('\n🎉 所有测试通过!平台迁移成功。');
  294. }
  295. }
  296. }
  297. // 运行测试
  298. const tests = new PlatformMigrationTests();
  299. tests.runAllTests();