Skip to content

test(app): cover publish 429/401 error paths in e2e#382

Merged
graydawnc merged 4 commits into
mainfrom
test/share-publish-error-e2e
Jun 10, 2026
Merged

test(app): cover publish 429/401 error paths in e2e#382
graydawnc merged 4 commits into
mainfrom
test/share-publish-error-e2e

Conversation

@graydawnc

Copy link
Copy Markdown
Collaborator

What

Adds failure injection to the share-publish mock backend — a failures switch that forces a status code on selected routes (/api/publish, /api/me/shares) — and two specs for the publish error surfaces:

  • 429 rate-limit: the inline error renders the rate-limit copy, the form survives, and once the backend recovers the same submit button retries to a successful publish
  • 401 expired session: the session-expired copy renders and no share is created

Error-copy assertions are sourced from en.json rather than hand-typed, so copy edits don't flake the suite while still verifying which of the three error variants rendered.

Why

The e2e suite covered the publish happy paths; 429/401 handling was verified only at the unit layer on each side of the wire (backend status codes in publish.test.ts, renderer branching in the PublishTab state machine). Nothing proved the status code actually travels through IPC into the visible error element — the exact wiring class the pre-GA audit flagged as untested.

Test plan

  • share-publish e2e suite green on this branch (7/7)
  • failures is cleared by reset() so injection can't leak across tests

🤖 Generated with Claude Code

graydawnc and others added 3 commits June 10, 2026 14:33
The Share button, Publish/Export tab labels, and the popover/tablist
aria-labels were the last hardcoded English strings in the share-publish
surfaces after the #372 i18n pass. Route them through t() with new
shareEditor.shareMenu.* keys across all 7 locales.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The prod CSP hardcoded the spool.pro origin family in connect-src and
img-src. When SPOOL_SHARE_BACKEND redirects API traffic elsewhere
(staging, local mock), main-process fetches follow the override but the
renderer's direct fetches — avatar <img> loads and api calls — get
silently blocked by CSP, which looks like a broken image with an empty
network tab.

buildCsp() now appends the override origin (normalized via URL.origin,
so a trailing-slash default doesn't duplicate) to both directives in
both profiles. The canonical spool.pro family stays unconditionally:
published-share URLs and avatar links keep pointing there.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The publish-flow e2e suite covered the happy paths but not the error
surfaces: rate-limit (429) and expired-session (401) rendering was only
verified at the unit layer on each side of the wire, never end-to-end
through IPC into the inline error element.

The mock backend gains a 'failures' switch that forces a status code on
selected routes, and two specs assert the exact error copy (sourced
from en.json, not hand-typed), that the form survives for retry, and
that a recovered backend lets the same submit button succeed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Base automatically changed from fix/csp-backend-origin to main June 10, 2026 06:58
The Published tab mixed live and revoked shares in one list with text
badges and two bare hover icons per row — ambiguous at a glance and
structurally unprepared for revoked history, which the backend keeps
forever (only account deletion purges it) and so grows without bound.

- Live rows mirror the share-web /me row: visibility as an icon-only
  glyph with tooltip (globe = on profile, link-2 = link only), whole-row
  open, expiry inline in the meta line. Hover/cursor/action behavior
  mirrors SessionRow: warm-surface row hover, default cursor, actions
  in a single hover-revealed ⋯ menu that stays visible while open.
- Revoked shares move to a collapsed "Unpublished · N" section at the
  bottom and are display-only: revoke is permanent (R2 content deleted,
  slug 410 forever), so Copy link would hand out a dead URL.
- A failed myShares refresh now raises a persistent inline banner
  ("showing cached data" + retry) instead of silently rendering a stale
  cache that may miss remote revocations.
- Drafts tab drops its count to match the Published tab.

New e2e: stale banner raise/clear, live-row affordances via the ⋯ menu,
revoked rows collapsing into the section with no actions.

Co-authored-by: Chen <99816898+donteatfriedrice@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
@graydawnc
graydawnc added this pull request to the merge queue Jun 10, 2026
Merged via the queue into main with commit b136386 Jun 10, 2026
6 checks passed
@graydawnc
graydawnc deleted the test/share-publish-error-e2e branch June 10, 2026 07:12
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