bun:test: render null/undefined in test.each $key titles and stop eating the next character

Closed
RO
2mo ago
+28-8

Repro

import { it } from "bun:test";
it.each([{ v: null }])("v is $v here", () => {});
beforeafterJest
{ v: null } / "v is $v here"v is $vherev is null herev is null here
{ v: undefined } / "u is $v end"u is $vendu is undefined endu is undefined end
{ v: 1 } / "x $nope end"x $nopeendx $nope endx $nope end
{ a: { b: null } } / "n $a.b tail"n $a.btailn null tailn null tail
{ v: 1 } / "$5 USD"$5USD$5 USD$5 USD

Cause

format_label's $key fallback wrote the literal $key text and set idx = var_end, then fell through to the loop's trailing idx += 1, which skipped the character immediately after the identifier. Both arms of the is_identifier_start check land on that fallback (property missing after a valid identifier, and $ followed by a digit or other non-identifier-start), so both swallowed a character.

Separately, is_empty_or_undefined_or_null() sent existing-but-null/undefined properties down the same literal path. Jest renders those values through pretty-format.

Fix

  • continue after emitting the literal $key so the next character is not swallowed.
  • Guard only on is_empty(). get_if_property_exists_from_path returns an empty JSValue for a missing property and the real null/undefined value otherwise, so null/undefined now go through the same formatter as every other non-string value and print null / undefined. A missing property still leaves the literal placeholder, which is also what Jest does.

Tests

test/cli/test/bun-test.test.ts in the existing $variable syntax block:

  • New renders null and undefined property values covers { v: null }, { v: undefined }, nested $a.b resolving to null, and a missing property keeping its literal with the following space intact.
  • handles edge cases with underscores and invalid identifiers now asserts the full rendered title, which pins the space after $123invalid (the non-identifier-start arm) as well as $has-dash / $has space.
  • handles missing properties gracefully previously encoded the swallowed-character output ($missing|) and now expects the full title.

All three fail on the released binary and pass with this change.


no test proof · iteration 0 · Platform-specific test(s) that do not run on this machine. Deferring to CI, which covers all platforms: test/cli/test/bun-test.test.ts