test(di): guard against duplicate Symbol.for DI token strings#2580
Conversation
Symbol.for(key) resolves through the global registry, so two token consts in different files that pass the same string are the same symbol — binding two services to it is last-load-wins with no error, and the wrong service resolves at runtime. Add a test that scans packages/ and apps/ source files and fails if any Symbol.for() token string is defined in more than one production file, reporting each colliding site so the fix is to namespace them distinctly (posthog.<area>.<thing>). Note: this test fails on main until #2579 (which namespaces the colliding githubConnect tokens) merges. Generated-By: PostHog Code Task-Id: ab590a64-c7b3-45eb-b381-083a3c75b3f0
Prompt To Fix All With AIFix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
packages/di/src/tokenUniqueness.test.ts:79-101
**Prefer a parameterised test shape**
The team convention is `it.each` for data-driven assertions. You can compute the collisions at describe scope so vitest receives one test case per violation, making individual failures immediately visible in the reporter without having to parse the aggregate message string.
One common pattern to avoid the "0 test cases" warning when no collisions exist is to fall back to a trivial sentinel `it`; but even a top-level `it.each(collisions)(…)` with an empty array is fine in modern vitest — it simply produces no failures.
Reviews (1): Last reviewed commit: "Merge branch 'main' into posthog-code/di..." | Re-trigger Greptile |
| describe("DI token Symbol.for uniqueness", () => { | ||
| it("never defines the same Symbol.for string in more than one source file", () => { | ||
| const byString = findTokenStrings(); | ||
|
|
||
| const collisions = [...byString.entries()].filter(([, sites]) => { | ||
| const distinctFiles = new Set(sites.map((s) => s.file)); | ||
| return distinctFiles.size > 1; | ||
| }); | ||
|
|
||
| const report = collisions | ||
| .map(([key, sites]) => { | ||
| const lines = sites.map((s) => ` ${s.name} @ ${s.file}`).join("\n"); | ||
| return ` Symbol.for("${key}") is defined in multiple files:\n${lines}`; | ||
| }) | ||
| .join("\n\n"); | ||
|
|
||
| expect( | ||
| collisions.length, | ||
| collisions.length === 0 | ||
| ? "" | ||
| : `Duplicate DI token string(s) found — these resolve to the SAME symbol and will silently shadow each other. Namespace them distinctly (posthog.<area>.<thing>):\n\n${report}\n`, | ||
| ).toBe(0); | ||
| }); |
There was a problem hiding this comment.
Prefer a parameterised test shape
The team convention is it.each for data-driven assertions. You can compute the collisions at describe scope so vitest receives one test case per violation, making individual failures immediately visible in the reporter without having to parse the aggregate message string.
One common pattern to avoid the "0 test cases" warning when no collisions exist is to fall back to a trivial sentinel it; but even a top-level it.each(collisions)(…) with an empty array is fine in modern vitest — it simply produces no failures.
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/di/src/tokenUniqueness.test.ts
Line: 79-101
Comment:
**Prefer a parameterised test shape**
The team convention is `it.each` for data-driven assertions. You can compute the collisions at describe scope so vitest receives one test case per violation, making individual failures immediately visible in the reporter without having to parse the aggregate message string.
One common pattern to avoid the "0 test cases" warning when no collisions exist is to fall back to a trivial sentinel `it`; but even a top-level `it.each(collisions)(…)` with an empty array is fine in modern vitest — it simply produces no failures.
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Adds a regression test that guards against the
Symbol.forcollision class such as in #2579Created with PostHog Code