Comfy-Org / Comfy-Org/ComfyUI_frontend
Two badge-parity tests assert '' and survive a fully disabled badge pipeline
- Dominant language
- TypeScript
- Stars
- 2k
- Forks
- 699
- Avg merge
- 1d 7h
- Merged PRs (30d)
- 490
Description
## Problem
Two tests in `src/composables/node/badgeRendererParity.test.ts` assert that a badge string is `''`.
Because the helpers they call return `''` both when a badge is correctly hidden and when the badge
pipeline is broken, these two tests stay green under a mutation that disables badge rendering
entirely. They read as coverage for the "hide" settings and detect nothing.
Both mutants below were executed. Neither is caught by the test that is supposed to catch it.
## Provenance
* **Found by:** mutation-verifying the badge-parity suite while confirming an unrelated ordering
defect · 2026-08-22
* **How:** two independent mutants applied at `origin/main` `612ea3e151`, suite run under each,
survivors recorded. The unmutated baseline was re-run at `origin/main` `a08a7598aa` and is
unchanged (`5 passed | 4 expected fail (9)`); the two commits between those refs touch only the
mask editor and a CI workflow, none of the files below
* **Why now:** the suite is new (added in #15568, 2026-08-21) and is about to be edited by the
ordering fix; hardening it now is cheaper than after it has been trusted for a while
* **Lane rationale:** `agent-ok` — the weakness is located, the mutants that must be killed are
named and executable, and the fix is confined to one test file
* **Dedup identity:** `fe-badge-parity-vacuous-empty-assertions`. Linear dedupe run 2026-08-22: no
existing ticket
* **Confidence:** verified by execution, both arms
## Sequencing
**There is a related in-flight fix to the same file: GitHub issue
https://github.com/Comfy-Org/ComfyUI_frontend/issues/15662, assigned to @AustinMroz** (the core
badge ordering fix — Vue renders `BETA #1` where the canvas renders `#1 BETA`). It edits `:169`,
`:191` and `:216` of this same test file. This ticket edits `:202-207` and `:224-228`. They do not
overlap textually, so this work does not block on it, but check whether #15662 has landed before you
start: if it has, the three `it.fails` at `:169`, `:191` and `:216` will already be plain `it` and
the baseline counts below will have shifted to `8 passed | 1 expected fail (9)`. Adjust your
before/after expectations accordingly and say in the PR which baseline you saw.
**This test-hardening ticket must land before #15567 / FE-1738.** Today #15567's `it.fails` at
`:230` is the only test that kills mutant A. Fixing #15567 correctly removes that marker and leaves
a completely dead Vue badge pipeline undetected unless the `:202-207` positive control lands first.
The ECS branch has already fixed #15567 and removed the marker, which demonstrates the sequencing
hazard rather than closing it on `main`.
## Evidence
All at `origin/main` `612ea3e151`.
The two vacuous assertions:
* `:202-207` — `it('agrees that None hides every badge')`, asserting
`expect(legacyBadgeText(node)).toBe('')` and `expect(vueBadgeText(node)).toBe('')`
* `:224-228` — `it('hides built-in legacy badges')`, asserting `expect(legacyBadgeText(node)).toBe('')`
Why `''` is not a signal. `vueBadgeText` (`:105-125`) ends
`return (facts ?? []).join(' ')` — an empty `core` array and a broken composable both produce `''`.
`legacyBadgeText` (`:99-103`) reads `thunk().text`, and the badge text is assembled from segments
that each fall back to `?? ''` (`src/composables/node/useNodeBadge.ts:101`, `:104`), so suppressed
segments and absent data are indistinguishable.
Baseline:
```
$ vitest run src/composables/node/badgeRendererParity.test.ts
Tests 5 passed | 4 expected fail (9)
```
**Mutant A — Vue badge partitioning always returns empty.** Early-return
`{ hasComfyBadge: false, core: [], extension: [], pricing: [] }` from the computed in
`src/renderer/extensions/vueNodes/composables/usePartitionedBadges.ts:190`.
```
Tests 1 failed | 5 passed | 3 expected fail (9)
```
The only test that changed state is `it.fails('hides built-in Vue badges')` at `:230`, which flipped
to passing. The Vue half of `:202-207` — the assertion whose job this is — stayed green under a
completely dead Vue badge pipeline. Note that `:230` is a marker for issue #15567 and will be
removed when that is fixed, at which point nothing detects mutant A.
**Mutant B — legacy badge text always suppressed.** Make `badgeTextVisible` in
`src/composables/node/useNodeBadge.ts:63` return `false` unconditionally.
```
Tests 3 failed | 2 passed | 4 expected fail (9)
```
The three killed tests are the positive legacy assertions at `:159`, `:181`, `:210`. The two
survivors are exactly the `''`-asserting legacy tests at `:202-207` and `:224-228`.
`badgeRendererParity.test.ts` was added by Christian Byrne in #15568;
`useNodeBadge.ts` and `usePartitionedBadges.ts` were last touched by Alexander Brown.
## Acceptance criteria
- [ ] `:202-207` and `:224-228` each assert something that distinguishes "hidden" from "broken".
The cheapest sufficient shape is a positive control inside the same test: render the same node
under a mode where the badge **must** appear, assert the non-empty expected string, then switch
to `None` / `HideBuiltIn` and assert `''`
- [ ] Mutant A is killed by `:202-207` specifically, not only by the `it.fails` at `:230`
- [ ] Mutant B is killed by both `:202-207` and `:224-228`
- [ ] The PR reports both mutant runs with their exact counts, before and after, and confirms the
test **count** is unchanged in every arm — a mutation that changes the count proves nothing
- [ ] The suite is green on unmutated `main` after the change
- [ ] `pnpm lint`, `pnpm typecheck` and `pnpm test:unit` pass
## Out of scope
1. **Do not fix either badge defect here.** `:230` (`it.fails('hides built-in Vue badges')`) is
[#15567](https://github.com/Comfy-Org/ComfyUI_frontend/issues/15567) / FE-1738 and its marker must
survive this PR unchanged. The core ordering defect is
[#15662](https://github.com/Comfy-Org/ComfyUI_frontend/issues/15662) and has its own ticket
2. No production code changes at all. The mutants are throwaway; revert them
3. Do not add new test cases for badge behaviour not already covered — this is hardening two
existing assertions, not extending the suite
4. Do not touch the other `''` assertion sites elsewhere in the repo
## Working notes
Everything needed is above; you do not need any other context to finish this.
* Base off `main`. Do not target `feature/ecs-migration`, and do not merge anything.
* Baseline at `origin/main` `a08a7598aa`, re-run and confirmed:
`vitest run src/composables/node/badgeRendererParity.test.ts` → `5 passed | 4 expected fail (9)`.
If you do not see that, your setup is wrong — fix it before drawing any conclusion.
* This is a pnpm workspace with **eight** `node_modules` directories. With only the root one
present, vitest dies at `Failed to resolve import "clsx"` at *every* commit, so a mutation
comparison silently becomes garbage. Run
`vitest run src/lib/litegraph/src/LLink.test.ts` as a known-green positive control first.
* A mutation that changes the test **count** proves nothing — the count must be identical in every
arm. That is why the counts are quoted above rather than just "it failed".
* Revert both mutants when you are done. They are throwaway; no production code changes ship in
this PR.
Contributor guide
Assessment
This issue has not been assessed yet.