Archived
feat(w05): 数据工单第四轮九连改 —— 笔↔软盘卡角编辑、只选不建、浅蓝题头、镜像修数字
2026-08-31 用户一次点齐九件,逐条落: ① 两行编辑闸退役 → 卡右上角笔(开当前这一面的编辑)↔ 软盘(保存)+ 叉(放弃); 按钮就是平台的 data-edit-open/save/cancel 触发器,快照/取消机制原样,按面显隐全在样式表。 ② 保存一瞬间下拉变数字 → ui-kit mirrorTwins:下拉镜像**选项文案**不镜 value,并把 selected 属性拨到人选的那一项(守卫 CSS 与取消回显都认它)。2 测。 ③ 参数输入框占位提示 → 渲染器 twinInputs 认 data-ph 落成 placeholder(平台小扩面,1 测); 值格「规格书上的值 · 查不到留空」,说明格「补充说明 · 选填」。 ④ 参数说明空着不再摆「建议」→ 什么都不摆(连兜底破折号一起收)。 ⑤ 区序对调:芯片档案在前,比对基准在后。 ⑥ **新建芯片类型整条路移除**(只能选已有类型):抽屉与两张编辑表(种子行/Critical-1 修法/thead 回归网)退役,S1 配方 ②③ 自投影删除(八笔→六笔),gateLedgers 收窄到 profile+parameter,writes 同步,gate_reason 与指导书改口「只选不建」;样例改名 「候选缺库·建档定型」;e2e 案例 0 改走选既有 type_1(type_id=90 那套绕坑法随路退役)。 退役面的七条钉测按仓例 it.skip 留墓志铭(钉的是已移除的路径,不是放松断言)。 ⑦ 题头回浅蓝渐变(原目标件那条 120°),深色夜景只留验收两件。 ⑧ 对话区执行卡不再摆「参考信息」板块(basis 数据照旧随卡走,详情/归档仍有)。 ⑨ 比对基准降噪:字段收成丸(名+硬软徽+单位),说明藏进悬浮气泡指上即看; 类型说明一行截断、悬浮展开。 测:ui-kit 33(mirror 2 新)+ 渲染器 61(ph 1 新)+ 包内 104(38 steps 重排)+ 2525 全仓 四门绿;2.10.0 装库 SQL 六探针全中(hd-light/软盘/data-ph/零表格/无 chip_type 编辑面/ gateLedgers 两张);:8787 已重启载入 data-ph 渲染器。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
This commit is contained in:
@@ -450,7 +450,7 @@ describe('报告模版:编辑面与只读面各就各位', () => {
|
||||
|
||||
it('每个可编辑格子的 data-col 都在对应台账对象的声明里(input-supplement 一屏四张表,四张台账对象的声明并起来看;difference-review 一张表)', () => {
|
||||
const cases: Array<[string, Array<[string, string]>]> = [
|
||||
['input-supplement', [['parts', 'profile'], ['parts', 'chip_type'], ['parts', 'type_param'], ['parts', 'parameter']]],
|
||||
['input-supplement', [['parts', 'profile'], ['parts', 'parameter']]],
|
||||
/* 件② 2026-08-31 起多一张:收口四格可就地改,写向 substitution.relation */
|
||||
['difference-review', [['substitution', 'difference_item'], ['substitution', 'relation']]],
|
||||
];
|
||||
@@ -548,12 +548,12 @@ describe('件① 评估输入补全', () => {
|
||||
expect(steps.find((s) => s.item === 'S1_inputs')?.view).toBe('input-supplement');
|
||||
});
|
||||
|
||||
it('四块都在,行都绑本单草稿(不是整表);档案卡行源是 parts.profile 本身', () => {
|
||||
it('三块都在,行都绑本单草稿(不是整表);档案卡行源是 parts.profile 本身(类型字典只读整表,不再有 mine: 镜像)', () => {
|
||||
expect(html).toContain('data-rows="mine:sub_eval.part"');
|
||||
expect(html).toContain('data-rows="mine:parts.profile"');
|
||||
expect(html).toContain('data-rows="mine:parts.parameter"');
|
||||
expect(html).toContain('data-rows="mine:parts.chip_type"');
|
||||
expect(html).toContain('data-rows="mine:parts.type_param"');
|
||||
expect(html).not.toContain('data-rows="mine:parts.chip_type"');
|
||||
expect(html).not.toContain('data-rows="mine:parts.type_param"');
|
||||
});
|
||||
|
||||
/*
|
||||
@@ -597,16 +597,14 @@ describe('件① 评估输入补全', () => {
|
||||
/* 全只读:选类型在档案卡,建类型在抽屉 —— 基准卡上一个编辑面都不许有 */
|
||||
expect(basis).not.toContain('data-col');
|
||||
expect(basis).not.toContain('data-edit');
|
||||
/* 基准卡不再有表格:类型 + 字段全是瓷贴 */
|
||||
/* 基准卡不再有表格:类型 + 字段全是瓷贴;说明藏进悬浮气泡(降噪,2026-08-31) */
|
||||
expect(basis).not.toContain('<table');
|
||||
expect(basis).toContain('class="ftiles"');
|
||||
/* 抽屉存在,且两张编辑表都住在里面(说明折叠用的是 lab lab-brief,不会被认成这一个) */
|
||||
const labAt = html.indexOf('<details class="lab">');
|
||||
const labEnd = html.indexOf('</details>', labAt);
|
||||
expect(labAt).toBeGreaterThanOrEqual(0);
|
||||
expect(html.indexOf('<table data-edit="parts.chip_type">')).toBeGreaterThan(labAt);
|
||||
expect(html.indexOf('<table data-edit="parts.type_param">')).toBeGreaterThan(labAt);
|
||||
expect(labEnd).toBeGreaterThan(html.indexOf('<table data-edit="parts.type_param">'));
|
||||
expect(html).toContain('.ftile:hover .ft-desc');
|
||||
/* 新建类型抽屉已随「只选不建」退役(2026-08-31 用户定)—— 只剩说明折叠那一只 details */
|
||||
expect(html).not.toContain('<details class="lab">');
|
||||
expect(html).not.toContain('data-edit="parts.chip_type"');
|
||||
expect(html).not.toContain('data-edit="parts.type_param"');
|
||||
});
|
||||
|
||||
/*
|
||||
@@ -631,34 +629,28 @@ describe('件① 评估输入补全', () => {
|
||||
expect(html).toContain('点击翻面');
|
||||
});
|
||||
|
||||
it('主画面无表格:说明折叠之前的正文一张 <table 都没有 —— 表格只活在抽屉里(表单要加行,加行机制认 tr)', () => {
|
||||
const beforeDrawer = html.slice(0, html.indexOf('<details class="lab">'));
|
||||
expect(beforeDrawer).not.toContain('<table');
|
||||
it('整件零表格(2026-08-31 用户:「这个界面都不再需要表格来展示数据了」;抽屉连表带功能一并退役)', () => {
|
||||
expect(html).not.toContain('<table');
|
||||
expect(html).not.toContain('class="jc-tbl-wrap"');
|
||||
});
|
||||
|
||||
it('三级占位:必填红 / 建议橘 —— 空格子直说要不要填(档案卡正面与卡背参数瓷贴两处)', () => {
|
||||
it('占位口径:正面必填红/建议橘;卡背值必填红,说明空着**什么都不摆**(2026-08-31 用户:「没写就什么都不要展示」)', () => {
|
||||
expect(html).toContain('.fcell.req .jc-vcell:empty::after{content:"必填"');
|
||||
expect(html).toContain('.fcell.sug .jc-vcell:empty::after{content:"建议"');
|
||||
expect(html).toContain('.ptile .pv .jc-vcell:empty::after{content:"必填"');
|
||||
expect(html).toContain('.ptile .sg .jc-vcell:empty::after{content:"建议"');
|
||||
expect(html).toContain('.ptile .sg .jc-vcell:empty{display:none}');
|
||||
expect(html).not.toContain('.ptile .sg .jc-vcell:empty::after');
|
||||
});
|
||||
|
||||
it('芯片类型是从台账现读的下拉 —— 写死等于「只能选出包那天就有的那几种」(块①的 chip_type_id 与块②b 的 type_id 都是)', () => {
|
||||
it('芯片类型是从台账现读的下拉 —— 写死等于「只能选出包那天就有的那几种」', () => {
|
||||
expect(html).toContain('data-options="parts.chip_type"');
|
||||
expect(html).toContain('data-option-value="type_id"');
|
||||
expect(html).toContain('data-option-label="type_name"');
|
||||
/* data-options 与 data-slot 不能共存(渲染时 data-slot 会被剥掉)—— 当下值由 data-col 定 */
|
||||
expect(/data-options="[^"]*"[^>]*data-slot=/.test(html)).toBe(false);
|
||||
/* 块①(sub_eval.part 行模版,只有一份行模版,被 data-rows 迭代)绑 chip_type_id 下拉 */
|
||||
/* 档案卡正面绑 chip_type_id 下拉 —— 只选不建(2026-08-31 用户定),type_id 的写入下拉已随抽屉退役 */
|
||||
expect(html).toContain('data-col="chip_type_id" required data-options="parts.chip_type"');
|
||||
/*
|
||||
* 块②b(type_param)绑 type_id 下拉的地方**该出现两次**——已有行的行模版(data-rows
|
||||
* 迭代)一份、种子行(字面量静态行,不受行数所限)一份;只数子串存在会被「只剩其中一份」
|
||||
* 这种退化蒙混过去(已用变异验证逮到:只把动态行模版那份换回裸文本输入,这条子串断言
|
||||
* 仍然为真,因为种子行那份还在——按出现次数数才钉得住两处都在)。
|
||||
*/
|
||||
const typeIdSelectCount = (html.match(/data-col="type_id" required data-options="parts\.chip_type"/g) ?? []).length;
|
||||
expect(typeIdSelectCount).toBe(2);
|
||||
expect(html).not.toContain('data-col="type_id"');
|
||||
});
|
||||
|
||||
/*
|
||||
@@ -667,18 +659,14 @@ describe('件① 评估输入补全', () => {
|
||||
* (查证见 Task 7b 报告)。补一条**不受 `data-rows` 管辖的静态种子行**——两张表各一条,
|
||||
* 字面量手写 `data-col` 输入格,不经 `cell()`/`data-slot`,行数再少也在。
|
||||
*/
|
||||
it('**零行也加得出第一行**:两张表各带一条静态种子行(class="jc-row-static"),不靠 data-rows 生成', () => {
|
||||
const staticRows = html.match(/<tr class="jc-row-static">/g) ?? [];
|
||||
expect(staticRows).toHaveLength(2);
|
||||
/* 种子行里的输入格是手写的,不经 twinInputs —— 直接断言 data-col 存在即可 */
|
||||
expect(html).toContain('<input class="jc-cell" data-col="type_name" placeholder="新类型名称">');
|
||||
expect(html).toContain('<input class="jc-cell" data-col="description"');
|
||||
expect(html).toContain('<input class="jc-cell" data-col="param_name" placeholder="参数名">');
|
||||
expect(html).toContain('<input class="jc-cell" data-col="param_desc"');
|
||||
expect(html).toContain('<select class="jc-cell" data-col="constraint_type">');
|
||||
expect(html).toContain('<input class="jc-cell" data-col="param_unit"');
|
||||
/* 种子行只在编辑态露面 —— 读的时候不该看见一行空壳子(界面不撒谎) */
|
||||
expect(html).toContain('table:not(.on) tr.jc-row-static { display: none; }');
|
||||
/*
|
||||
* SKIP(2026-08-31 用户定「把添加芯片类型的功能从这个活动中移除,只能选择已有类型」):
|
||||
* 新建类型抽屉连同两张编辑表(静态种子行 / type_id 禁用 data-col 的 Critical-1 修法 /
|
||||
* thead 后置回归网 / data-edit 双写)整体退役 —— 这些钉的是已移除的创建路径,不是被放松的
|
||||
* 断言。平台侧机制钉测(view-render-addrow-thead / view-table-edit)不随本活动退役。
|
||||
*/
|
||||
it.skip('**零行也加得出第一行**:两张表各带一条静态种子行(class="jc-row-static"),不靠 data-rows 生成', () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
|
||||
/*
|
||||
@@ -696,17 +684,14 @@ describe('件① 评估输入补全', () => {
|
||||
* 钉住修法:`type_id` 必须挂 `data-col`,且必须是禁用的 —— 人看得见「由系统生成」
|
||||
* 这句占位,但怎么点都改不了它的值。
|
||||
*/
|
||||
it('**新建类型的种子行:type_id 挂 data-col、但禁用恒空**(2026-08-30 修 Critical 1 —— 漏挂会让 resolveRowKey 的"全表一致"把新建的类型误判成既有那一行,静默覆盖它)', () => {
|
||||
expect(html).toContain('由系统生成');
|
||||
// 「由系统生成」只出现在 chip_type 那条种子行里 —— 精确抓出那一行
|
||||
const chipTypeStaticRow = /<tr class="jc-row-static">(?:(?!<\/tr>)[\s\S])*?由系统生成(?:(?!<\/tr>)[\s\S])*?<\/tr>/.exec(html)?.[0] ?? '';
|
||||
expect(chipTypeStaticRow).not.toBe('');
|
||||
/* 必须是一个真的 <input data-col>(collect() 只认 input/select/textarea[data-col]),
|
||||
不能是纯文本 <span> —— 否则这一格永远不会出现在回传的 cells 里,barred 的保护无从谈起 */
|
||||
expect(chipTypeStaticRow).toMatch(/<input[^>]*data-col="type_id"[^>]*disabled/);
|
||||
/* disabled 意味着人怎么点都改不了它的值 —— 保存时这一格恒是空串,才谈得上「barred」 */
|
||||
expect(chipTypeStaticRow).toContain('data-col="type_name"');
|
||||
expect(chipTypeStaticRow).toContain('data-col="description"');
|
||||
/*
|
||||
* SKIP(2026-08-31 用户定「把添加芯片类型的功能从这个活动中移除,只能选择已有类型」):
|
||||
* 新建类型抽屉连同两张编辑表(静态种子行 / type_id 禁用 data-col 的 Critical-1 修法 /
|
||||
* thead 后置回归网 / data-edit 双写)整体退役 —— 这些钉的是已移除的创建路径,不是被放松的
|
||||
* 断言。平台侧机制钉测(view-render-addrow-thead / view-table-edit)不随本活动退役。
|
||||
*/
|
||||
it.skip('**新建类型的种子行:type_id 挂 data-col、但禁用恒空**(2026-08-30 修 Critical 1 —— 漏挂会让 resolveRowKey 的"全表一致"把新建的类型误判成既有那一行,静默覆盖它)', () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
|
||||
it('**主键列必挂 `data-col`** —— 它不是编辑面,是行的钥匙(漏了会把人改的行错配到别行上)', () => {
|
||||
@@ -714,10 +699,28 @@ describe('件① 评估输入补全', () => {
|
||||
expect(html).toContain('data-col="param_name"');
|
||||
});
|
||||
|
||||
it('可改的三张表 + 档案卡各有一道编辑闸', () => {
|
||||
for (const address of ['parts.profile', 'parts.chip_type', 'parts.type_param', 'parts.parameter']) {
|
||||
expect(html).toContain(`data-edit="${address}"`);
|
||||
/*
|
||||
* 2026-08-31 用户定:两行编辑闸退役,换成卡右上角的笔↔软盘 —— 笔开当前这一面的编辑
|
||||
* (正面=主数据 / 背面=参数值),软盘保存,叉放弃。按钮就是平台认的 data-edit-open /
|
||||
* data-edit-save / data-edit-cancel 触发器,快照与取消机制原样。
|
||||
*/
|
||||
it('编辑收进卡角:笔(open)/软盘(save)/叉(cancel)正反两面各一套;地址只剩 profile 与 parameter', () => {
|
||||
for (const address of ['parts.profile', 'parts.parameter']) {
|
||||
expect(html).toContain(`data-edit-open="${address}"`);
|
||||
expect(html).toContain(`data-edit-save="${address}"`);
|
||||
expect(html).toContain(`data-edit-cancel="${address}"`);
|
||||
}
|
||||
/* 老的闸行不再出现在正文里(样式表里的基座规则给 ② 用,不算) */
|
||||
expect(html.slice(html.indexOf('</style>'))).not.toContain('jc-editgate');
|
||||
/* 笔↔软盘的按面显隐由样式表判 */
|
||||
expect(html).toContain('.dossiers.on .disk-f{display:grid}');
|
||||
expect(html).toContain(".dossier:has(.pback.on) .disk-b{display:grid}");
|
||||
/* 参数瓷贴的输入孪生件带占位提示(渲染器认 data-ph) */
|
||||
expect(html).toContain('data-ph="规格书上的值 · 查不到留空"');
|
||||
expect(html).toContain('data-ph="补充说明 · 选填"');
|
||||
/* 题头回浅蓝渐变(2026-08-31 用户:「标题背景还是改成之前的那种蓝色渐变」) */
|
||||
expect(html).toContain('class="card hd-light"');
|
||||
expect(html).toContain('linear-gradient(120deg,#f0f5ff 0%,#fff 55%,#eef4ff 100%)');
|
||||
});
|
||||
|
||||
/*
|
||||
@@ -727,11 +730,14 @@ describe('件① 评估输入补全', () => {
|
||||
* 内层 `data-rows` 那个 `<tbody>` 一处(给 `renderRows` 的 `editable` 检测看,
|
||||
* 它只认与 `data-rows` 同一个标签自带的属性,不看祖先)。
|
||||
*/
|
||||
it('新建类型 / 新建字段两张表的 data-edit 各出现两次(外层 table + 内层 data-rows tbody)', () => {
|
||||
for (const address of ['parts.chip_type', 'parts.type_param']) {
|
||||
const count = (html.match(new RegExp(`data-edit="${address}"`, 'g')) ?? []).length;
|
||||
expect(count, address).toBe(2);
|
||||
}
|
||||
/*
|
||||
* SKIP(2026-08-31 用户定「把添加芯片类型的功能从这个活动中移除,只能选择已有类型」):
|
||||
* 新建类型抽屉连同两张编辑表(静态种子行 / type_id 禁用 data-col 的 Critical-1 修法 /
|
||||
* thead 后置回归网 / data-edit 双写)整体退役 —— 这些钉的是已移除的创建路径,不是被放松的
|
||||
* 断言。平台侧机制钉测(view-render-addrow-thead / view-table-edit)不随本活动退役。
|
||||
*/
|
||||
it.skip('新建类型 / 新建字段两张表的 data-edit 各出现两次(外层 table + 内层 data-rows tbody)', () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
|
||||
/*
|
||||
@@ -758,20 +764,14 @@ describe('件① 评估输入补全', () => {
|
||||
* 谁若把 `<thead>` 挪回两个 `<tbody>` 之前(哪怕只改一张表),这条测试立刻标红,
|
||||
* 提醒去核对 `view-render-addrow-thead.test.ts` 是否也需要同步。
|
||||
*/
|
||||
it('**回归安全网**:两张新表的 <thead> 都排在两个 <tbody> 之后(不是最前面)—— 与 view-render-addrow-thead.test.ts 的假设锁在一起', () => {
|
||||
for (const address of ['parts.chip_type', 'parts.type_param']) {
|
||||
const tableStart = html.indexOf(`<table data-edit="${address}">`);
|
||||
expect(tableStart, address).toBeGreaterThanOrEqual(0);
|
||||
const tableEnd = html.indexOf('</table>', tableStart);
|
||||
const tableHtml = html.slice(tableStart, tableEnd);
|
||||
const theadAt = tableHtml.indexOf('<thead>');
|
||||
const tbodyPositions = [...tableHtml.matchAll(/<tbody/g)].map((m) => m.index ?? -1);
|
||||
expect(theadAt, `${address}: 找不到 <thead>`).toBeGreaterThanOrEqual(0);
|
||||
expect(tbodyPositions.length, `${address}: 应有两个 <tbody>`).toBe(2);
|
||||
// <thead> 必须排在两个 <tbody> 的开标签**之后**(源码序;视觉呈现由 CSS 的
|
||||
// table-header-group 保证仍在最前,与源码序无关)
|
||||
for (const pos of tbodyPositions) expect(theadAt, address).toBeGreaterThan(pos);
|
||||
}
|
||||
/*
|
||||
* SKIP(2026-08-31 用户定「把添加芯片类型的功能从这个活动中移除,只能选择已有类型」):
|
||||
* 新建类型抽屉连同两张编辑表(静态种子行 / type_id 禁用 data-col 的 Critical-1 修法 /
|
||||
* thead 后置回归网 / data-edit 双写)整体退役 —— 这些钉的是已移除的创建路径,不是被放松的
|
||||
* 断言。平台侧机制钉测(view-render-addrow-thead / view-table-edit)不随本活动退役。
|
||||
*/
|
||||
it.skip('**回归安全网**:两张新表的 <thead> 都排在两个 <tbody> 之后(不是最前面)—— 与 view-render-addrow-thead.test.ts 的假设锁在一起', () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
|
||||
/*
|
||||
@@ -799,14 +799,14 @@ describe('件① 评估输入补全', () => {
|
||||
* 只读态与编辑态下「#」列逐行都是空白。钉死 `.jc-tbl-wrap` 现在也接了这五条规则,
|
||||
* 且这张件确实只用 `.jc-tbl-wrap`(没有表在用没打这条补丁就会数不出来的 `.tbl-wrap`)。
|
||||
*/
|
||||
it('抽屉里两张表的序号列真的会数:.jc-tbl-wrap 也接了 CSS 计数器(不再只认 .tbl-wrap)', () => {
|
||||
expect(html).toMatch(/\.jc-tbl-wrap\s+table\s*,\s*\.tbl-wrap\s+table\s*\{\s*counter-reset:\s*rn;?\s*\}/);
|
||||
expect(html).toMatch(/\.jc-tbl-wrap\s+table\s+td\.rn\s*,\s*\.tbl-wrap\s+table\s+td\.rn\s*\{\s*counter-increment:\s*rn;?\s*\}/);
|
||||
expect(html).toMatch(/\.jc-tbl-wrap\s+table\s+td\.rn\s+\.jc-rn-num::before\s*,\s*\.tbl-wrap\s+table\s+td\.rn\s+\.jc-rn-num::before\s*\{\s*content:\s*counter\(rn\);?\s*\}/);
|
||||
// 只剩抽屉里两张(2026-08-31 第三轮:基准卡瓷贴化、参数值上卡背 —— 主画面零表格)
|
||||
expect(html).not.toContain('class="tbl-wrap"');
|
||||
const jcTblWrapCount = html.match(/class="jc-tbl-wrap"/g)?.length ?? 0;
|
||||
expect(jcTblWrapCount).toBe(2);
|
||||
/*
|
||||
* SKIP(2026-08-31 用户定「把添加芯片类型的功能从这个活动中移除,只能选择已有类型」):
|
||||
* 新建类型抽屉连同两张编辑表(静态种子行 / type_id 禁用 data-col 的 Critical-1 修法 /
|
||||
* thead 后置回归网 / data-edit 双写)整体退役 —— 这些钉的是已移除的创建路径,不是被放松的
|
||||
* 断言。平台侧机制钉测(view-render-addrow-thead / view-table-edit)不随本活动退役。
|
||||
*/
|
||||
it.skip('抽屉里两张表的序号列真的会数:.jc-tbl-wrap 也接了 CSS 计数器(不再只认 .tbl-wrap)', () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1068,10 +1068,9 @@ describe.skip('徽标别名与值域相关的坑(2026-08-27 实测账,回归网)
|
||||
*/
|
||||
describe('可编辑件的主键与必填列(2026-08-27 复审:主键丢钥匙 / 必填填不了,两条 Critical 回归;Task 7b 补 parts.chip_type)', () => {
|
||||
/** input-supplement 一屏四张真能编辑的表与它们各自绑定的台账对象(Task 7b 加入 parts.chip_type) */
|
||||
/* 2026-08-31「只选不建」:chip_type / type_param 不再是可编辑面,从名单撤下 */
|
||||
const EDITABLE: ReadonlyArray<{ view: string; domain: string; object: string }> = [
|
||||
{ view: 'input-supplement', domain: 'parts', object: 'profile' },
|
||||
{ view: 'input-supplement', domain: 'parts', object: 'chip_type' },
|
||||
{ view: 'input-supplement', domain: 'parts', object: 'type_param' },
|
||||
{ view: 'input-supplement', domain: 'parts', object: 'parameter' },
|
||||
];
|
||||
|
||||
|
||||
@@ -146,10 +146,10 @@ describe('S1 配方', () => {
|
||||
* 变成空字符串)见 `apps/api/src/modules/loop-engine/__tests__/w05-gate-reason-order.test.ts`
|
||||
* ——这份文件只做结构断言,不跑引擎(活动包不许 import apps/*)。
|
||||
*/
|
||||
it('八笔,次序是:两颗料 → 类型字典自投 → 字段清单自投 → 主数据骨架 → 参数骨架 → 案卷 → 卡 → 交代', () => {
|
||||
expect(kinds).toEqual(['project', 'project', 'project', 'project', 'project', 'project', 'card', 'say']);
|
||||
it('六笔,次序是:两颗料 → 主数据骨架 → 参数骨架 → 案卷 → 卡 → 交代(类型字典/字段清单两笔自投影已随「只选不建」退役)', () => {
|
||||
expect(kinds).toEqual(['project', 'project', 'project', 'project', 'card', 'say']);
|
||||
expect(acts.map((a) => (a.kind === 'project' ? a.into : undefined)).filter(Boolean)).toEqual([
|
||||
'sub_eval.part', 'parts.chip_type', 'parts.type_param', 'parts.profile', 'parts.parameter', 'sub_eval.case',
|
||||
'sub_eval.part', 'parts.profile', 'parts.parameter', 'sub_eval.case',
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -165,21 +165,13 @@ describe('S1 配方', () => {
|
||||
* 跳过已落地的行(loop-engine/port.ts),prune 回来:没落地的陈旧选型照撤,
|
||||
* 已落地的原地留下 —— 案例 2 不再炸,用户那条路清得干净。
|
||||
*/
|
||||
it('②③ 两笔自投影都读 sub_eval.part 的 chip_type_id 去查字典/字段清单,原样抄回自己(带 prune,已落地由基座跳过)', () => {
|
||||
const chipType = acts[1];
|
||||
expect(chipType?.kind === 'project' && chipType.into).toBe('parts.chip_type');
|
||||
expect(chipType?.kind === 'project' && chipType.prune).toBe(true);
|
||||
expect(chipType?.kind === 'project' && chipType.from).toMatchObject({
|
||||
each: 'mine:sub_eval.part',
|
||||
then: { each: 'parts.chip_type', where: { type_id: { outer: 'chip_type_id' } } },
|
||||
});
|
||||
const typeParam = acts[2];
|
||||
expect(typeParam?.kind === 'project' && typeParam.into).toBe('parts.type_param');
|
||||
expect(typeParam?.kind === 'project' && typeParam.prune).toBe(true);
|
||||
expect(typeParam?.kind === 'project' && typeParam.from).toMatchObject({
|
||||
each: 'mine:sub_eval.part',
|
||||
then: { each: 'parts.type_param', where: { type_id: { outer: 'chip_type_id' } } },
|
||||
});
|
||||
/*
|
||||
* SKIP(2026-08-31 用户定「只选不建」):②③ 两笔自投影连同 gateLedgers 上那两张表
|
||||
* 一并退役 —— 类型只许从字典里选,选中的行本来就在正式表里,镜像与落地都失去了对象。
|
||||
* 这条钉的机制(prune + skipLanded)仍活在 auto-runner 测试里,不随本活动退役。
|
||||
*/
|
||||
it.skip('②③ 两笔自投影都读 sub_eval.part 的 chip_type_id 去查字典/字段清单,原样抄回自己(带 prune,已落地由基座跳过)', () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
|
||||
it('案号由 let 铸,只从本单开案时刻取材', () => {
|
||||
@@ -203,7 +195,7 @@ describe('S1 配方', () => {
|
||||
* 「加一行」),必须换成说实情、给真出路的话:没法比出差异,终止重开。
|
||||
*/
|
||||
it('gate_reason 第一档:两参必填之后只剩"填成同一个号"这条残余路径,文案不再指向不存在的"补两格"', () => {
|
||||
const kase = acts[5];
|
||||
const kase = acts[3];
|
||||
const fields = kase?.kind === 'project' ? kase.fields : undefined;
|
||||
const gateReason = fields?.['gate_reason'] as { when?: string; then?: string } | undefined;
|
||||
expect(gateReason?.when).toBe('sub_eval_part_rows < 2');
|
||||
@@ -213,7 +205,7 @@ describe('S1 配方', () => {
|
||||
});
|
||||
|
||||
it('参数骨架:两颗料都铺、值回填现值 —— 「在库但当年参数没录全」也要被拦住', () => {
|
||||
const params = acts[4];
|
||||
const params = acts[2];
|
||||
/* 'live':人加不了行的表,quiet 拍也撤 —— 改类型后旧参数行跟手消失(2026-08-31 用户点名「只会变多不会变少」) */
|
||||
expect(params?.kind === 'project' && params.prune).toBe('live');
|
||||
const from = params?.kind === 'project' ? params.from : undefined;
|
||||
@@ -224,7 +216,7 @@ describe('S1 配方', () => {
|
||||
});
|
||||
|
||||
it('**发卡的条件全是基座读数** —— 不许拿 `gate_reason != ""` 当条件', () => {
|
||||
const card = acts[6];
|
||||
const card = acts[4];
|
||||
const when = card?.kind === 'card' ? (card.when ?? '') : '';
|
||||
/*
|
||||
* S-FEEL 里**未绑定的名字 `!= ""` 求值为 true**,而 `gate_reason` 为空串时那一列压根不写、
|
||||
@@ -245,16 +237,16 @@ describe('S1 配方', () => {
|
||||
* (2026-08-30 真跑 e2e 撞见)。现在四张表都在闸上、也都会一起落地。
|
||||
*/
|
||||
it('卡:数据工单、四张表都在闸上(含 parts.chip_type/parts.type_param,Ruling H35)、且有 basis(基座拒发 basis 为空的工单)', () => {
|
||||
const card = acts[6];
|
||||
const card = acts[4];
|
||||
expect(card?.kind === 'card' && card.as).toBe('execution');
|
||||
expect(card?.kind === 'card' && card.variant).toBe('data');
|
||||
expect(card?.kind === 'card' && card.gateLedgers).toEqual(['parts.chip_type', 'parts.type_param', 'parts.profile', 'parts.parameter']);
|
||||
expect(card?.kind === 'card' && card.gateLedgers).toEqual(['parts.profile', 'parts.parameter']);
|
||||
expect((card?.kind === 'card' ? card.basis ?? [] : []).length).toBeGreaterThan(0);
|
||||
expect((card?.kind === 'card' ? card.guide ?? [] : []).length).toBeGreaterThanOrEqual(3);
|
||||
});
|
||||
|
||||
it('发卡条件与 doneWhen 是同一件事的正反面', () => {
|
||||
const when = acts[6]?.kind === 'card' ? (acts[6].when ?? '') : '';
|
||||
const when = acts[4]?.kind === 'card' ? (acts[4].when ?? '') : '';
|
||||
for (const reading of [
|
||||
'sub_eval_part_exists_status_found', 'sub_eval_part_missing',
|
||||
'sub_eval_part_distinct_chip_type_id', 'parts_profile_missing', 'parts_parameter_missing',
|
||||
|
||||
Reference in New Issue
Block a user