Skip to content

两处 filter-operator 平价测试从 spec 词表里减去 is_empty / is_not_empty,但没有一条断言这两个 token 仍在词表里 #3628

Description

@yinlianghui

发现于 #3601 / PR #3623(修那单时顺手排查同类结构,未在该 PR 修)。

现象

两个 spec 平价测试各自维护一个排除集,从 spec 派生的 VIEW_FILTER_OPERATORS 里减去同样两个 token:

  • packages/plugin-list/src/__tests__/filter-operator-ast-parity.test.ts:35 —— HANDLED_BEFORE_MAPPING = new Set(['is_empty', 'is_not_empty'])
  • packages/data-objectstack/src/filter-operator-ast-parity.test.ts:34 —— NOT_THIS_ADAPTERS_JOB = new Set(['is_empty', 'is_not_empty'])

两处的排除理由都成立(视图层在 mapOperator 被问到之前就把这两个改写成 [field, '=' | '!=', null],所以它们不需要 AST 拼写)。缺的是排除项本身的存活断言:没有任何一条断言 is_empty / is_not_empty 仍然是 VIEW_FILTER_OPERATORS 的成员。

一旦上游把这两个 token 从视图词表里退役或改名,排除集就变成一次空减法 —— 平价扫描依然全绿(它对剩下的 token 仍然是完整的),但排除行成了死重,注释还会继续告诉读者「视图层会先改写这两个」,而那时视图词表里已经没有它们了。

现状测量(objectui origin/main,@objectstack/spec@17.0.0-rc.5)

VIEW_FILTER_OPERATORS count: 19
is_empty       LIVE in spec
is_not_empty   LIVE in spec

今天两条都还在,排除是有效的 —— 这条是预防性的,不是已兑现的腐化。

为什么标 finding

今天没有用户会碰到:测试绿,行为无影响,排除项当前全部有效。代价是结构性的 —— 这正是 #3601 里 82 条拒绝名单烂掉 37 条的同一个形状:一份手写清单挂在 spec 派生的词表旁边,却没有一条断言清单成员仍然存在于那份词表#3601 的 37 条恰恰是没人给它加存活断言,才一路积累到只有做审计时才被量出来。

对照组:仓里同类结构里,有两处已经把这件事做对了,可以直接抄——

  • packages/fields/src/widgets/__tests__/FilterConditionField.operators.test.ts:117 —— PR chore(deps): track the @objectstack family at 17.0.0-rc.5 and restore green #3568KNOWN_UNREACHABLE 加的「每个排除 token 仍是 spec operator」断言。
  • packages/plugin-charts/src/__tests__/chart-type-spec-parity.test.tsx —— TRACKED_DIALECT 在 spec 收编条目时 console.info 提示删除,并在注释里写明它是上界而非期望。

反过来,FlowReferenceField.specDerivation.test.tsEXPECTED_KINDS 是双向 pin + 显式反空断言,不属此类,无需处理。

建议处置(供参考,非结论)

每个文件加三行,与 PR #3568 同手法:

it('every excluded operator is still in the spec view vocabulary', () => {
  for (const op of HANDLED_BEFORE_MAPPING) {
    expect(
      VIEW_FILTER_OPERATORS.includes(op),
      `'${op}' is excluded from the bridge sweep but the spec no longer lists it`,
    ).toBe(true);
  }
});

严重性交 PM triage 判定,不自评。


Generated by Claude Code

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions