Skip to content

test(editor): cover the vault-path race the image resolver hit - #911

Merged
h4yfans merged 1 commit into
mainfrom
obsidian-embed-roundtrip
Aug 1, 2026
Merged

test(editor): cover the vault-path race the image resolver hit#911
h4yfans merged 1 commit into
mainfrom
obsidian-embed-roundtrip

Conversation

@h4yfans

@h4yfans h4yfans commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

#910 fixed a real race: BlockNote calls resolveFileUrl exactly once while building an image block's DOM, and #907 read the vault path from useVault(), which starts at null and fills in after an IPC round-trip. The editor mount won that race, so the resolver saw a null vault path, correctly left the ref alone, and the image stayed broken for the life of the block.

That fix shipped without a test — I said so in #910, because driving BlockNote's image-block DOM construction in jsdom is disproportionate for a change that size. This closes that gap without the jsdom cost.

The callback moves into createNoteFileUrlResolver, which takes the note path and the vault lookup as plain functions. ContentArea wires the real ones; the test wires a vault lookup that has deliberately not answered yet. Behaviour is unchanged.

Three properties are now pinned:

Plus two boundary cases: no note path yet (no vault lookup fired at all), and a note path that arrives after mount.

Reviewer notes

Release note

none

Test plan

  • pnpm --filter @memry/desktop test:renderer — 518 files, 5672 passed, 0 failed
  • pnpm --filter @memry/desktop typecheck:web
  • eslint --no-cache --max-warnings=0 on both changed source files

#910 fixed the race where BlockNote's one-and-only `resolveFileUrl` call ran
before the vault path had loaded, leaving the image broken for the life of the
block. That fix shipped without a test, because driving BlockNote's image-block
DOM construction in jsdom is disproportionate.

Extract the callback into `createNoteFileUrlResolver` so the behaviour is
testable on its own, and pin the three properties that matter: it waits for a
vault path that has not arrived yet, it looks the vault up once however many
images a note has, and a failed lookup degrades to leaving the URL alone rather
than throwing inside the editor.

Verified by mutation — restoring the pre-#910 "read whatever has loaded" shape
fails three of the five cases.
Copilot AI review requested due to automatic review settings August 1, 2026 12:18
@github-actions github-actions Bot added the test label Aug 1, 2026
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

React Doctor found no new issues. 🎉

Reviewed by React Doctor for commit 34fdeff.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds targeted renderer-unit coverage for the vault-path resolution race that previously broke note-relative images, by extracting the BlockNote resolveFileUrl callback into a testable helper and wiring it into the editor.

Changes:

  • Introduces createNoteFileUrlResolver to encapsulate (and cache) the async vault-path lookup used for resolving note-relative asset URLs.
  • Adds a focused Vitest suite that pins the “await vault path”, “single lookup”, and “degrade gracefully on lookup failure” behaviors (plus two note-path boundary cases).
  • Updates ContentArea to use the new resolver factory instead of inlining the logic.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
apps/desktop/src/renderer/src/lib/create-note-file-url-resolver.ts New helper to build a cached, async resolveFileUrl callback that waits for the vault path before resolving note-relative URLs.
apps/desktop/src/renderer/src/lib/create-note-file-url-resolver.test.ts New unit tests covering the vault-path race, caching behavior, and failure/boundary handling.
apps/desktop/src/renderer/src/components/note/content-area/ContentArea.tsx Wires the editor’s resolveFileUrl to the new helper and removes the inline implementation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +223 to +228
const resolveFileUrl = useRef(
createNoteFileUrlResolver(
() => notePathRef.current,
async () => (await vaultService.getStatus()).path ?? null
)
).current
Comment on lines +26 to +31
return async (url: string) => {
const notePath = getNotePath()
if (!notePath) return url
if (!vaultPath) vaultPath = fetchVaultPath().catch(() => null)
return resolveNoteRelativeUrl(url, notePath, await vaultPath)
}
@codecov

codecov Bot commented Aug 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.00000% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...r/src/components/note/content-area/ContentArea.tsx 33.33% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@h4yfans
h4yfans marked this pull request as ready for review August 1, 2026 13:22
@h4yfans
h4yfans merged commit 7178941 into main Aug 1, 2026
18 of 19 checks passed
@h4yfans
h4yfans deleted the obsidian-embed-roundtrip branch August 1, 2026 13:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants