test(youtube): assert the rendered anchor, and teach the shim href/src - #567
Merged
Conversation
`youtubeExternalFallback` matched markdown.ts for the signature of
`replaceWithYoutubeLink`, for each assignment inside it, and for the
absence of `createElement("iframe")`. Six assertions about how one
function is written, none about what a document renders as.
It also could not see the two decisions that make the feature bearable:
only a paragraph that is *nothing but* the link becomes a poster (a link
mid-sentence stays a link), and an id that is not 11 characters is left
alone rather than turned into an anchor around a thumbnail that 404s.
Both are now covered, along with the four recognised URL spellings —
`youtube.com/embed/` in particular, since that is the one people paste
out of an embed snippet.
The CSP assertion stays as it is: `frame-src` in tauri.conf.json is a
contract with the packaged app, and nothing type-checks it. The click
ordering in MarkdownViewer stays too, but as the ordering it actually
claims — `closest('a')` before `closest('img')` — rather than a 60
character regex over the branch bodies.
renderProtocolDom gains `href` and `src` reflection. A browser writes the
attribute when you assign the property, so `link.href = url` is visible
to getAttribute and survives serialization; the shim dropped it on the
floor, which left every test blind to where a link points — the whole
content of a link. Four accessors next to the existing `id` and
`className` ones. All 952 tests pass with it, including the six other
files that use the shim.
Reverting to `createElement("iframe")` turns three of the seven red.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Aug 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
Third slice of the source-shape → behaviour conversion (after #564, #565). Test files only.
youtubeExternalFallback.test.ts— rewritten to render documents and look at the output.renderProtocolDom.ts— the shim now reflectshrefandsrcinto attributes, as a browser does.Mechanism
The old file made six assertions about how
replaceWithYoutubeLinkis written: its exact signature,link.className = 'youtube-link',link.href = href, the thumbnail URL template, the call site, anddoesNotMatch(/createElement\(["']iframe["']\)/). None of them rendered a document.What that missed is not subtle. Two decisions make this feature bearable and neither was covered:
Both are now tested, along with all four recognised URL spellings.
youtube.com/embed/earns its own case: it is the URL people paste out of an embed snippet, so it is the one most likely to be missed if the detection list is ever split.The shim change
replaceWithYoutubeLinksetslink.href = hrefandthumbnail.src = …as properties. A browser reflects those into attributes;renderProtocolDomhad accessors foridandclassNameand nothing else, so the assignment landed on a plain JS property, never reachedgetAttribute, and never reached the serialized HTML:An anchor with no href and an image with no src. Every existing shim-based test was blind to where a link points, which is the entire content of a link. Four accessors alongside the existing pair fixes it. The full suite — including the six other files that install the shim — passes with the change: 952 tests, 0 failures.
Scope
frame-srcintauri.conf.jsonis a contract with the packaged app, nothing type-checks it, and aframe-srcthat outlived the iframe is permission granted for a feature that no longer exists.handleLinkClicklives in a Svelte component this runner cannot import — but it is now the ordering it actually claims (closest('a')resolved beforeclosest('img')) rather than a 60-character regex over the branch bodies that any reformatting would break.Tests
Restoring the pre-fix renderer —
createElement("iframe")in place of the anchor — turns 3 of the 7 red. Ran it, then reverted.The two new negative cases were written against the current behaviour and checked by hand against
getYoutubeId's 11-character rule and theparent.childNodes.length === 1guard, not derived from the code by inspection alone.Verification
Not verified: the shim is not a browser.
href/srcreflection now matches what a browser does for these two attributes specifically; the rest of the reflection surface (value,checked,htmlFor, …) is still absent, and this PR does not add it speculatively.🤖 Generated with Claude Code