154 行
6.8 KiB
JavaScript
154 行
6.8 KiB
JavaScript
/**
|
||
* DMEPA提现字段长度超限修复与自愈机制回归测试
|
||
* 覆盖场景:
|
||
* 1. withdraw_info 超长 JSON(>255 字节)结构序列化与解析完整性测试
|
||
* 2. Withdraw 模型获取器 (getWithdrawInfoDisplayAttr) 针对超长及紧凑数据的一致性验证
|
||
* 3. 数据库迁移脚本与 deploy.sh 部署闭环检查
|
||
* 4. settle_date 为 null 防止日结唯一键冲突验证
|
||
*/
|
||
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
const assert = require('assert');
|
||
|
||
console.log('========================================================');
|
||
console.log(' 开始执行 DMEPA 提现截断修复与表结构自愈测试');
|
||
console.log('========================================================\n');
|
||
|
||
// 1. 测试真实提现场景下 withdrawInfo JSON 长度(复现导致 1406 截断的数据)
|
||
const realWithdrawInfo = {
|
||
real_name: "陈测试",
|
||
bank_name: "中国工商银行股份有限公司北京中关村高新技术产业园区科技金融支行",
|
||
card_no: "6222020202020202020",
|
||
"提现资产": "DMEPA",
|
||
"扣除DMEPA": "666000.6660 DMEPA",
|
||
"市值汇率": "1 DMEPA ≈ 0.000015015 元",
|
||
"换算市值": "10.00 元",
|
||
"提现手续费": "0.60 元 (6%)",
|
||
"预计到账": "9.40 元",
|
||
wallet_type: "madow",
|
||
madow_amount: "666000.6660",
|
||
rate: 0.000015015,
|
||
charge_fee: "0.60",
|
||
charge_rate: 0.06
|
||
};
|
||
|
||
const jsonStr = JSON.stringify(realWithdrawInfo);
|
||
const byteLen = Buffer.byteLength(jsonStr, 'utf8');
|
||
console.log(`[测试点 1] 提现信息 JSON 字符串长度: ${jsonStr.length} 字符, UTF-8 字节数: ${byteLen} 字节`);
|
||
assert(byteLen > 255, `JSON 字节数 (${byteLen}) 必须 > 255(确保证明历史 varchar(255) 必报截断)`);
|
||
console.log(' ✓ 验证成功: 确认真实提现数据超出历史 varchar(255) 限制,复现了该错误根因');
|
||
|
||
// 2. 测试 install.sql 中的表结构定义已升级为 text
|
||
const installSqlPath = path.resolve(__dirname, '../../addons/shopro/install.sql');
|
||
const installSql = fs.readFileSync(installSqlPath, 'utf8');
|
||
assert(
|
||
installSql.includes("`withdraw_info` text NULL COMMENT '提现信息'"),
|
||
'install.sql 中 shopro_withdraw.withdraw_info 已定义为 text'
|
||
);
|
||
assert(
|
||
installSql.includes("`charge_rate` decimal(10, 4) NOT NULL DEFAULT '0.0000' COMMENT '手续费率'"),
|
||
'install.sql 中 shopro_withdraw.charge_rate 已定义为 decimal(10, 4)'
|
||
);
|
||
assert(
|
||
installSql.includes("`platform` varchar(50) NULL DEFAULT NULL COMMENT '平台'"),
|
||
'install.sql 中 shopro_withdraw.platform 已定义为 varchar(50)'
|
||
);
|
||
assert(
|
||
installSql.includes("ALTER TABLE `__PREFIX__shopro_withdraw` MODIFY COLUMN `withdraw_info` text NULL"),
|
||
'install.sql 升级补丁包含 withdraw_info 升级 text'
|
||
);
|
||
console.log('[测试点 2] install.sql 表结构与升级补丁断言通过');
|
||
|
||
// 3. 检查 deploy.sh 中包含 migrate_withdraw_schema.php 部署执行
|
||
const deployShPath = path.resolve(__dirname, '../../scripts/deploy.sh');
|
||
const deploySh = fs.readFileSync(deployShPath, 'utf8');
|
||
assert(
|
||
deploySh.includes('migrate_withdraw_schema.php'),
|
||
'deploy.sh 包含 migrate_withdraw_schema.php 自动执行'
|
||
);
|
||
console.log('[测试点 3] deploy.sh 部署自动化迁移挂载断言通过');
|
||
|
||
// 4. 检查 Withdraw.php 服务层中具备自愈和兜底
|
||
const withdrawPhpPath = path.resolve(__dirname, '../../addons/shopro/service/Withdraw.php');
|
||
const withdrawPhp = fs.readFileSync(withdrawPhpPath, 'utf8');
|
||
assert(
|
||
withdrawPhp.includes('saveWithdrawSafe'),
|
||
'Withdraw.php 包含 saveWithdrawSafe 方法'
|
||
);
|
||
assert(
|
||
withdrawPhp.includes("ALTER TABLE `{$prefix}shopro_withdraw` MODIFY COLUMN `withdraw_info` text"),
|
||
'Withdraw.php 具备动态 DDL 自愈升级能力'
|
||
);
|
||
assert(
|
||
withdrawPhp.includes("'settle_date' => null"),
|
||
'applyMadow 提现流水 settle_date 为 null,避免日结唯一键 uk_daily_user_type 冲突'
|
||
);
|
||
assert(
|
||
withdrawPhp.includes("mb_substr($oper_info, 0, 80, 'UTF-8')"),
|
||
'Withdraw.php handleLog 包含截断保护'
|
||
);
|
||
console.log('[测试点 4] Withdraw.php 自愈机制与防唯一键冲突断言通过');
|
||
|
||
// 5. 模拟 WithdrawModel getWithdrawInfoDisplayAttr 在降级紧凑数据下的解析一致性
|
||
function simulateGetWithdrawInfoDisplay(info, amount, chargeFee, chargeRate) {
|
||
if (typeof info === 'string') {
|
||
info = JSON.parse(info);
|
||
}
|
||
const display = {};
|
||
const isMadow = (info.wallet_type === 'madow') || (info['提现资产'] && info['提现资产'].toLowerCase() === 'dmepa');
|
||
if (isMadow) {
|
||
display['提现资产'] = 'DMEPA';
|
||
const madowAmount = info.madow_amount || info['扣除DMEPA'];
|
||
if (madowAmount !== undefined) {
|
||
const madowClean = String(madowAmount).replace(/dmepa/ig, '').trim();
|
||
display['扣除DMEPA'] = madowClean + ' DMEPA';
|
||
}
|
||
const rate = info.rate || info['市值汇率'];
|
||
if (rate !== undefined) {
|
||
display['市值汇率'] = '1 DMEPA ≈ ' + rate + ' 元';
|
||
}
|
||
const marketValue = info['换算市值'] || amount;
|
||
if (marketValue !== undefined) {
|
||
display['换算市值'] = Number(marketValue).toFixed(2) + ' 元';
|
||
}
|
||
if (Number(chargeFee) > 0 || Number(chargeRate) > 0) {
|
||
display['提现手续费'] = Number(chargeFee).toFixed(2) + ' 元 (' + (chargeRate * 100).toFixed(1) + '%)';
|
||
}
|
||
const real = (Number(amount) - Number(chargeFee)).toFixed(2);
|
||
display['预计到账'] = real + ' 元';
|
||
}
|
||
const excludeKeys = ['wallet_type', 'madow_amount', 'rate', 'charge_fee', 'charge_rate', '提现资产', '扣除DMEPA', '扣除dmepa', '市值汇率', '折算汇率', '换算市值', '提现手续费', '预计到账'];
|
||
for (let k in info) {
|
||
if (!excludeKeys.includes(k)) {
|
||
display[k] = info[k];
|
||
}
|
||
}
|
||
return display;
|
||
}
|
||
|
||
// 测试紧凑模式数据解析
|
||
const compactData = {
|
||
real_name: "陈测试",
|
||
bank_name: "中国工商银行",
|
||
card_no: "6222020202020202020",
|
||
wallet_type: "madow",
|
||
madow_amount: "666000.6660",
|
||
rate: 0.000015015,
|
||
charge_fee: 0.60,
|
||
charge_rate: 0.06
|
||
};
|
||
|
||
const displayResult = simulateGetWithdrawInfoDisplay(compactData, 10.00, 0.60, 0.06);
|
||
assert.strictEqual(displayResult['提现资产'], 'DMEPA');
|
||
assert.strictEqual(displayResult['扣除DMEPA'], '666000.6660 DMEPA');
|
||
assert.strictEqual(displayResult['换算市值'], '10.00 元');
|
||
assert.strictEqual(displayResult['预计到账'], '9.40 元');
|
||
assert.strictEqual(displayResult['提现手续费'], '0.60 元 (6.0%)');
|
||
assert.strictEqual(displayResult['real_name'], '陈测试');
|
||
console.log('[测试点 5] 紧凑模式下的后台展示数据解析完全一致无损');
|
||
|
||
console.log('\n========================================================');
|
||
console.log(' 所有 DMEPA 提现截断修复测试用例全部通过![100% OK]');
|
||
console.log('========================================================');
|