41 lines
5.7 KiB
JavaScript
41 lines
5.7 KiB
JavaScript
// Pure UTS data-service regression; no network, account or model access.
|
||||
|
|
const fs = require('node:fs'), vm = require('node:vm'), path = require('node:path'), assert = require('node:assert/strict');
|
|||
|
|
const ts = require('D:/Develop/HBuilderX/plugins/uniapp-uts-v1/node_modules/@dcloudio/uni-uts-v1/lib/typescript/lib/typescript.js');
|
|||
|
|
class Json { constructor(v = {}) { for (const [k,x] of Object.entries(v)) this[k] = Array.isArray(x) ? x.map(wrap) : wrap(x); } getString(k) { return typeof this[k] === 'string' ? this[k] : null; } getNumber(k) {return typeof this[k] === 'number' ? this[k] : null;} getBoolean(k) {return typeof this[k] === 'boolean' ? this[k] : null;} }
|
|||
|
|
function wrap(x) { return x && typeof x === 'object' && !Array.isArray(x) ? new Json(x) : x; }
|
|||
|
|
let reply;
|
|||
|
|
const api = {requestJson:async()=>new Json(reply)};
|
|||
|
|
function load(file) {
|
|||
|
|
const exports = {};
|
|||
|
|
const source = fs.readFileSync(path.join(__dirname,'..',file),'utf8').replace(/const (fieldNames|labels): UTSJSONObject = (.*)/g,'const $1: UTSJSONObject = new UTSJSONObject($2)');
|
|||
|
|
vm.runInNewContext(ts.transpileModule(source,{compilerOptions:{module:ts.ModuleKind.CommonJS,target:ts.ScriptTarget.ES2020}}).outputText,
|
|||
|
|
{exports,UTSJSONObject:Json,require:p=>p.endsWith('api.uts')?api:p.endsWith('config.uts')?{API_BASE_URL:'https://synthetic.invalid/api/v1'}:p.endsWith('records.uts')?{revisionParams:v=>({revisionId:v})}:load('services/money.uts'),Error,Number,Math},{filename:file});
|
|||
|
|
return exports;
|
|||
|
|
}
|
|||
|
|
function fixture() {
|
|||
|
|
return {assessmentId:'1',revisionId:'2',resultVersion:3,matching:{status:'completed',catalogSnapshotId:'synthetic-hash',ruleVersion:'product-matching-v2',orderingPolicyVersion:'product-score-descending-v1'},item:{productId:'4',productVersion:7,eligibility:'eligible',score:92,scorePolicyVersion:'product-soft-score-v1',rank:1,currentAvailability:'available',positiveReasons:[],blockingReasons:[],cautions:[],evidence:[],aiExplanation:{status:'not_requested'},productSnapshot:{productId:'4',productVersion:7,productName:'合成产品',bankName:'合成机构',productType:'信用贷',amountMinYuan:'500000.00',amountMaxYuan:'3000000.00',annualRateMinPercent:'3.60',annualRateMaxPercent:'8.50',termMinMonths:6,termMaxMonths:36,applicantTypes:['enterprise'],regions:[],validFrom:'2026-01-01',validUntil:'2030-01-01',source:{publisher:'合成机构',title:'仅供测试'},rules:[],bankLogo:'/uploads/synthetic.png',consultPhone:'400-123-4567',repaymentMethod:'按月付息',materials:[{name:'营业执照',required:true,note:'准备有效副本',applicantTypes:['enterprise']}]}}};
|
|||
|
|
}
|
|||
|
|
(async()=>{
|
|||
|
|
const service=load('packages/finance/services/matches.uts'); let checks=0;
|
|||
|
|
reply=fixture();let result=await service.fetchMatchDetailRecord('1','4','2');
|
|||
|
|
assert.equal(result.item.score,92);checks++;
|
|||
|
|
assert.equal(result.item.product.amount,'50–300 万元');checks++;
|
|||
|
|
assert.equal(result.item.product.logo,'https://synthetic.invalid/uploads/synthetic.png');checks++;
|
|||
|
|
assert.equal(result.item.product.materialList[0].objects,'企业');checks++;
|
|||
|
|
assert.equal(result.item.product.consultPhone,'400-123-4567');checks++;
|
|||
|
|
assert.equal(result.item.product.repayment,'按月付息');checks++;
|
|||
|
|
reply=fixture();reply.item.productSnapshot.expectation='额度按银行审批';reply.item.productSnapshot.quota='期限按合同';reply.item.productSnapshot.source={};reply.item.productSnapshot.regionMode='unverified';reply.item.productSnapshot.annualRateMinPercent=null;reply.item.productSnapshot.annualRateMaxPercent='8.50';
|
|||
|
|
result=await service.fetchMatchDetailRecord('1','4','2');assert.equal(result.item.product.amount,'额度按银行审批');assert.equal(result.item.product.term,'期限按合同');assert.equal(result.item.product.rate,'最高 8.5%');assert.equal(result.item.product.source,'待核实');assert.equal(result.item.product.regions,'待核实');checks++;
|
|||
|
|
for (const [from,until,want] of [[null,null,'未设置有效期'],[null,'2030-01-01','有效至 2030-01-01'],['2026-01-01',null,'2026-01-01 起生效'],['2026-01-01','2030-01-01','2026-01-01 至 2030-01-01']]) {
|
|||
|
|
reply=fixture();reply.item.productSnapshot.validFrom=from;reply.item.productSnapshot.validUntil=until;
|
|||
|
|
result=await service.fetchMatchDetailRecord('1','4','2');assert.equal(result.item.product.valid,want);checks++;
|
|||
|
|
}
|
|||
|
|
reply=fixture();reply.item.score=null;reply.item.scorePolicyVersion=null;reply.matching.ruleVersion='product-matching-v1';reply.matching.orderingPolicyVersion='product-id-ascending-v1';delete reply.item.productSnapshot.materials;delete reply.item.productSnapshot.bankLogo;
|
|||
|
|
result=await service.fetchMatchDetailRecord('1','4','2');assert.equal(result.item.score,null);assert.equal(result.item.product.materialList.length,0);assert.equal(result.item.product.logo,'');checks++;
|
|||
|
|
for(const [score,policy] of [[101,'product-soft-score-v1'],[-1,'product-soft-score-v1'],[92.2,'product-soft-score-v1'],[80,'unknown-policy']]) {reply=fixture();reply.item.score=score;reply.item.scorePolicyVersion=policy;await assert.rejects(service.fetchMatchDetailRecord('1','4','2'));checks++;}
|
|||
|
|
reply=fixture();reply.item.productSnapshot.bankLogo='javascript:alert(1)';reply.item.productSnapshot.consultPhone='unsafe';result=await service.fetchMatchDetailRecord('1','4','2');assert.equal(result.item.product.logo,'');assert.equal(result.item.product.consultPhone,'');checks++;
|
|||
|
|
reply=fixture();reply.revisionId='3';await assert.rejects(service.fetchMatchDetailRecord('1','4','2'));checks++;
|
|||
|
|
reply=fixture();reply.item.productSnapshot.productId='5';await assert.rejects(service.fetchMatchDetailRecord('1','4','2'));checks++;
|
|||
|
|
console.log('PASS: '+checks+' product presentation UTS checks');
|
|||
|
|
})().catch(e=>{console.error(e);process.exitCode=1;});
|