/** * 用户规范昵称生成服务专项测试 * 规则规格:HL + 手机尾号后4位(如 HL5758);若重复则追加递增数字(HL57581, HL57582...) */ const fs = require('fs'); const path = require('path'); const assert = require('assert'); let passCount = 0; let failCount = 0; function it(desc, fn) { try { fn(); console.log(` [PASS] ${desc}`); passCount++; } catch (err) { console.error(` [FAIL] ${desc}`); console.error(` Error: ${err.message}`); failCount++; } } console.log('========================================================'); console.log(' 用户规范昵称生成服务 (HL+手机尾号) 专项测试'); console.log('========================================================\n'); // 1. 静态源码与架构完整性检查 const nicknameServicePath = path.resolve(__dirname, '../addons/shopro/service/user/NicknameService.php'); const userAuthPath = path.resolve(__dirname, '../addons/shopro/service/user/UserAuth.php'); const authPath = path.resolve(__dirname, '../application/common/library/Auth.php'); it('NicknameService.php 服务类文件必须存在', () => { assert(fs.existsSync(nicknameServicePath), 'NicknameService.php 不存在'); }); it('NicknameService.php 包含 HL 前缀常量及核心方法', () => { const content = fs.readFileSync(nicknameServicePath, 'utf8'); assert(content.includes("PREFIX = 'HL'"), "缺少 PREFIX = 'HL' 常量定义"); assert(content.includes('function generate('), '缺少 generate 方法'); assert(content.includes('function extractMobileSuffix('), '缺少 extractMobileSuffix 方法'); assert(content.includes('function ensureUnique('), '缺少 ensureUnique 方法'); assert(content.includes('function isNicknameTaken('), '缺少 isNicknameTaken 方法'); }); it('UserAuth.php 注册时正确接入 NicknameService::generate', () => { const content = fs.readFileSync(userAuthPath, 'utf8'); assert(content.includes('NicknameService::generate($mobile)'), 'UserAuth.php 未接入 NicknameService::generate'); assert(!content.includes("userDefaultConfig['nickname'] . $username"), '仍残留旧的随机乱码拼接逻辑'); }); it('Auth.php 底层注册支持 NicknameService 规范生成', () => { const content = fs.readFileSync(authPath, 'utf8'); assert(content.includes('NicknameService::generate'), 'Auth.php 未适配 NicknameService'); }); // 2. 模拟 NicknameService 核心算法纯逻辑验证 class MockNicknameService { static PREFIX = 'HL'; static extractMobileSuffix(mobile) { if (mobile) { const digits = String(mobile).replace(/\D/g, ''); if (digits.length >= 4) { return digits.slice(-4); } } return '8888'; // 模拟兜底4位 } static generate(mobile, existingNicknames = []) { const suffix = this.extractMobileSuffix(mobile); const baseNickname = this.PREFIX + suffix; if (!existingNicknames.includes(baseNickname)) { return baseNickname; } let seq = 1; while (true) { const candidate = `${baseNickname}${seq}`; if (!existingNicknames.includes(candidate)) { return candidate; } seq++; } } } // 3. 场景测试:基础场景 it('场景一:正常手机号 13800005758,无重名 -> 生成 HL5758', () => { const nickname = MockNicknameService.generate('13800005758', []); assert.strictEqual(nickname, 'HL5758'); }); // 4. 场景测试:一次重复追加数字 it('场景二:同尾号用户已占用 HL5758 -> 自动追加数字 1 生成 HL57581', () => { const existing = ['HL5758']; const nickname = MockNicknameService.generate('15900005758', existing); assert.strictEqual(nickname, 'HL57581'); }); // 5. 场景测试:多次重复依次追加数字 it('场景三:HL5758 与 HL57581 均已被占用 -> 递增追加生成 HL57582', () => { const existing = ['HL5758', 'HL57581']; const nickname = MockNicknameService.generate('18800005758', existing); assert.strictEqual(nickname, 'HL57582'); }); // 6. 场景测试:高并发/较多重名场景依次进位 it('场景四:HL5758 及 1~9 均被占用 -> 顺延追加两位数生成 HL575810', () => { const existing = ['HL5758']; for (let i = 1; i <= 9; i++) { existing.push(`HL5758${i}`); } const nickname = MockNicknameService.generate('13300005758', existing); assert.strictEqual(nickname, 'HL575810'); }); // 7. 场景测试:格式化手机号 it('场景五:手机号带国际区号或分隔符 (+86 138-0000-5758) -> 正确提取尾号生成 HL5758', () => { const nickname = MockNicknameService.generate('+86 138-0000-5758', []); assert.strictEqual(nickname, 'HL5758'); }); // 8. 场景测试:优先使用用户自定义填写的昵称 it('场景六:注册传入用户自定义昵称(如“尚善”) -> 优先保留用户昵称,不覆盖', () => { const params = { nickname: '尚善', mobile: '13800005758' }; const finalNickname = params.nickname ? params.nickname : MockNicknameService.generate(params.mobile, []); assert.strictEqual(finalNickname, '尚善'); }); console.log(`\n--------------------------------------------------------`); console.log(`测试结果统计: 通过 ${passCount} 项, 失败 ${failCount} 项`); console.log(`========================================================\n`); if (failCount > 0) { process.exit(1); } else { process.exit(0); }