Skip to content

fix(test): 拒绝两种静默假绿的 vitest 调用,并把正确跑法写进 AGENTS.md - #3437

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-3378-pkg-test-false-green
Aug 6, 2026
Merged

fix(test): 拒绝两种静默假绿的 vitest 调用,并把正确跑法写进 AGENTS.md#3437
yinlianghui merged 1 commit into
mainfrom
claude/issue-3378-pkg-test-false-green

Conversation

@yinlianghui

@yinlianghui yinlianghui commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Fixes #3378
Fixes #3288

(注:正文一律用 PKG / PATHS 当占位符,不写尖括号 —— GitHub 的正文消毒会把「尖括号+字母」
当成 HTML 标签整段吃掉,第一版正文里的占位符就是这么消失的。)

前提复核(两条都在 origin/main 上原样复现)

#3378 —— 包级 cwd 跑 vitest:

$ cd packages/app-shell ; pnpm exec vitest list --filesOnly
[@object-ui/console] ../../apps/console/src/LocalizationFetchProvider.test.tsx
[@object-ui/console] ../../apps/console/src/__tests__/preview-samples-spec-valid.test.ts
...  (22 行,全部是 @object-ui/console;app-shell 自己 281 个文件一个都没有)

#3288 —— 路径挂在 -- 后面:

$ pnpm --filter @object-ui/fields test -- --run packages/fields/src/widgets/useRecordQuery.test.ts
   实际执行: vitest run -- --run packages/fields/src/widgets/useRecordQuery.test.ts
 Test Files  22 passed (22)      # 又是 console 的 22 个;点名的那个文件零执行
 EXIT=0

补一条 issue 正文没写、同族的第三种:仓根跑但路径写错/写歪,passWithNoTests: true
把它变成绿的 ——

$ pnpm exec vitest run packages/fields/src/does-not-exist.test.ts   # main
 EXIT=0

共同点是没有任何 0-match 信号:计数是 22 不是 0,passWithNoTests 甚至没参与判定。
按「包级验证」约定干活的 agent 会据此报「整包绿」。

机制

