/** * tests/partner/verify_remove_mabi_wording_spec.js * * 验证“我的dmepa”全链路移除“马币”二字: * 1. 移动端 madow.vue 指示胶囊文案对齐为「市值 1 dmepa ≈ xx 元」 * 2. 移动端 madow.vue 抽屉弹窗默认文案与数据净化逻辑(不含“马币”) * 3. 服务端 PartnerConfig::madowRuleTitle 与 madowRules 彻底去除“马币”并具备脱敏自愈能力 * 4. 后台 Config 控制器、后台视图 index.html、config.js 默认值与提示语彻底移除“马币” */ const fs = require('fs'); const path = require('path'); const assert = require('assert'); console.log('===================================================='); console.log(' 验证:“我的dmepa”全链路彻底移除「马币」二字'); console.log('====================================================\n'); let passCount = 0; let failCount = 0; function runTest(title, fn) { try { fn(); console.log(`[PASS] ${title}`); passCount++; } catch (err) { console.error(`[FAIL] ${title}`); console.error(` 错误原因: ${err.message}`); failCount++; } } const rootDir = path.resolve(__dirname, '../../'); // 1. 验证 uniapp/pages/commission/madow.vue runTest('uniapp/pages/commission/madow.vue 胶囊文案由「马币市值」调整为「市值」', () => { const file = path.join(rootDir, 'uniapp/pages/commission/madow.vue'); assert.ok(fs.existsSync(file), 'madow.vue 存在'); const content = fs.readFileSync(file, 'utf-8'); // 核心指示胶囊 assert.ok(/市值\s*1\s*DMEPA\s*≈/i.test(content), '胶囊必须使用「市值 1 DMEPA ≈」'); assert.ok(!content.includes('马币市值'), '胶囊中严禁出现「马币市值」'); // 顶栏红框文字去除验证 assert.ok(content.includes('生态资产'), '必须保留「生态资产」标签'); assert.ok(!content.includes('持有dmepa总量') && !content.includes('持有DMEPA总量'), '顶栏「持有DMEPA总量」文字已按需求彻底去掉'); // 默认规则弹窗标题 assert.ok(content.includes("ruleTitle: '市值与增值规则'"), '默认弹窗标题必须为「市值与增值规则」'); // 默认规则内容 assert.ok(content.includes("title: '市值动态增值'"), '默认规则条目必须为「市值动态增值」'); // 数据接收净化 assert.ok(content.includes('.replace(/马币/g, \'\')'), 'getMadow 必须对动态规则标题和条目做去除「马币」净化'); }); // 2. 验证 addons/shopro/service/partner/PartnerConfig.php runTest('addons/shopro/service/partner/PartnerConfig.php 规则方法彻底移除「马币」并脱敏净化', () => { const file = path.join(rootDir, 'addons/shopro/service/partner/PartnerConfig.php'); assert.ok(fs.existsSync(file), 'PartnerConfig.php 存在'); const content = fs.readFileSync(file, 'utf-8'); assert.ok(content.includes("self::get('partner_madow_rule_title', '市值与增值规则')"), '默认标题为「市值与增值规则」'); assert.ok(content.includes("return str_replace('马币', '', $title);"), '标题输出时执行 str_replace 清除「马币」'); assert.ok(content.includes("'title' => '市值动态增值'"), '默认规则条目包含「市值动态增值」'); assert.ok(content.includes("str_replace('马币', '', $rule['title'])"), '条目输出时执行 str_replace 清除「马币」'); }); // 3. 验证 application/admin/controller/shopro/Config.php runTest('application/admin/controller/shopro/Config.php 后台自愈默认值去除「马币」', () => { const file = path.join(rootDir, 'application/admin/controller/shopro/Config.php'); assert.ok(fs.existsSync(file), 'Config.php 存在'); const content = fs.readFileSync(file, 'utf-8'); assert.ok(content.includes("'partner_madow_rule_title' => '市值与增值规则'"), 'ruleDefaults 默认标题去除「马币」'); assert.ok(content.includes("['title' => '市值动态增值'"), 'ruleDefaults 默认条目去除「马币」'); }); // 4. 验证 application/admin/view/shopro/config/index.html runTest('application/admin/view/shopro/config/index.html 视图提示与占位符去除「马币」', () => { const file = path.join(rootDir, 'application/admin/view/shopro/config/index.html'); assert.ok(fs.existsSync(file), 'index.html 存在'); const content = fs.readFileSync(file, 'utf-8'); assert.ok(content.includes('市值 1 dmepa ≈ xxxx 元'), 'tip 提示更新为「市值 1 dmepa ≈ xxxx 元」'); assert.ok(content.includes('placeholder="市值与增值规则"'), '输入框占位符更新为「市值与增值规则」'); }); // 5. 验证 public/assets/js/backend/shopro/config.js runTest('public/assets/js/backend/shopro/config.js 默认值去除「马币」', () => { const file = path.join(rootDir, 'public/assets/js/backend/shopro/config.js'); assert.ok(fs.existsSync(file), 'config.js 存在'); const content = fs.readFileSync(file, 'utf-8'); assert.ok(content.includes("form.model.partner_madow_rule_title = '市值与增值规则'"), 'config.js 默认标题更新为「市值与增值规则」'); assert.ok(content.includes("{ title: '市值动态增值'"), 'config.js 默认规则条目更新为「市值动态增值」'); }); // 6. API 模拟测试:涵盖正常场景、业务失败场景、参数错误场景 runTest('API 模拟测试:正常请求 partner/madow 接口数据结构与文案校验', () => { const mockSuccessResponse = { code: 1, msg: 'ok', data: { madow: '3993.0000', madow_rate: '0.00000858', madow_value: '0.03', show_madow_rate: 1, rule_title: '市值与增值规则', rules: [ { title: 'DMEPA获取与核算', desc: '平台合伙人与创客达成考核或完成订单后,系统将于次日 00:30 起统一参与每日DMEPA加权核算并自动分发。' }, { title: '市值动态增值', desc: '市值随全平台订单增加而上浮增值。全网完成订单总量越多,DMEPA单价所对应的市值越高,共享生态红利。' }, { title: '价值说明与权益', desc: '市值仅作为平台数字生态资产价值参考展示,不可直接兑换现金提现。具体权益按平台股东与合伙人章程执行。' } ], list: [] } }; assert.strictEqual(mockSuccessResponse.code, 1); assert.strictEqual(mockSuccessResponse.data.rule_title.includes('马币'), false, '返回的 rule_title 严禁包含马币'); assert.strictEqual(mockSuccessResponse.data.rules[1].title.includes('马币'), false, '返回的 rules[1].title 严禁包含马币'); assert.strictEqual(mockSuccessResponse.data.rules[1].desc.includes('马币'), false, '返回的 rules[1].desc 严禁包含马币'); }); runTest('API 模拟测试:当服务端数据包含历史「马币」文案时,前端净化脱敏逻辑生效', () => { const dirtyData = { rule_title: '马币市值与增值规则', rules: [ { title: '马币市值动态增值', desc: '马币市值随全平台订单增加而上浮增值。' } ] }; const sanitizedTitle = String(dirtyData.rule_title).replace(/马币/g, ''); const sanitizedRules = dirtyData.rules.map(item => ({ ...item, title: String(item.title || '').replace(/马币/g, ''), desc: String(item.desc || '').replace(/马币/g, '') })); assert.strictEqual(sanitizedTitle, '市值与增值规则'); assert.strictEqual(sanitizedRules[0].title, '市值动态增值'); assert.strictEqual(sanitizedRules[0].desc, '市值随全平台订单增加而上浮增值。'); }); runTest('API 模拟测试:业务拒绝场景(未登录/无权限)统一响应封装', () => { const mockAuthFailResponse = { code: 0, msg: '请先登录后查看DMEPA资产', data: null }; assert.strictEqual(mockAuthFailResponse.code, 0); assert.strictEqual(typeof mockAuthFailResponse.msg, 'string'); }); runTest('API 模拟测试:参数错误场景(page为非法字符串)边界处理', () => { const sanitizePage = (inputPage) => { const p = parseInt(inputPage, 10); return isNaN(p) || p < 1 ? 1 : p; }; assert.strictEqual(sanitizePage('invalid'), 1); assert.strictEqual(sanitizePage('-5'), 1); assert.strictEqual(sanitizePage('3'), 3); }); console.log('\n===================================================='); console.log(`测试完成: 成功 ${passCount} 项, 失败 ${failCount} 项`); console.log('===================================================='); if (failCount > 0) { process.exit(1); }