@marianmeres/stuic 3.117.0 → 3.118.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// Conventions escape hatch (docs/component-testing/02-test-conventions.md):
|
|
3
|
+
// AssetsPreview is imperative-only — it opens a ModalDialog via a ref method
|
|
4
|
+
// open(index?). A *.svelte.test.ts file can't hold a bind:this + a trigger, so
|
|
5
|
+
// this fixture exposes an opener button that calls open(openIndex); all other
|
|
6
|
+
// AssetsPreview props are forwarded through ...rest.
|
|
7
|
+
import type { ComponentProps } from "svelte";
|
|
8
|
+
import AssetsPreview from "./AssetsPreview.svelte";
|
|
9
|
+
|
|
10
|
+
let ref = $state<AssetsPreview>();
|
|
11
|
+
let {
|
|
12
|
+
openIndex,
|
|
13
|
+
...rest
|
|
14
|
+
}: { openIndex?: number } & ComponentProps<typeof AssetsPreview> = $props();
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<button data-testid="opener" onclick={() => ref?.open(openIndex)}>open</button>
|
|
18
|
+
|
|
19
|
+
<AssetsPreview bind:this={ref} {...rest} />
|
|
@@ -36,7 +36,7 @@ Branch: `feat/component-testing`
|
|
|
36
36
|
| Rank | Task | Source | Status |
|
|
37
37
|
| ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | ------ |
|
|
38
38
|
| 14 | Rest of Tier 1 (Separator already smoke-tested · H, KbdShortcut, ButtonGroupRadio, ListItemButton, Card, TabbedMenu, IconSwap, Collapsible) | [03](./03-component-coverage-roadmap.md) #10–17 | ✅ |
|
|
39
|
-
| 15 | Tier 2 — `FieldInput` first, then the Field\* family + OtpInput, Nav, etc. | [03](./03-component-coverage-roadmap.md) |
|
|
39
|
+
| 15 | Tier 2 — `FieldInput` first, then the Field\* family + OtpInput, Nav, etc. | [03](./03-component-coverage-roadmap.md) | ✅ |
|
|
40
40
|
| 16 | Portals/focus-traps in browser mode (Modal, ModalDialog, Backdrop, Drawer, AlertConfirmPrompt) | [04](./04-hard-cases-and-e2e.md) | ✅ |
|
|
41
41
|
| 17 | Anchor-positioned menus (DropdownMenu, CommandMenu, UserAvatarMenu) + extract search logic to `_internal` | [04](./04-hard-cases-and-e2e.md) | ✅ |
|
|
42
42
|
| 18 | Standalone Playwright E2E layer (drag: Tree/FieldOptions/FieldFile; Milkdown; Checkout/auth flows) | [04](./04-hard-cases-and-e2e.md) | ⏭️ |
|
|
@@ -77,16 +77,22 @@ Other Tier 2:
|
|
|
77
77
|
- [x] ImageCycler — single-image static contract: role=img, aria-label, data-fit, bg, snippets (5 tests)
|
|
78
78
|
- [x] PricingTable — list/tiers, billing toggle switches prices, data flags, CTA callback (11 tests)
|
|
79
79
|
- [x] SlidingPanels — fixture-driven imperative `show()`; post-transition panel destroy (3 tests)
|
|
80
|
-
- [
|
|
81
|
-
|
|
82
|
-
- [
|
|
83
|
-
|
|
84
|
-
- [
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
80
|
+
- [x] Nav — section title (interactive vs not), group expand/collapse + onGroupToggle, leaf href/onClick/
|
|
81
|
+
disabled variants, parent-with-children nesting, activeId/isActive auto-expand, isCollapsed (12 tests)
|
|
82
|
+
- [x] ThemePreview — root class, default header vs header/sidebar/footer snippet overrides, showLabels/
|
|
83
|
+
showInputs/compact toggles, embedded sidebar Nav (8 tests)
|
|
84
|
+
- [x] AppShell — slot-driven data-shell regions (conditional vs always-on), children in page-main,
|
|
85
|
+
pageFlexGrow → flex class (7 tests)
|
|
86
|
+
- [x] AppShellSimple — main always renders; header/rail/aside conditional; headerStyle applied (6 tests)
|
|
87
|
+
- [x] AssetsPreview — inline gallery exercises AssetsPreviewContent (name/zoom-state/dots/arrow nav) +
|
|
88
|
+
modal fixture for imperative open()/Close; hermetic 1×1-PNG data URIs (11 tests)
|
|
89
|
+
- [x] Notifications — reactive stack render: role=alert + data-type per intent, dedup count badge,
|
|
90
|
+
close-button removal, noXButton, multiple/empty stacks (8 tests)
|
|
91
|
+
|
|
92
|
+
**Task 15 status:** ✅ DONE — 22 components. Core 16 (FieldInput + 6 Field family + 3 complex Field +
|
|
93
|
+
OtpInput, TypeaheadInput, ColorScheme, ImageCycler, PricingTable, SlidingPanels) plus the final 6
|
|
94
|
+
(Nav, ThemePreview, AppShell, AppShellSimple, AssetsPreview inline+modal, Notifications). The whole
|
|
95
|
+
non-deferred backlog (#14–#17, #19) is now complete; only #18/#20 remain deferred.
|
|
90
96
|
|
|
91
97
|
### Task 16 — Portals / focus-traps
|
|
92
98
|
|
|
@@ -107,6 +113,26 @@ behavioral yield; revisit in a focused follow-up. Moving on to backlog #16/#17.
|
|
|
107
113
|
|
|
108
114
|
## Decisions log
|
|
109
115
|
|
|
116
|
+
- **2026-06-09** — **Task 15 closed — the final 5 postponed components done.** Nav, ThemePreview,
|
|
117
|
+
AppShell, AppShellSimple, AssetsPreview (inline + modal), Notifications — drafted + adversarially
|
|
118
|
+
reviewed in a parallel workflow, then verified against real Chromium + the full-suite gate before
|
|
119
|
+
per-component commits. **484 tests** green; `pnpm check`/`lint`/`test` all clean. The entire
|
|
120
|
+
non-deferred backlog (#14–#17, #19) is now complete; only #18 (standalone E2E) and #20 (visual
|
|
121
|
+
regression) remain deferred. New gotchas learned: (a) **un-caught image preload rejects on dead
|
|
122
|
+
URLs** — `AssetsPreview`/`AssetsPreviewInline` call `preloadImgs(...)` without `.catch`, so a
|
|
123
|
+
network/`example.com` URL surfaces as an unhandled rejection (and isn't hermetic for CI). Fix: pass
|
|
124
|
+
`AssetPreview` objects with a real 1×1-PNG **data-URI** `url` + explicit `name`/`type:"image"` so the
|
|
125
|
+
preload resolves offline. (b) **The AssetsPreviewContent slide has a ~300ms async tail** (`await
|
|
126
|
+
waitForNextRepaint()` + `sleep(300)`); if the component unmounts mid-slide, the continuation reads
|
|
127
|
+
`$state` on a torn-down scope → **`track_reactivity_loss` unhandled rejection**. Fix: after navigating,
|
|
128
|
+
poll until the slide settles (outgoing panel gone → a single `<img>`) so it finishes while mounted.
|
|
129
|
+
(c) Re-confirmed the `page.elementLocator` staleness rule — it snapshots an element by its current
|
|
130
|
+
text, so a name label that changes during navigation must be read live via `expect.poll(() =>
|
|
131
|
+
el.textContent)`. (d) `AssetsPreview.open(index)` settles back to index 0 (its open-effect reads then
|
|
132
|
+
nulls `_openIdx` and re-runs) — a component quirk; the modal test asserts open()/Close only and leaves
|
|
133
|
+
index-precise nav to the inline test. (e) **Nav persists expand state in localStorage** (persistState
|
|
134
|
+
defaults true) → pass `persistState={false}` + `localStorage.clear()` in beforeEach; and never `.click()`
|
|
135
|
+
a Nav `<a href>` leaf (it navigates the page) — assert its attributes instead.
|
|
110
136
|
- **2026-06-08** — **Backlog #15/#16/#17 done (this session).** Tier-2 core (16 components), portals/
|
|
111
137
|
focus-traps (#16: focus-trap action proof + Backdrop/Modal/Drawer/ModalDialog/AlertConfirmPrompt), and
|
|
112
138
|
anchor menus (#17: DropdownMenu/CommandMenu/UserAvatarMenu) — all browser-mode, drafted+adversarially-
|