const fs = require('fs'); const path = require('path'); const vm = require('vm'); let passed = 0; let failed = 0; function assert(condition, testName, detail = '') { if (condition) { console.log(` [PASS] ${testName}`); passed++; } else { console.error(` [FAIL] ${testName} - ${detail}`); failed++; } } console.log("========================================================"); console.log(" 订单页面 JS 语法与模板渲染健壮性 TDD 自动化测试"); console.log("========================================================\n"); // 1. 验证 order.js 文件存在与语法解析 const orderJsPath = path.resolve(__dirname, '../public/assets/js/backend/shopro/order/order.js'); assert(fs.existsSync(orderJsPath), 'order.js 文件存在'); const orderJsContent = fs.readFileSync(orderJsPath, 'utf-8'); // 语法检查 let syntaxOk = false; let syntaxErrorMsg = ''; try { new vm.Script(orderJsContent, { filename: 'order.js' }); syntaxOk = true; } catch (e) { syntaxErrorMsg = e.message; } assert(syntaxOk, 'order.js 语法解析无 SyntaxError', syntaxErrorMsg); // 2. 验证 order.js 结构与闭合完整性 const dummyDefine = function (deps, factory) { const $ = () => ({}); const Backend = { api: {} }; const Table = {}; const Form = {}; return factory($, undefined, Backend, Table, Form); }; let moduleLoaded = false; let controllerObj = null; try { const sandbox = { define: dummyDefine, console: console, location: { search: '?ref=addtabs' }, window: {}, Fast: { api: { ajax: () => {}, open: () => {}, fixurl: (u) => u } }, Vue: { ref: (v) => ({ value: v }), reactive: (o) => o, onMounted: () => {}, getCurrentInstance: () => ({ proxy: { $refs: {} } }) }, createApp: () => {} }; vm.createContext(sandbox); controllerObj = vm.runInContext(orderJsContent, sandbox); if (controllerObj && typeof controllerObj.index === 'function' && typeof controllerObj.detail === 'function') { moduleLoaded = true; } } catch (e) { syntaxErrorMsg = e.message; } assert(moduleLoaded, 'order.js 成功执行并导出包含 index 和 detail 的 Controller 对象', syntaxErrorMsg); // 3. 验证 detail 中的 onConfirm 闭合与 onBack 独立存在 const onConfirmPattern = /function onConfirm\(\)\s*\{[\s\S]*?proxy\.\$refs\['formRef'\]\.validate[\s\S]*?\}\);\s*\}\s*function onBack\(\)/; assert(onConfirmPattern.test(orderJsContent), 'detail 中的 onConfirm 函数具有独立完整的闭合大括号,不侵入包裹后续方法'); // 4. 验证 index.html 模板中的按钮健壮性 const orderIndexPath = path.resolve(__dirname, '../application/admin/view/shopro/order/order/index.html'); assert(fs.existsSync(orderIndexPath), 'order/index.html 视图文件存在'); const orderIndexContent = fs.readFileSync(orderIndexPath, 'utf-8'); const unsafeBtnMatch = orderIndexContent.includes('scope.row?.btns.includes'); assert(!unsafeBtnMatch, 'order/index.html 中避免 scope.row?.btns.includes 引起的潜在 TypeError 崩溃'); console.log(`\n测试统计: 通过 ${passed}, 失败 ${failed}`); if (failed > 0) { process.exit(1); } else { process.exit(0); }