Skip to content
C.W.K.
Stream
Lesson 04 of 05 · published

Verify Where the Prop Is Absent

~14 min · testing, sampling, layout, failure

Level 0Loose Parts
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

Nine of Eleven, From One Optional Slot

A slot was added to the shared panel so a host could render something above the embedded frame. Two apps needed it. It was built, wired into both, and looked correct in both.

It broke the frame in nine of the eleven consumers — every app that passed nothing.

The mechanism is a grid detail with a large consequence. The slot node was rendered only when content was supplied, and a grid row does not collapse when its node is absent: the row remains, and everything below shifts up into it. The frame landed in a middle, auto-sized row, and an embedded frame in an auto row falls back to its intrinsic height. On one measured panel that turned a full-height frame into a small stub with a large empty region under it, and the embedded composer below the visible area.

The Sampling Error, Which Is the Real Lesson

Verification was done in two consumers, and it was thorough. The problem is which two: precisely the two that pass the slot. The entire sample consisted of the feature's users.

The majority — every consumer that passes nothing and therefore hits the new code path in its default state — was never opened. And that state is not an edge case. It is what the change does to almost everybody.

When a shared surface grows an optional prop, verify in a consumer that does NOT pass it. The author of an optional feature has its users open — that is where the work happened and where it is easy to check. Those are the least informative consumers to look at. The default case is the majority case, and it is the one nobody has open, so it has to be verified deliberately rather than incidentally.

Fixed Twice, So It Cannot Recur

Two changes rather than one, and the second is the interesting one. First, the slot node is now always present in the DOM and simply empty when unused, with the empty state dropping its own border — so absence and presence produce the same structure. Second, the frame and its alternative are pinned to an explicit grid row, so no future slot added above them can shift them at all.

The first fix repairs this bug. The second removes the entire class: the next person adding a slot cannot reintroduce it, because the frame's position no longer depends on how many nodes precede it. That is the difference between fixing an incident and fixing the shape that produced it — and it is worth the extra ten minutes precisely because the next person will not have read this story.

Code

The conditional node, the collapse it caused, and both fixes·typescript
// BEFORE - the slot node exists only when content is supplied.
// Looks correct in the two apps that pass it. In the nine that do
// not, the grid row remains and everything below shifts UP into it.
<div className="panel">
  <Header />
  {beforeFrame && <div className="slot">{beforeFrame}</div>}
  <iframe className="frame" src={embedUrl} />
</div>

/*  .panel { display: grid; grid-template-rows: auto auto 1fr; }

    with the slot:      38px  |  90px   |  520px   frame fills 1fr
    without the slot:   38px  |  150px  |  460px
                                  ^^^^^
    the FRAME is now in the middle AUTO row, where an iframe falls
    back to its intrinsic 150px - a stub, with 460px of nothing
    under it and the embedded composer below the fold.            */


// FIX 1 - the node is ALWAYS in the DOM; absence and presence
// produce the same structure. :empty drops the border so an unused
// slot is invisible rather than a stray line.
<div className="panel">
  <Header />
  <div className="slot">{beforeFrame}</div>
  <iframe className="frame" src={embedUrl} />
</div>

/*  .slot:empty { border: 0; padding: 0; }                        */


// FIX 2 - the one that removes the CLASS. The frame is pinned to an
// explicit row, so no future slot added above it can move it at all.
// The next person adding a slot cannot reintroduce this bug, which
// matters because they will not have read this story.

/*  .frame,
    .unavailable { grid-row: 3; }                                 */


// THE TEST THAT WOULD HAVE CAUGHT IT - note the second case is the
// one nobody writes, because it is the case with nothing in it.
test("frame keeps its height WITHOUT the optional slot", () => {
  const { frame } = renderPanel({ beforeFrame: undefined });
  expect(frame.clientHeight).toBeGreaterThan(400);
});

External links

Exercise

Find the most recent optional prop or configuration flag added to a shared component you maintain. List the consumers that pass it and the consumers that do not. Then open one from the second list and check the behavior. If nobody has ever looked at that case, you have found the same sampling error, whether or not it produced a bug this time.
Hint
Check the pull request that added the feature and read which consumers appear in it. If every consumer mentioned is one that passes the new prop, the default case was never observed — and the default case is what most of your users are running.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.