vitest 把 root 定成 cwd。根级 projects(unit/dom/dom-heavy)的 include
相对 rootpackages/** / examples/** / scripts/**,从 packages/app-shell 里看就成了
packages/app-shell/packages/**,匹配不到任何文件;唯一还解析得成功的是以绝对路径引进来的
apps/console project。于是收集到 22 个别人的文件,跑绿,退出 0。

-- 那条是另一半:pnpm 把 -- 原样转发进脚本,vitest 的 CLI 解析在 -- 处停止,后面的
一切在 vitest 看到之前就不存在了 —— 不是「忽略并警告」,是压根没传进去。

改了什么

没动的东西:17 个 per-package vitest.config.ts(那是 #3240,已上抛维护者)、39 条包级
test 脚本、.github/workflows/**、任何 package 源码。

关于 #3288 里的方向 C(改写包级脚本转发路径)—— 评估后没做

test 脚本改成 vitest run --root ../.. packages/PKG/ 能让 pnpm --filter PKG test 真跑
起来,但它要改 39 个脚本,并且会把 turbo run test 从「一个几乎空转的假绿」变成「39 个真跑」——
ci.yml 的注释明确写着不要跑 turbo run test(多个包配置继承根 project 列表,会重复大段套件)。
更关键的是:包级脚本该不该存在本身就是 #3240 的议题,让它们「能用」等于替维护者提前定了案。
现在它们只是失败,不再撒谎 —— 这既满足本 PR 的目标,也不占 #3240 的位。

验证矩阵(方向都是先预测再跑的)

# 调用 预测 实际
1 包目录里 pnpm exec vitest list(#3378 的复现命令) 拒绝 exit 1 + #3378 报错框
2 pnpm --filter @object-ui/fields test -- --run PATH 拒绝,并同时点出两条 exit 1,正文含 #3288#3378
3 仓根 pnpm exec vitest run packages/fields/src/widgets/useRecordQuery.test.ts 照常绿 Test Files 1 passed (1) / Tests 10 passed
4 CI 形状 pnpm test --shard=1/4 --project unit 不受影响 Test Files 94 passed (94) / Tests 1313 passed, 1 skipped
5 pnpm --filter @object-ui/app-shell test(无路径参数) 应当失败(它收集的是别人的包) exit 1 + #3378 报错框
6 仓根 + 不存在的路径 由 main 的 exit 0 变 exit 1 exit 1(guard)
7 仓根 + 零匹配的子串过滤 由 main 的 exit 0 变 exit 1 exit 1 No test files found

反向验证(把 guard 关掉,看是否原样退回旧行为):

$ OBJECTUI_VITEST_GUARD=off pnpm --filter @object-ui/app-shell exec vitest list --filesOnly
[@object-ui/console] ../../apps/console/src/LocalizationFetchProvider.test.tsx ...
collected files: 22

—— 底层 vitest 行为一点没变,变的只是「它现在会被拦下」。

guard 自身的单测:pnpm exec vitest run scripts/__tests__/vitest-invocation-guard.test.ts
Test Files 1 passed (1) / Tests 23 passed (23),其中两条钉住根配置确实接了线
(assertCanonicalVitestInvocation(...) 在位、passWithNoTests 不再是硬编码 true),
否则 guard 就成了「测试很齐、没人调用」的摆设。

node scripts/check-control-bytes.mjs → OK(3630 个 tracked 文本文件);另按
[\x00-\x08\x0b\x0c\x0e-\x1f] 自查四个改动文件,无命中。

type-check:改动全部落在 vitest.config.mts / scripts/ / AGENTS.md,而每个包的 tsconfig
include 都只到 src,apps/console/tsconfig.node.json 收的是 ../../scripts/vite-*.ts
(匹配不到 vitest-invocation-guard.mjs)—— 没有任何 tsconfig 覆盖到本次改动。作为实证跑了
tsc -b apps/console/tsconfig.node.json --force → exit 0。

changeset:按仓内先例(#3253 / #3273 / #3278 等纯 infra/CI 改动均无 changeset)不加 —— 本 PR
不触及任何已发布包的源码。

两条调用方式会在「一个目标测试都没跑」的情况下报绿,且没有任何 0-match 信号:

- #3378 包级 cwd:`pnpm --filter <pkg> test` / `cd packages/x && pnpm exec vitest`。
  vitest 把 root 定成该目录,根级 projects 的 include(packages/**、examples/**、
  scripts/**)相对它匹配不到任何文件,只有以绝对路径引入的 apps/console project
  仍解析成功 —— 于是跑 @object-ui/console 的 22 个文件并报
  `Test Files 22 passed (22)`,本包(app-shell 281 个)一个没跑。
- #3288 `-- <paths>`:pnpm 把 `--` 原样转发,vitest 的解析在 `--` 处停止,路径过滤
  在 vitest 看到之前就没了,退回默认集合(叠加上一条即别人的包)后全绿。

scripts/vitest-invocation-guard.mjs 在 vitest.config.mts 顶部拦下两者:vitest root
不是仓根 → 拒绝;`--` 之后还有参数 → 拒绝;点名了具体文件却不存在 → 拒绝。并且
`passWithNoTests` 改为只在「命令行没点名任何文件」时才为 true —— 过滤零匹配从此非零退出。
报错正文写清机制并给出唯一正确跑法(仓根 `pnpm exec vitest run <paths>`),AGENTS.md
同步落成条文。

不动 17 个 per-package vitest.config.ts,也不改 39 条包级 test 脚本(#3240 另议):
它们现在只是失败,不再撒谎。CI 的根级调用(pnpm test --shard=N/4)完全不受影响。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
@vercel

vercel Bot commented Aug 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectui Ignored Ignored Aug 6, 2026 4:04am

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation configuration tests labels Aug 6, 2026
@yinlianghui
yinlianghui marked this pull request as ready for review August 6, 2026 04:42
@yinlianghui
yinlianghui added this pull request to the merge queue Aug 6, 2026
Merged via the queue into main with commit 34a3bad Aug 6, 2026
15 of 16 checks passed
@yinlianghui
yinlianghui deleted the claude/issue-3378-pkg-test-false-green branch August 6, 2026 04:42
akarma-synetal pushed a commit to akarma-synetal/objectui that referenced this pull request Aug 6, 2026
objectstack-ai#3443)

QUICK_REFERENCE.md 和 skills/objectui/guides/project-setup.md 两处入门文档,
把 objectstack-ai#3378 那条会静默假绿的调用当推荐用法写着。按该机制,vitest 的 root 落在包
目录,根级 unit/dom/dom-heavy 三个 project 的 include 相对它匹配不到任何文件,
只有以绝对路径引入的 apps/console project 仍解析成功 —— 跑的是 console 的 22
个文件、报绿,注释声称的那个包一个都没跑。

PR objectstack-ai#3437 合并后 vitest.config.mts 的 invocation guard 会让这些命令直接非零退出,
所以文档教的命令现在不只是误导,而是根本跑不通。三处全部换成仓根跑法,并把 guard
实际打印的正确跑法摘录进来,便于读者在别处撞见该错误框时认得出。

- QUICK_REFERENCE.md: --filter console test / --filter core test 两行
  → pnpm exec vitest run packages/core/ | apps/console/ | packages/core/src/<file>.test.ts
- project-setup.md: --filter core test 一行 → 同上(单独拆出 Scoped tests 段,
  因为它和同块的 --filter build / --filter dev 不同,不能用 --filter 表达)

单文件示例一律写成 <file> 占位符:guard 的 missing-path-filter 分支会拒绝指向
不存在文件的具体路径,写个看似真实的 x.test.ts 反而会被拒。

content/docs/guide/plugin-development.md:422 本就是正确形状,未改动。
与 objectstack-ai#3240(包级 test 脚本存废)无关 —— 无论存废,文档都该教仓根跑法。

Fixes objectstack-ai#3442


Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

configuration documentation Improvements or additions to documentation tests

Projects

None yet

2 participants