Skip to content

Point two tests at the vendored nostr-tools - #296

Merged
dmnyc merged 1 commit into
mainfrom
fix/tests-use-vendored-nostr-tools
Sep 11, 2026
Merged

Point two tests at the vendored nostr-tools#296
dmnyc merged 1 commit into
mainfrom
fix/tests-use-vendored-nostr-tools

Conversation

@dmnyc

@dmnyc dmnyc commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Both files did require('nostr-tools'). package.json has declared no dependencies at all since 3b9d482 on 2026-07-13, which removed the devDependency as part of moving to vendored copies. Both test files were written after that — 2026-07-28 and 2026-07-29 — against a package that was already gone.

So they never ran. Not "failed" in the sense of assertions going red: the require threw at load, so node --test reported one failing file and nothing inside ever executed. That's 51 tests, including the NIP-22 tag-shape checks that exist precisely because getting that wrong lands a comment outside the thread it was meant for. Silent for six weeks, across four releases.

The fix loads nostr-tools.js the way owner-sign.test.js and the keystore tests already do. No dependency comes back, and it tests the exact bytes the extension ships rather than whatever npm would have resolved — which for a signer is the version you actually want under test.

Suite goes from 1032 pass / 2 fail to 1073 pass / 0 fail.

I also swept for other tests requiring a package that isn't installed. These two were the only ones.

One thing I did not change, because it's a judgement call rather than a fix: package.json says 1.10.0 while manifest.json says 1.12.0. Nothing reads the former — scripts/stamp-version.sh and the packaging scripts use the manifest — so it's cosmetic drift rather than a bug. Worth either syncing it at release time or dropping the field so it can't mislead.

search-entity.test.js and web-comment.test.js both did
`require('nostr-tools')`. package.json has declared no dependencies since
3b9d482 on 2026-07-13, which removed the devDependency as part of moving to
vendored copies. Both files were written after that — 2026-07-28 and
2026-07-29 — against a package that was already gone.

So they never ran. Not "failed": the require threw before the file loaded, so
node --test reported one failing file and none of the assertions inside ever
executed. That is 51 tests, including the NIP-22 tag-shape checks that were
written precisely because getting them wrong lands a comment outside the
thread it was meant for, silent for six weeks.

Loading nostr-tools.js the way owner-sign.test.js and the keystore tests
already do fixes it without reintroducing a dependency, and tests the exact
bytes the extension ships rather than whatever npm would have resolved.

