文件
Henglianshutong/tests/partner/verify_withdraw_methods_visibility_spec.js

179 行
7.2 KiB
JavaScript

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

/**
* tests/partner/verify_withdraw_methods_visibility_spec.js
*
* 验证提现方式选择弹窗(account-type-select.vue)与提现主页(withdraw.vue)
* “如果后台设置关闭的 这里隐藏掉 只有开启才显示” 业务规范自动化测试:
*
* 1. 组件源码结构静态检查(filteredTypeList 仅渲染后台开启的提现渠道)
* 2. 彻底废除旧的 disabled 灰色禁用行显示,改为未开启方式完全不渲染
* 3. 提现主页面关闭渠道自愈与单渠道智能预选逻辑验证
* 4. 各种后台配置场景模拟(单银行卡、微信+银行卡、全开、全关等)
* 5. API 模拟测试(正常场景、业务拒绝场景、参数边界场景)
*/
const fs = require('fs');
const path = require('path');
const assert = require('assert');
console.log('========================================================');
console.log(' 验证:提现方式选择弹窗后台关闭项完全隐藏专项测试');
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/pay/components/account-type-select.vue
runTest('account-type-select.vue 源码实现 filteredTypeList 动态过滤与彻底隐藏未开启项', () => {
const file = path.join(rootDir, 'uniapp/pages/pay/components/account-type-select.vue');
assert.ok(fs.existsSync(file), 'account-type-select.vue 文件存在');
const content = fs.readFileSync(file, 'utf-8');
// 验证 template 中通过 filteredTypeList 遍历,而非全量 typeList
assert.ok(content.includes('v-for="(item, index) in filteredTypeList"'), '必须遍历 filteredTypeList');
assert.ok(!content.includes(':disabled="!methods.includes(item.value)"'), '严禁以 disabled 形式展示未开启的灰色提现项');
// 验证 computed 定义与过滤逻辑
assert.ok(content.includes('const filteredTypeList = computed('), '必须包含 filteredTypeList 计算属性');
assert.ok(content.includes('props.methods.includes(item.value)'), '必须根据 props.methods 严格过滤项');
// 验证空状态提示
assert.ok(content.includes('暂无可用的提现方式'), '包含全关闭时的友好兜底提示');
// 验证响应式同步
assert.ok(content.includes('function syncCurrentValue('), '包含有效提现方式同步校验函数');
});
// 2. 验证 uniapp/pages/pay/withdraw.vue 协同自愈逻辑
runTest('withdraw.vue 规则加载后自动清理后台已关闭的提现方式并支持单方式预选', () => {
const file = path.join(rootDir, 'uniapp/pages/pay/withdraw.vue');
assert.ok(fs.existsSync(file), 'withdraw.vue 文件存在');
const content = fs.readFileSync(file, 'utf-8');
// 验证对已失效提现方式的清理逻辑
assert.ok(
content.includes('!data.methods.includes(state.accountInfo.type)'),
'当后台关闭某提现方式时,清空当前失效选中'
);
// 验证单提现方式自动预选
assert.ok(
content.includes('data.methods.length === 1'),
'当后台仅开启1种提现方式时,自动预选该方式'
);
});
// 3. 核心算法模拟测试:矩阵过滤验证
const allTypes = [
{ icon: 'wechat.png', title: '微信零钱', value: 'wechat' },
{ icon: 'alipay.png', title: '支付宝账户', value: 'alipay' },
{ icon: 'bank.png', title: '银行卡转账', value: 'bank' },
];
function filterTypeList(methods) {
if (!Array.isArray(methods) || methods.length === 0) return [];
return allTypes.filter((item) => methods.includes(item.value));
}
runTest('场景1(如用户截图):后台仅开启银行卡,微信与支付宝必须完全隐藏', () => {
const result = filterTypeList(['bank']);
assert.strictEqual(result.length, 1);
assert.strictEqual(result[0].value, 'bank');
assert.strictEqual(result[0].title, '银行卡转账');
const hasWechat = result.some((r) => r.value === 'wechat');
const hasAlipay = result.some((r) => r.value === 'alipay');
assert.strictEqual(hasWechat, false, '微信零钱必须完全隐藏');
assert.strictEqual(hasAlipay, false, '支付宝账户必须完全隐藏');
});
runTest('场景2:后台开启微信和银行卡,支付宝关闭,仅显示微信和银行卡', () => {
const result = filterTypeList(['wechat', 'bank']);
assert.strictEqual(result.length, 2);
assert.deepStrictEqual(result.map(r => r.value), ['wechat', 'bank']);
const hasAlipay = result.some((r) => r.value === 'alipay');
assert.strictEqual(hasAlipay, false, '支付宝账户必须完全隐藏');
});
runTest('场景3:后台开启全部三种提现方式,三者均正常显示', () => {
const result = filterTypeList(['wechat', 'alipay', 'bank']);
assert.strictEqual(result.length, 3);
assert.deepStrictEqual(result.map(r => r.value), ['wechat', 'alipay', 'bank']);
});
runTest('场景4:后台关闭所有提现方式,列表为空且触发兜底', () => {
const result1 = filterTypeList([]);
assert.strictEqual(result1.length, 0);
const result2 = filterTypeList(null);
assert.strictEqual(result2.length, 0);
});
// 4. API 模拟测试
runTest('API 模拟测试:pay/withdraw/rules 返回仅包含 bank 的提现规则', () => {
const mockRulesResponse = {
code: 1,
msg: '提现规则',
data: {
status: 1,
is_withdraw_open: true,
min_amount: '1.00',
max_amount: '50000.00',
charge_rate_format: 0.5,
charge_rate: 0.005,
methods: ['bank'],
auto_arrival: 0,
}
};
assert.strictEqual(mockRulesResponse.code, 1);
assert.deepStrictEqual(mockRulesResponse.data.methods, ['bank']);
const visible = filterTypeList(mockRulesResponse.data.methods);
assert.strictEqual(visible.length, 1);
assert.strictEqual(visible[0].value, 'bank');
});
runTest('API 模拟测试:提现申请发起时若渠道已被关闭,服务端拦截', () => {
const mockConfig = { status: 1, methods: ['bank'] };
function simulateApply(type) {
if (!mockConfig.methods.includes(type)) {
return { code: 3001, message: '暂不支持该提现方式' };
}
return { code: 0, message: '操作成功', data: { withdraw_sn: 'W123456789' } };
}
const resWechat = simulateApply('wechat');
assert.strictEqual(resWechat.code, 3001);
assert.strictEqual(resWechat.message, '暂不支持该提现方式');
const resBank = simulateApply('bank');
assert.strictEqual(resBank.code, 0);
assert.strictEqual(resBank.data.withdraw_sn, 'W123456789');
});
runTest('API 模拟测试:参数异常(非法提现方式字符串)前端与接口防穿透拦截', () => {
const allowed = ['bank'];
const testInput = 'malicious_eval_type';
const isAllowed = allowed.includes(testInput);
assert.strictEqual(isAllowed, false);
});
console.log('\n========================================================');
console.log(`测试完成: 成功 ${passCount} 项, 失败 ${failCount} 项`);
console.log('========================================================');
if (failCount > 0) {
process.exit(1);
}