| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- /**
- * 验证「点卡片 → 打开哪一条详情」的下标反查逻辑。
- *
- * 背景(2026-09-17 用户报的 bug):同一条政策下的多个申报事项会各生成一张卡片,
- * 但适配层把 `title` 与 `declaration_item` 都取自 `card.name.text`(只有政策名),
- * 后端又不下发 `id`/`policy_id`(实测恒为 undefined)——这些卡片在字段上**无法区分**。
- * 原先的 findIndex 只要任一条件命中就返回,于是点第二张卡片也跳到第一张,
- * 表现为「两张卡片的详情内容一模一样」。
- *
- * 验证的不变量:
- * ① 卡片区点击(originalData 是 policies 里的同一对象)必须精确命中自己那一条
- * ② 字段比对**只有唯一命中**才采信;多个候选时返回 -1(交给兜底,不张冠李戴)
- *
- * 怎么跑(在项目根目录):
- * npx esbuild harness/tools/_entry-policy-match.ts --bundle --format=esm \
- * --outfile=harness/tools/_policy-match.mjs
- * node harness/tools/verify-policy-detail-index.mjs
- */
- import { resolvePolicyDetailIndex } from './_policy-match.mjs';
- let pass = 0;
- let fail = 0;
- const check = (name, cond, extra = '') => {
- if (cond) {
- pass++;
- console.log(' ok ' + name);
- } else {
- fail++;
- console.log(' FAIL ' + name + ' ' + extra);
- }
- };
- // ── 复现用户场景:同一政策的两个申报事项 ────────────────────────────────
- // 适配层产出的两个条目:declaration_item 都是政策名,都没有 id
- const POLICY_NAME = '关于进一步完善本区创业扶持政策有关事项的通知';
- const rawA = { declaration_item: POLICY_NAME, support_objects: '本区户籍创业人员' };
- const rawB = { declaration_item: POLICY_NAME, support_objects: '区级考核优秀/良好/合格基地' };
- const policies = [
- { declaration_item: POLICY_NAME, originalData: rawA, support_objects: rawA.support_objects },
- { declaration_item: POLICY_NAME, originalData: rawB, support_objects: rawB.support_objects },
- ];
- console.log('场景:同政策的两个申报事项,declaration_item 与 id 都无法区分\n');
- console.log('【1】卡片区点击(对象同一性——精确路径)');
- check('点第 1 张 → 下标 0', resolvePolicyDetailIndex(policies, policies[0]) === 0, String(resolvePolicyDetailIndex(policies, policies[0])));
- check(
- '点第 2 张 → 下标 1(**修复前这里会返回 0**)',
- resolvePolicyDetailIndex(policies, policies[1]) === 1,
- String(resolvePolicyDetailIndex(policies, policies[1]))
- );
- console.log('\n【2】字段无法区分时不得猜(唯一性要求)');
- // 一个不在 policies 里的对象,但 declaration_item 与两张卡片都相同
- const foreign = { originalData: { declaration_item: POLICY_NAME }, declaration_item: POLICY_NAME };
- check(
- '外来条目 + 两个候选 → 返回 -1(不张冠李戴,交给兜底)',
- resolvePolicyDetailIndex(policies, foreign) === -1,
- String(resolvePolicyDetailIndex(policies, foreign))
- );
- console.log('\n【3】字段唯一命中时仍应采信(退化路径保留)');
- const uniqueRaw = { declaration_item: '某个独占的申报事项' };
- const uniquePolicies = [
- { declaration_item: POLICY_NAME, originalData: rawA },
- { declaration_item: '某个独占的申报事项', originalData: uniqueRaw },
- ];
- check(
- '外来条目 + 唯一 declaration_item 命中 → 正确的下标',
- resolvePolicyDetailIndex(uniquePolicies, { originalData: { declaration_item: '某个独占的申报事项' } }) === 1,
- String(resolvePolicyDetailIndex(uniquePolicies, { originalData: { declaration_item: '某个独占的申报事项' } }))
- );
- const idRaw = { id: 'k_abc123' };
- const idPolicies = [
- { declaration_item: POLICY_NAME, originalData: rawA },
- { declaration_item: POLICY_NAME, originalData: idRaw },
- ];
- check(
- '按 id 唯一命中 → 正确的下标',
- resolvePolicyDetailIndex(idPolicies, { originalData: { id: 'k_abc123' } }) === 1,
- String(resolvePolicyDetailIndex(idPolicies, { originalData: { id: 'k_abc123' } }))
- );
- check(
- 'policy_id 同样可用',
- resolvePolicyDetailIndex(idPolicies, { originalData: { policy_id: 'k_abc123' } }) === 1,
- String(resolvePolicyDetailIndex(idPolicies, { originalData: { policy_id: 'k_abc123' } }))
- );
- console.log('\n【4】边界');
- check('policies 为空 → -1', resolvePolicyDetailIndex([], policies[0]) === -1);
- check('policies 为 null → -1', resolvePolicyDetailIndex(null, policies[0]) === -1);
- check('item 为 null → -1', resolvePolicyDetailIndex(policies, null) === -1);
- check('完全对不上 → -1', resolvePolicyDetailIndex(policies, { originalData: { declaration_item: '不存在的事项' } }) === -1);
- console.log(`\n===== 通过 ${pass} 项,失败 ${fail} 项 =====`);
- process.exit(fail ? 1 : 0);
|