文件
shanghaipeiwan/server/tests/barcode-qrcode.spec.ts

91 行
4.2 KiB
TypeScript

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);
});
});
});