Suite goes 1032 pass / 2 fail to 1073 pass / 0 fail.
dmnyc added a commit that referenced this pull request Sep 9, 2026
A theme belongs to an account, not to the install (themeBy, #266/#303), so
reading only settings.theme would have handed these pages the default that
an account which never chose inherits. That is this branch's own bug back
again for anyone using per-account themes: on Par Avion, opening the guide
would still give you a dark page out of nowhere.

theme-boot now resolves sidecar_active_pubkey against themeBy and falls
back to settings.theme. Both keys are a plain chrome.storage.local read,
so nothing has to be asked of the background.

RESOLVED HERE, unlike the pay card, and the difference is worth stating
because they look like the same problem. That card renders into a web page
that can see it, so it must never learn which account is active and takes
the theme of the account its own site is bound to instead. help.html,
welcome.html and wallets.html are chrome-extension:// documents that
nothing on the web can read, so the account on screen is simply the right
answer.

The change is a no-op until #303 lands: with no themeBy in storage the
first term is undefined and it falls through to settings.theme, which is
exactly what shipped before. So this does not care which of the two merges
first, and the two branches share no files, meaning they would otherwise
have merged clean and been silently wrong.

The storage listener now watches sidecar_active_pubkey as well, and
re-reads rather than pulling a value out of the change record, because the
answer needs both keys and each one moves alone. Switching account now
repaints a guide already open in another tab, the way a theme change
already did.

Verified in a browser across all four states: no themeBy at all wears the
global and keeps .theme-light; giving the active account Nixie repainted an
already-open help.html live and dropped the class; switching to an account
on Bauhaus followed and restored it; clearing that account's theme fell
back to the default. Suite: 1,034 pass, with search-entity and web-comment
still red on the pre-existing missing nostr-tools that #296 fixes.
@dmnyc
dmnyc merged commit 50c8a20 into main Sep 11, 2026
2 checks passed
@dmnyc
dmnyc deleted the fix/tests-use-vendored-nostr-tools branch September 11, 2026 14:19
dmnyc added a commit to ChadFarrow/sidecar that referenced this pull request Sep 11, 2026
Three things, one surface. The bell sheet was read-only apart from a Reply
button, and the rows are summaries: a 140-character snippet, or — for a
reaction, a repost or a zap — no content at all, just "reacted to your note"
and a pointer you could not follow without leaving for a client.

REFRESH, beside the sheet's close button. Notifications arrive on a live
subscription, so this looks redundant until you hit what the live sub cannot
cover: the worker evicted while the panel sat idle, or a relay that dropped
and reconnected. The sheet opens from cache with no round trip, so there was
no way to ask. It goes back through the SAME addEvent the subscriptions use,
exposed as cache.refetch, because that function drops your own events,
applies the mute list, de-dupes by id, prefetches the sender's name and
appends to an open sheet. A second copy of those five would be five things
to keep in step, and the ones that fail quietly — a muted sender
reappearing, a duplicate row — are the ones that survive a release. Nothing
new is the usual answer, so it says so rather than going silent.

REPLY, REACT AND ZAP on every note row, as three icons. Not behind the
chevron: they are what you came to the row to do, and a drawer in front of
them is a tap that buys nothing. Which is affordable precisely because they
are icons — three labelled buttons is ~200px of minimum width and reads as a
toolbar repeated 25 times down a list, where the glyphs this app already
uses for these verbs read on their own and carry an aria-label each. They
are 30px tap targets rather than shrunken buttons, and offered on a note or
a comment only: there is no thread to join on a kind:7, and a button that
produces a dead-end event is worse than no button, which is the rule the old
Reply already followed.

React opens a full picker over the vendored Unicode table, 1,914 emoji in
nine groups with search across all of them. One group at a time: every cell
is a real button, for the keyboard and for a screen reader, and 1,914 of
those is a visible hitch on open. Zap sends a zap OF THE NOTE rather than of
its author, by handing makeZapRequest the event so it carries an e tag, and
reuses the profile sheet's presets and amount row so the two forms cannot
drift apart. Its form is built on first tap, since learning whether someone
can be zapped at all costs a profile fetch and doing that per row would be
25 round trips for the one zap anybody sends.

EXPAND, on a chevron in the row's corner, is left with the job the actions
never belonged to: reading. A reply or a mention gives up its full text; a
reaction, repost or zap fetches the note it is about and quotes your own note
back at you, which is the half of the sentence the label leaves out. Notes
are cached including the misses, since two reactions to one note is the
normal shape of a busy list.

Worth knowing: the text is cut TWICE, at 140 characters in the source and
again by a three-line -webkit-line-clamp in CSS. Undoing only the first left
the row looking identical, with the browser drawing its own ellipsis at the
same three lines, so the chevron read as a control that did nothing.

emoji-data.js joins the vendoring pipeline with the same gates as the rest:
pinned version, tarball checked against the registry's integrity hash, hash
recorded in scripts/vendor-hashes.sha256, provenance in VENDOR.md. It is
reduced rather than copied — the published file is 838KB because it carries a
slug, two version fields and a skin-tone flag per emoji, and a picker needs
the character, a name to search and the group. Packed, it is 52KB.

Verified in a browser end to end, with a real note from a second account:
the row arrived carrying its three icons unexpanded, the chevron grew the
text from 141 to 205 characters with the clamp lifted, React published a
kind:7 🔥, and Zap opened its form on someone with no lightning address to
the honest "They have no lightning address." with Send held disabled. 27 new
tests across notif-refresh and notif-actions; suite 1,109 pass, with the two
pre-existing nostr-tools failures that dmnyc#296 fixes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant