import * as fs from 'fs'; import * as path from 'path'; import * as vm from 'vm'; function loadFrontendEsm(filePath: string) { let code = fs.readFileSync(filePath, 'utf-8'); code = code.replace(/export\s+const\s+(\w+)/g, 'const $1'); code = code.replace(/export\s+class\s+(\w+)/g, 'class $1'); code = code.replace(/export\s+function\s+(\w+)/g, 'function $1'); const sandbox: any = { module: { exports: {} }, exports: {} }; vm.createContext(sandbox); vm.runInContext( `${code}\nmodule.exports = { ...module.exports, ...(typeof encodeCode128B !== 'undefined' ? { encodeCode128B, getBarcodeBits } : {}), ...(typeof generateQRCodeMatrix !== 'undefined' ? { generateQRCodeMatrix, QRCodeModel } : {}) };`, sandbox ); return sandbox.module.exports; } describe('Barcode & QRCode Architecture (TDD 门票真实条形码与二维码生成及零Mock门禁)', () => { const rootDir = path.resolve(__dirname, '../..'); const barcodeJsPath = path.join(rootDir, 'pwuniapp/common/barcode.js'); const qrcodeJsPath = path.join(rootDir, 'pwuniapp/common/qrcode.js'); const ticketVuePath = path.join(rootDir, 'pwuniapp/pages/activity/my-ticket.vue'); describe('1. Code128 条形码算法规范', () => { it('barcode.js 文件必须存在且导出 encodeCode128B 和 getBarcodeBits', () => { expect(fs.existsSync(barcodeJsPath)).toBe(true); const content = fs.readFileSync(barcodeJsPath, 'utf-8'); expect(content).toContain('export function encodeCode128B'); expect(content).toContain('export function getBarcodeBits'); }); it('Code128 编码能够正确计算校验码并生成标准条空序列', () => { const { encodeCode128B, getBarcodeBits } = loadFrontendEsm(barcodeJsPath); const testCode = 'TICKET-101-8392'; const segments = encodeCode128B(testCode); expect(Array.isArray(segments)).toBe(true); expect(segments.length).toBeGreaterThan(10); const bits = getBarcodeBits(testCode); expect(typeof bits).toBe('string'); expect(bits).toMatch(/^[01]+$/); }); }); describe('2. QR Code 二维码矩阵算法规范', () => { it('qrcode.js 文件必须存在且导出 generateQRCodeMatrix 和 QRCodeModel', () => { expect(fs.existsSync(qrcodeJsPath)).toBe(true); const content = fs.readFileSync(qrcodeJsPath, 'utf-8'); expect(content).toContain('export function generateQRCodeMatrix'); expect(content).toContain('export class QRCodeModel'); }); it('QR Code 算法能够为任意门票串生成合法的 N*N 二维点阵矩阵', () => { const { generateQRCodeMatrix } = loadFrontendEsm(qrcodeJsPath); const testText = 'TICKET-101-8392'; const matrix = generateQRCodeMatrix(testText, 2); expect(Array.isArray(matrix)).toBe(true); expect(matrix.length).toBe(25); // Ver 2: 25x25 矩阵 expect(matrix[0].length).toBe(25); // 验证寻象图形 (Position Probe Pattern: 左上角第 0 行应有黑块) expect(matrix[0][0]).toBe(true); }); }); describe('3. 门票页面真实接入门禁与移除Mock依赖', () => { it('my-ticket.vue 必须引入真实条形码与二维码生成算法', () => { const content = fs.readFileSync(ticketVuePath, 'utf-8'); expect(content).toContain('encodeCode128B'); expect(content).toContain('generateQRCodeMatrix'); expect(content).toContain('barcodeSegments'); expect(content).toContain('qrcodeMatrix'); }); it('my-ticket.vue 必须彻底移除对 ACTIVITIES_LIST 假Mock数据的依赖', () => { const content = fs.readFileSync(ticketVuePath, 'utf-8'); expect(content).not.toContain("import { ACTIVITIES_LIST } from '@/common/mock.js';"); expect(content).not.toContain('const ticketData = ref(ACTIVITIES_LIST[0])'); }); it('所有新写的代码中严禁包含任何系统 Emoji', () => { const bContent = fs.readFileSync(barcodeJsPath, 'utf-8'); const qContent = fs.readFileSync(qrcodeJsPath, 'utf-8'); const tContent = fs.readFileSync(ticketVuePath, 'utf-8'); const emojiRegex = /[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/u; expect(emojiRegex.test(bContent)).toBe(false); expect(emojiRegex.test(qContent)).toBe(false); expect(emojiRegex.test(tContent)).toBe(false); }); }); });