My Formatter Would Have Rewritten This Test Into a Different Test

There’s one line in my serializer test suite that carries a comment longer than the assertion:

// The hole is the point. `biome check --write` rewrites this to
// [1, undefined, 3], which still passes while testing something else
// entirely -- a hole and an explicit undefined take different paths
// through the indexed loop in sanitize().
// biome-ignore lint/suspicious/noSparseArray: an array hole is the case under test
expect(safeStringify([1, , 3])).toBe('[1,"[undefined]",3]');

That [1, , 3] is a sparse array. The middle slot isn’t undefined, it’s absent. JavaScript treats those as different things in ways that bite you exactly once, and my serializer has a loop written specifically to handle the difference:

if (Array.isArray(container)) {
  // Indexed rather than mapped: Array.prototype.map skips holes, and a hole
  // must still render as '[undefined]'.
  const items: unknown[] = [];
  for (let index = 0; index < container.length; index++) {
    items.push(sanitize(container[index], ancestors, depth + 1, maxDepth));
  }
  return items;
}

An indexed for loop, in 2026, with a comment defending itself. Array.prototype.map skips holes. It doesn’t visit them, doesn’t call your callback, and leaves the hole in place, which JSON.stringify then renders as null. So if I’d written the obvious .map(), a sparse array would serialize as [1,null,3] instead of [1,"[undefined]",3], which is a different claim about the data. The test above is the only thing standing between me and that regression.

And a code formatter will quietly replace it.

The part where I check my own claim

I wrote that comment in a hurry and asserted that biome check --write does the rewrite. Before publishing this I actually ran it, on Biome 2.4.7, against a throwaway file:

$ cat probe.ts
const x = [1, , 3];

$ biome check --write ./probe.ts
Found 1 error.
× Some errors were emitted while applying fixes.

$ cat probe.ts
const x = [1, , 3];

Unchanged. My comment was wrong. Plain --write won’t touch it, it reports the noSparseArray violation and refuses to fix it, because Biome classifies that fix as unsafe. Unsafe fixes are ones that can change program behavior, and they’re opt-in.

So here’s the accurate version:

$ biome check --write --unsafe ./probe.ts
Checked 1 file in 4ms. Fixed 1 file.

$ cat probe.ts
const x = [1, undefined, 3];

One extra flag. That’s the whole gap between “my tools protect me” and “my test now asserts something I never meant to assert.”

I like this correction more than the original claim. --write alone failing loudly is good design, and Biome deserves credit for it. The risk isn’t the default. The risk is the flag people reach for when the lint queue is long and the fixes look boring, which is a decision made by a tired human at the end of a cleanup branch, not by a tool doing something wrong.

Why the rewrite is invisible

Here’s the ugly part. I ran both forms through the serializer:

HOLE      = [1,"[undefined]",3]
UNDEFINED = [1,"[undefined]",3]
same?     = true

Identical output. The rewritten test passes. Green check, no diff in the test result, nothing in CI to look at. The assertion string doesn’t change, the expectation doesn’t change, and the only thing that changed is which branch of sanitize() the input exercises. The hole test becomes a duplicate of the undefined test on the line above it, and the indexed loop loses its only coverage.

The regression this catches wouldn’t show up until somebody refactors that loop into a .map() for readability, sees 470 tests pass, and ships a serializer that renders holes as null.

That’s the shape I want you to take away. A test that gets deleted is loud. A test that gets rewritten into a passing test of something else is silent, and your coverage tooling will report the same numbers before and after because the line still executes.

Three things worth doing

  1. Any test whose input is a syntactic edge case needs an ignore comment with a reason. Sparse arrays, -0, trailing commas in odd places, \r\n in a fixture string, a lone surrogate in a UTF-16 test. Your formatter has opinions about all of them, and the comment is what tells the next person the weirdness is deliberate.
  2. Be careful with --unsafe on a test directory. It’s fine on source. On tests it can turn the case under test into a different case. If you run it, read the diff for the test files specifically, not just the summary line.
  3. When you write a claim in a code comment, run it. Mine said --write. It took one throwaway file and about eight seconds to find out the truth needed a second flag. Comments rot, but this one was born wrong, and it would have taught the next reader to fear the wrong command.

I fixed the comment. It now says --write --unsafe, which is both accurate and, I think, more useful, because it names the exact thing you shouldn’t run on this file.

Sources

I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].

Testing javascript Biome Tooling