Açıklama Yok
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

frontend_test.js 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. // 前端功能验证测试
  2. const fs = require('fs');
  3. const path = require('path');
  4. console.log('🔍 开始前端应用测试...\n');
  5. // 读取app.js文件内容
  6. const appJsPath = path.join(__dirname, '../../web/app.js');
  7. if (!fs.existsSync(appJsPath)) {
  8. console.error('❌ app.js文件不存在');
  9. process.exit(1);
  10. }
  11. const appJsContent = fs.readFileSync(appJsPath, 'utf8');
  12. console.log(`📄 app.js文件大小: ${appJsContent.length} 字符`);
  13. // 测试项目
  14. const tests = [
  15. {
  16. name: 'OpenCodeApp类定义',
  17. condition: appJsContent.includes('class OpenCodeApp'),
  18. message: '✓ OpenCodeApp类定义存在'
  19. },
  20. {
  21. name: '构造函数',
  22. condition: appJsContent.includes('constructor()'),
  23. message: '✓ 构造函数存在'
  24. },
  25. {
  26. name: '用户ID生成',
  27. condition: appJsContent.includes('generateUserId()'),
  28. message: '✓ 用户ID生成功能存在'
  29. },
  30. {
  31. name: 'DOM元素初始化',
  32. condition: appJsContent.includes('initElements()'),
  33. message: '✓ DOM元素初始化存在'
  34. },
  35. {
  36. name: '事件绑定',
  37. condition: appJsContent.includes('bindEvents()'),
  38. message: '✓ 事件绑定功能存在'
  39. },
  40. {
  41. name: '健康检查',
  42. condition: appJsContent.includes('checkHealth()'),
  43. message: '✓ 健康检查功能存在'
  44. },
  45. {
  46. name: '会话创建',
  47. condition: appJsContent.includes('createSession()'),
  48. message: '✓ 会话创建功能存在'
  49. },
  50. {
  51. name: '会话列表加载',
  52. condition: appJsContent.includes('loadSessions()'),
  53. message: '✓ 会话列表加载功能存在'
  54. },
  55. {
  56. name: '消息发送',
  57. condition: appJsContent.includes('sendMessage()'),
  58. message: '✓ 消息发送功能存在'
  59. },
  60. {
  61. name: '同步消息发送',
  62. condition: appJsContent.includes('sendMessageSync()'),
  63. message: '✓ 同步消息发送功能存在'
  64. },
  65. {
  66. name: '流式消息发送',
  67. condition: appJsContent.includes('sendMessageStream()'),
  68. message: '✓ 流式消息发送功能存在'
  69. },
  70. {
  71. name: '日志流启动',
  72. condition: appJsContent.includes('startLogStream()'),
  73. message: '✓ 日志流启动功能存在'
  74. },
  75. {
  76. name: '日志条目添加',
  77. condition: appJsContent.includes('addLogEntry('),
  78. message: '✓ 日志条目添加功能存在'
  79. }
  80. ];
  81. // API端点检查
  82. const apiEndpoints = [
  83. '/api/health',
  84. '/api/session/create',
  85. '/api/session/list',
  86. '/api/prompt/sync',
  87. '/api/prompt/stream',
  88. '/api/logs/stream'
  89. ];
  90. // 运行测试
  91. let passed = 0;
  92. let failed = 0;
  93. console.log('🧪 运行功能测试:');
  94. tests.forEach(test => {
  95. if (test.condition) {
  96. console.log(` ${test.message}`);
  97. passed++;
  98. } else {
  99. console.log(` ❌ ${test.name} 失败`);
  100. failed++;
  101. }
  102. });
  103. console.log('\n🌐 API端点检查:');
  104. apiEndpoints.forEach(endpoint => {
  105. if (appJsContent.includes(endpoint)) {
  106. console.log(` ✓ 引用端点: ${endpoint}`);
  107. passed++;
  108. } else {
  109. console.log(` ❌ 缺少端点: ${endpoint}`);
  110. failed++;
  111. }
  112. });
  113. // 检查关键事件处理
  114. console.log('\n🎯 事件处理检查:');
  115. const events = [
  116. 'addEventListener',
  117. 'onclick',
  118. 'onkeydown',
  119. 'onmessage',
  120. 'onerror'
  121. ];
  122. events.forEach(event => {
  123. if (appJsContent.includes(event)) {
  124. console.log(` ✓ 事件处理: ${event}`);
  125. passed++;
  126. } else {
  127. console.log(` ⚠️ 未找到: ${event}`);
  128. }
  129. });
  130. // 检查流式处理技术
  131. console.log('\n🚀 流式处理技术检查:');
  132. const streamingTech = [
  133. 'EventSource',
  134. 'getReader',
  135. 'TextDecoder',
  136. 'fetch',
  137. 'JSON.parse'
  138. ];
  139. streamingTech.forEach(tech => {
  140. if (appJsContent.includes(tech)) {
  141. console.log(` ✓ 使用技术: ${tech}`);
  142. passed++;
  143. } else {
  144. console.log(` ⚠️ 未找到: ${tech}`);
  145. }
  146. });
  147. // 检查错误处理
  148. console.log('\n🛡️ 错误处理检查:');
  149. const errorHandling = [
  150. 'try {',
  151. 'catch (error)',
  152. 'console.error',
  153. 'console.log'
  154. ];
  155. errorHandling.forEach(item => {
  156. if (appJsContent.includes(item)) {
  157. console.log(` ✓ 错误处理: ${item}`);
  158. passed++;
  159. } else {
  160. console.log(` ⚠️ 未找到: ${item}`);
  161. }
  162. });
  163. // 检查DOM操作
  164. console.log('\n💻 DOM操作检查:');
  165. const domOperations = [
  166. 'getElementById',
  167. 'querySelector',
  168. 'innerHTML',
  169. 'textContent',
  170. 'classList',
  171. 'appendChild'
  172. ];
  173. domOperations.forEach(op => {
  174. if (appJsContent.includes(op)) {
  175. console.log(` ✓ DOM操作: ${op}`);
  176. passed++;
  177. } else {
  178. console.log(` ⚠️ 未找到: ${op}`);
  179. }
  180. });
  181. // 输出总结
  182. console.log('\n📊 测试总结:');
  183. console.log(` 通过: ${passed}`);
  184. console.log(` 失败: ${failed}`);
  185. console.log(` 总数: ${passed + failed}`);
  186. if (failed > 0) {
  187. console.log('\n❌ 前端测试失败');
  188. process.exit(1);
  189. } else {
  190. console.log('\n✅ 所有前端测试通过!');
  191. // 额外检查:验证HTML文件
  192. const htmlPath = path.join(__dirname, '../../web/index.html');
  193. if (fs.existsSync(htmlPath)) {
  194. const htmlContent = fs.readFileSync(htmlPath, 'utf8');
  195. console.log('\n📄 HTML文件检查:');
  196. const htmlChecks = [
  197. {
  198. name: '包含app.js引用',
  199. condition: htmlContent.includes('<script src="app.js"></script>'),
  200. message: '✓ 正确引用app.js'
  201. },
  202. {
  203. name: '包含必要元素ID',
  204. condition: htmlContent.includes('id="') &&
  205. htmlContent.includes('id="createSessionBtn"') &&
  206. htmlContent.includes('id="messageInput"'),
  207. message: '✓ 包含必要的元素ID'
  208. },
  209. {
  210. name: '包含CSS样式',
  211. condition: htmlContent.includes('<style>') && htmlContent.includes('</style>'),
  212. message: '✓ 包含内联CSS样式'
  213. }
  214. ];
  215. htmlChecks.forEach(check => {
  216. if (check.condition) {
  217. console.log(` ${check.message}`);
  218. } else {
  219. console.log(` ❌ ${check.name} 失败`);
  220. }
  221. });
  222. console.log(`\n🎨 HTML文件大小: ${htmlContent.length} 字符`);
  223. }
  224. console.log('\n✨ 前端应用验证完成!');
  225. }