Preconditions
The organizer is authenticated in the event-setup trunk, has edit access to a fixture event, and the event has a Canvas draft page with at least one root block.
Happy path
Open the Canvas editor from Event Setup.
The editor loads the draft page, root block sequence, autosave state, and preview pane.
Compose, preview, and publish.
The organizer edits the capability surface for Custom code, import/export, custom fonts, previews desktop and mobile, then confirms publish or schedule.
Verify public version semantics.
Publish creates a versioned snapshot; scheduled publish leaves the prior public version intact until its activation time.
Failure modes
Every Canvas branch includes the cluster E rubric: undo/redo, paste-from-other-page, asset isolation, missing-token fallback, preview parity, scheduled publish, autosave recovery, and two-editor conflict. Capability-specific probes bring each story to 10-12 failure modes.
Capability-specific gap probe
Trigger: matrix=Partial.
The visible parity panel lists the incomplete Custom code, import/export, custom fonts contract so the probe fails loudly until parity closes.
Undo/redo correctness across block ops
Trigger: the organizer inserts a block, deletes another, reorders the root block sequence, and edits one block property before using undo twice.
Resolution: each block operation creates exactly one undo entry; multi-step undo restores the prior root block sequence and block props exactly, then redo reapplies the same sequence without duplicating blocks.
Paste from other page
Trigger: the organizer copies a block from page A and pastes into page B, then tries the same paste from a different event.
Resolution: page-local references are remapped to the destination slug and asset URLs; cross-event paste opens an explicit confirmation before any draft mutation happens.
Asset upload failure isolated
Trigger: three assets upload while one fails with a transient R2 or connector error.
Resolution: the two successful uploads continue and bind to their blocks; the failed asset renders inline with retry and the page draft JSON remains valid.
Dynamic token rendering missing data
Trigger: preview resolves {guest.firstName} for a contact with no first name and {event.location} before location is configured.
Resolution: missing values fall back to "Guest" or configured fallback copy; no rendered sentence contains an empty merge or doubled punctuation.
Mobile preview vs published
Trigger: organizer previews at 375x667 and publishes the same draft.
Resolution: the public page matches mobile preview within layout-shift and viewport tolerances; differences surface as preview warnings before publish.
Scheduled publish vs immediate
Trigger: organizer schedules a draft for a future time instead of publishing immediately.
Resolution: before the scheduled time, the public URL serves the previous active version or 404 for first publish; at the scheduled time the new draft becomes live atomically.
Autosave recovery
Trigger: browser refreshes or crashes after an edit but before manual save.
Resolution: latest autosave is offered in a recovery banner with restore/discard; restore is the default and rehydrates the exact block tree.
Two-editor conflict resolution
Trigger: two organizers edit the same page; one publishes while the other saves a stale draft.
Resolution: the second organizer sees a conflict modal listing changed blocks and can merge or accept last-write-with-warning; both sessions converge to a deterministic state.
Custom CSS allow-list blocks unsafe code
Trigger: organizer enters CSS containing script tags, javascript: URLs, or @import from an unapproved host.
Resolution: save is blocked inline; arbitrary JS is never accepted, and approved CSS remains scoped to the page.
Import/export round-trips page tree JSON
Trigger: organizer exports a page tree, imports it into a fresh draft, and previews.
Resolution: every block, token, style, and asset reference survives the round trip with destination-safe ids.
Capability-specific gap probe: code/fonts parity incomplete
Trigger: matrix=Partial for EF-036 custom code and fonts.
Resolution: visible gap copy lists CSS allow-listing, JSON import/export, custom font upload/subsetting, and JS prohibition as required parity work.
Stable test attributes
Visibility teeth. Each attribute must be effectively visible when active and must match the agent probes.
| data-test | Where | Purpose |
|---|---|---|
canvas-canvas-custom-code-fonts-editor | Canvas editor | Main organizer-side Canvas editor surface |
canvas-canvas-custom-code-fonts-stepper | Canvas editor | Create/edit/preview/publish lifecycle indicator |
canvas-canvas-custom-code-fonts-block-tree | Canvas editor | Root block sequence and selected block tree |
canvas-canvas-custom-code-fonts-preview | Canvas editor | Preview pane for desktop and mobile layouts |
canvas-canvas-custom-code-fonts-publish-cta | Canvas editor | Publish or schedule publish action |
canvas-canvas-custom-code-fonts-publish-confirmation | Canvas editor | Confirmation dialog for publish or risky action |
canvas-canvas-custom-code-fonts-autosave-banner | Canvas editor | Autosave recovery and restore/discard banner |
canvas-canvas-custom-code-fonts-conflict-modal | Canvas editor | Two-editor conflict resolution modal |
canvas-canvas-custom-code-fonts-upload-row | Canvas editor | Per-asset upload progress/failure row |
canvas-canvas-custom-code-fonts-token-warning | Canvas editor | Dynamic token validation or fallback warning |
canvas-canvas-custom-code-fonts-gap-panel | Canvas editor | Visible parity gap panel when matrix is absent or partial |
canvas-canvas-custom-code-fonts-mobile-preview-warning | Canvas editor | Preview discrepancy warning for mobile vs published |
canvas-canvas-custom-code-fonts-custom-css-editor | Canvas editor | Custom CSS editor |
canvas-canvas-custom-code-fonts-import-export-panel | Canvas editor | Page tree import/export controls |
canvas-canvas-custom-code-fonts-font-uploader | Canvas editor | Custom font upload control |
Agent test plan
Inherits event-setup trunk preconditions. Component contract chaining applies through usesComponents.
- open-canvas-surface
- edit-preview-publish-flow
- published-version-recorded
- undo-redo-block-ops
- paste-cross-page
- asset-upload-isolated
- dynamic-token-fallback
- mobile-preview-published-match
- scheduled-vs-immediate-publish
- autosave-recovery
- two-editor-conflict
- custom-code-allowlist
- import-export-roundtrip
- custom-fonts-parity-gap
- evaluate-canvas-editor