Out of 484 tests, exactly one failed. I was implementing a small, self-contained Vue component, and the failure looked simple: a sentence that should have had spaces around a link didn’t.
I debugged the issue with a console.log and then I found a lead. Let’s review the root cause of all that.
The Component and the Missing Spaces
The component in question, OrgRestrictionNotice.vue, renders one fixed sentence with a link in the middle of it:
| |
The test asserted the rendered text matched that sentence exactly:
| |
It failed with this diff:
| |
No spaces at all around the link. Why?
The Culprit
If the compiled output looked fine, the bug had to be downstream of it—in how the test read the text back out. So I went looking in Vue Test Utils’ own source for what wrapper.text() actually does. Its textContent helper is:
| |
And the text() method on the wrapper itself is just:
| |
There it was. getRootNodes() returns every root-level node of the mounted component. .map(textContent) trims each one individually. .join('') glues the results back together with no separator at all.
OrgRestrictionNotice.vue has no wrapping element, so under Vue 3’s official support for fragments, its template compiles to three sibling root nodes: a text node, the <AppLink> (rendered as <a>), and another text node. wrapper.text() trims each of those three separately—stripping the trailing space off the first text node and the leading space off the third—then concatenates them with nothing in between. It didn’t matter what the template contained; any component with a bare text node touching its own root boundary would lose that space under wrapper.text().
The Actual Fix
Once I understood the mechanism, the fix was straightforward: stop asserting wrapper.text() on the component in isolation, and mount it the way it’s actually used—inside a single-root host:
| |
With one root node, getRootNodes() returns exactly one element, textContent trims only its outer edges, and the interior spacing survives the round-trip intact. All 484 tests passed. The component itself never needed to change.
Conclusion
I spent some time to diagnosis the issue and, to be honest, Claude didn’t help. It cycled to try to “fix” a component that worked fine because the symptom looked exactly like a template whitespace bug. Maybe a Context 7 MCP with the Vue and Vue Testing documentation would have helped.
I learned an important lesson on that occasion and I’m sure that if you reached that sentence, right now, you did as well.
If you liked this article…
Follow me
Thanks for reading this article. Make sure to follow me on X, subscribe to my Substack publication and bookmark my blog to read more in the future.
Credit: Photo by Ann H on Pexels (https://www.pexels.com/photo/pink-jigsaw-puzzle-piece-3482441/).
