Files
python-tdd/src/static/tests/SpecRunner.html

58 lines
2.2 KiB
HTML
Raw Normal View History

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="author" content="Disco DeDisco">
<meta name="robots" content="noindex, nofollow">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.8/css/bootstrap.min.css"/>
<link rel="stylesheet" href="lib/jasmine-6.0.1/jasmine.css">
<title>Jasmine Spec Runner</title>
<link rel="stylesheet" href="lib/jasmine.css">
<!-- Jasmine -->
<script src="lib/jasmine-6.0.1/jasmine.js"></script>
<script src="lib/jasmine-6.0.1/jasmine-html.js"></script>
<script src="lib/jasmine-6.0.1/boot0.js"></script>
<!-- spec files -->
<script src="Spec.js"></script>
<script src="RoleSelectSpec.js"></script>
<script src="TraySpec.js"></script>
tray cards: shadow, hover-tilt w. focus persistence, role-card tooltip — TDD - _tray.scss: drop-shadow on cell child elements (img → filter:drop-shadow so the silhouette is the shadow caster, div → box-shadow); 7° hover-tilt on .tray-role-card > img (-7°) and .tray-sig-card > .sig-stage-card (+7° via the standalone `rotate` property so the existing -5° baseline transform composes); :focus persists the tilt after click; cursor: pointer - tray.js: set tabIndex=0 on placeCard's role cell + on template-rendered .tray-role-card / .tray-sig-card cells at init() so :focus latches the hover state; clear tabindex in reset() for Jasmine afterEach - TraySpec: 4 new specs covering placeCard tabindex, reset cleanup, init-time tabindex on template-rendered sig & role cards, no-tabindex on bare cells - New tray-tooltip.js (#id_tooltip_portal) — Phase 1 of the apps.tooltips integration: hovering .tray-role-card > img copies its sibling .tt's innerHTML into the page-root portal, anchors above/below the trigger, & clamps to the viewport horizontally; mousemove outside the union of [trigger, portal] rects clears the portal (Game-Kit pattern, no btns) - room.html: #id_tooltip_portal mounted at room-page root (outside tray's overflow:hidden); .tt block rendered inline inside .tray-role-card via {% tooltip %} templatetag w. title=role display name & description="[Placeholder description]" - epic/views.py: my_tray_role_tooltip context dict ({title, description}) keyed off the seated role - TrayTooltipSpec: 8 specs covering portal population, .active class, sibling-.tt fallback, viewport-edge clamp left/right, and union-rect mouseleave - 2 FTs in test_component_tray_tooltip.py: hover role img → portal title=Player + description=Placeholder; mouseleave → portal clears Phase 2 (sig-card tooltip mirroring #id_fan_fyi_panel via a DRY refactor) deferred per plan. Code architected by Disco DeDisco <discodedisco@outlook.com> Git commit message Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 18:40:10 -04:00
<script src="TrayTooltipSpec.js"></script>
<script src="SigSelectSpec.js"></script>
<script src="SeaDealSpec.js"></script>
Game Kit fan stage + FLIP/SPIN; sig/sea/fan refactor — TDD - fan modal: stage block w. idle-reveal/careen-out; carousel shifts left so focused card sits left-of-center; SPIN rotates whole card via Element.animate(); FLIP toggles polarity (Levity ↔ Gravity) via perspective rotateY w. mid-flip repaint; SPIN state retained across FLIP; FLIP btn hover-revealed only when focused card or btn is hovered (:has) - mobile breakpoints: --fan-card-w / --fan-card-h / --fan-stage-shift / --fan-carousel-step lifted to CSS vars on .tarot-fan-wrap; portrait ≤ 480px @ 150×230, landscape ≤ 500h @ 150×235; corners + face text/padding scale w. card width - shared StageCard JS module (apps/epic/stage-card.js): fromDataset, populateCard, populateKeywords, buildInfoData, renderFyi — sig/sea/fan all delegate; ~150 lines de-duplicated - shared @mixin stat-block-shared (SCSS) lifts duplicated stat-face / stat-keywords / sig-info rules; @mixin stage-card-polarity unifies sea-stage--levity/--gravity + fan[data-polarity] coloring - model rename: TarotCard.reversal → reversal_qualifier (migration 0014); render-time fallback to current polarity's qualifier when blank - class unification: .sig-info-open / .sea-info-open / .fyi-open → .fyi-open (on stat block); .sig-flip-btn / .sea-spin-btn / .fan-spin-btn → .spin-btn; same for .fyi-btn / .fyi-prev / .fyi-next - custom combobox (apps/epic/combobox.js) replaces native <select> for PICK SEA spread picker — keyboard nav, click-outside-close, aria roles; Firefox/Chrome OS-rendered <option> ignored CSS - Jasmine: FanStageSpec.js w. idle-reveal / population / SPIN / FYI / FLIP specs; sig + sea fixtures + IT view assertions updated for renamed classes - 748 ITs + Jasmine green Code architected by Disco DeDisco <discodedisco@outlook.com> Git commit message Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 21:01:52 -04:00
<script src="FanStageSpec.js"></script>
<script src="SkyWheelSpec.js"></script>
<script src="NoteSpec.js"></script>
<script src="NotePageSpec.js"></script>
applet rows: hover + click-lock highlight on every `.applet-list-entry.row-3col` (My Posts / My Buds / My Notes / My Scrolls / My Games) — bg shifts to --secUser, title to --quiUser (overriding the inherited --terUser link color + stripping the text-shadow the global `.applet-list-entry a:hover` rule had been baking in), body + ts cells come up from their dimmed 0.6 / 0.5 opacity to full --priUser so the dim middle/right cols pop against the --secUser fill; new `apps/applets/static/apps/applets/row-lock.js` IIFE module owns the touch-persistence state machine (single `_lockedRow` ref, `.row-locked` class toggle): clicking a row not currently locked → locks (clearing any prior lock); clicking the locked row again → unlocks; clicking another row → moves the lock to the new row; clicking anywhere not inside a `.row-3col` → clears the lock — mirrors the note-page `notes-locked` click-lock state machine but lighter (no DON/DOFF, no greeting swap, no fetch), one document-level click listener bound once via `_bound` re-entry guard so beforeEach `_init()` calls in specs don't pile up handlers; loaded globally via `base.html` next to `applets.js` since the rows render on both /billboard/ + /gameboard/; padding-inline 0.5rem + border-radius 0.25rem on the row container shrinks the highlight to a chip shape so hovered rows don't bleed all the way to the applet box edge; 6 Jasmine specs in `RowLockSpec.js` cover the four state-machine transitions + the "child element of row still locks the parent row" affordance (since the user can tap the body cell text, not just the title link) + the "only one row carries .row-locked at a time" invariant; SpecRunner.html updated (both static_src + the static/ runtime mirror the FT reads from per the project's static-src→static copy discipline) — TDD Code architected by Disco DeDisco <discodedisco@outlook.com> Git commit message Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 00:27:39 -04:00
<script src="RowLockSpec.js"></script>
feat: wallet Shop applet — tile grid + BUY-ITEM microbutton + Stripe.js wiring — Chunk 4 of [[project-wallet-shop-expansion]]. The shop applet (slug `wallet-shop`, seeded in Chunk 2) now renders the catalog as a horizontal grid of `.shop-tile` icons: `tithe-1` ($1, fa-piggy-bank), `tithe-5` ($4, fa-piggy-bank w. `×5` badge), `band-1` ($20, fa-ring). Each tile hosts a hover-portaled tooltip carrying name + description + price + a `.tt-microbutton-portal` w. a `.btn-primary` BUY ITEM button — clicking opens `#id_guard_portal` w. "Buy {name} for ${price}?" prompt; confirming triggers Stripe.js confirmCardPayment then POSTs to /shop/confirm + reloads. Items where the user's owned-count has hit `max_owned` (eg. BAND, owned=1, cap=1) render w. `.btn-disabled` + × glyph + "Already owned" microtooltip text — visible-but-unbuyable per the locked decision. View context — `wallet` view + `toggle_wallet_applets` view both pass `shop_items` (decorated w. per-user `.available` via the new `_shop_items_for(user)` helper) + `default_payment_method_id` + `stripe_publishable_key`. SCSS — `.wallet-shop` (flex column wrapping `.shop-grid` flex row), `.shop-tile` (inline-flex tooltip target), `.shop-badge` (2rem circle, --quaUser glyph on --quiUser bg, top-right corner per spec), `.tt-microbutton-portal` (column-flex, BUY btn + 'Already owned' caption styling). JS in `wallet-shop.js` exposes a singleton `WalletShop` module (matching the project's `Brief` / `SeaDeal` / `StageCard` module pattern) w. a tested `initWalletShop()` method — uses event delegation on the shop root (so portal-relocated buy btns still hit the handler) + a DOM-keyed `data-shop-wired` flag (not a module-level boolean) so per-test fixture rebuilds re-wire cleanly. Wired into `wallet.html` after `wallet.js`. **TDD** — 5 Jasmine specs in `WalletShopSpec.js`: T1 click-on-enabled-BUY opens guard w. correct prompt; T2 click-on-disabled-BUY no-op; T3 onConfirm POSTs `shop_item_slug` to `/shop/buy`; T4 init idempotent (calling twice doesn't double-wire); T5 missing-root no-throw. **2 Jasmine traps caught**: (a) `spyOn(window, 'fetch')` collides if another spec already spied on fetch — switched to save+restore via per-test `_origFetch` capture; (b) T3 async pollution — sync assertion passed, `afterEach` restored `window.Stripe=undefined`, then `_doBuy`'s async continuation hit `Stripe(pubKey)` and threw "Unhandled promise rejection". Fixed by T3-local fetch mock returning a never-resolving promise so the chain pauses at the first await. **3 new FTs** in `test_dash_wallet.py`: tiles + icons + ×5 badge + tooltip prose; BUY click opens guard portal + NVM dismisses; BAND-already-owned shows disabled BUY w. 'Already owned' microtext (reads via `textContent` since `.tt` is `display: none`). FT trap caught: `TransactionTestCase` wipes both migration-seeded Applets + ShopItems → setUp must re-seed both manually (mirrors `test_shop_views.py`'s `_seed_starting_items` pattern). 1208 IT/UT + 9 wallet FTs + 5 Jasmine specs green Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 01:15:05 -04:00
<script src="WalletShopSpec.js"></script>
<!-- src files -->
applet rows: hover + click-lock highlight on every `.applet-list-entry.row-3col` (My Posts / My Buds / My Notes / My Scrolls / My Games) — bg shifts to --secUser, title to --quiUser (overriding the inherited --terUser link color + stripping the text-shadow the global `.applet-list-entry a:hover` rule had been baking in), body + ts cells come up from their dimmed 0.6 / 0.5 opacity to full --priUser so the dim middle/right cols pop against the --secUser fill; new `apps/applets/static/apps/applets/row-lock.js` IIFE module owns the touch-persistence state machine (single `_lockedRow` ref, `.row-locked` class toggle): clicking a row not currently locked → locks (clearing any prior lock); clicking the locked row again → unlocks; clicking another row → moves the lock to the new row; clicking anywhere not inside a `.row-3col` → clears the lock — mirrors the note-page `notes-locked` click-lock state machine but lighter (no DON/DOFF, no greeting swap, no fetch), one document-level click listener bound once via `_bound` re-entry guard so beforeEach `_init()` calls in specs don't pile up handlers; loaded globally via `base.html` next to `applets.js` since the rows render on both /billboard/ + /gameboard/; padding-inline 0.5rem + border-radius 0.25rem on the row container shrinks the highlight to a chip shape so hovered rows don't bleed all the way to the applet box edge; 6 Jasmine specs in `RowLockSpec.js` cover the four state-machine transitions + the "child element of row still locks the parent row" affordance (since the user can tap the body cell text, not just the title link) + the "only one row carries .row-locked at a time" invariant; SpecRunner.html updated (both static_src + the static/ runtime mirror the FT reads from per the project's static-src→static copy discipline) — TDD Code architected by Disco DeDisco <discodedisco@outlook.com> Git commit message Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 00:27:39 -04:00
<script src="/static/apps/applets/row-lock.js"></script>
<script src="/static/apps/dashboard/dashboard.js"></script>
<script src="/static/apps/dashboard/note.js"></script>
feat: wallet Shop applet — tile grid + BUY-ITEM microbutton + Stripe.js wiring — Chunk 4 of [[project-wallet-shop-expansion]]. The shop applet (slug `wallet-shop`, seeded in Chunk 2) now renders the catalog as a horizontal grid of `.shop-tile` icons: `tithe-1` ($1, fa-piggy-bank), `tithe-5` ($4, fa-piggy-bank w. `×5` badge), `band-1` ($20, fa-ring). Each tile hosts a hover-portaled tooltip carrying name + description + price + a `.tt-microbutton-portal` w. a `.btn-primary` BUY ITEM button — clicking opens `#id_guard_portal` w. "Buy {name} for ${price}?" prompt; confirming triggers Stripe.js confirmCardPayment then POSTs to /shop/confirm + reloads. Items where the user's owned-count has hit `max_owned` (eg. BAND, owned=1, cap=1) render w. `.btn-disabled` + × glyph + "Already owned" microtooltip text — visible-but-unbuyable per the locked decision. View context — `wallet` view + `toggle_wallet_applets` view both pass `shop_items` (decorated w. per-user `.available` via the new `_shop_items_for(user)` helper) + `default_payment_method_id` + `stripe_publishable_key`. SCSS — `.wallet-shop` (flex column wrapping `.shop-grid` flex row), `.shop-tile` (inline-flex tooltip target), `.shop-badge` (2rem circle, --quaUser glyph on --quiUser bg, top-right corner per spec), `.tt-microbutton-portal` (column-flex, BUY btn + 'Already owned' caption styling). JS in `wallet-shop.js` exposes a singleton `WalletShop` module (matching the project's `Brief` / `SeaDeal` / `StageCard` module pattern) w. a tested `initWalletShop()` method — uses event delegation on the shop root (so portal-relocated buy btns still hit the handler) + a DOM-keyed `data-shop-wired` flag (not a module-level boolean) so per-test fixture rebuilds re-wire cleanly. Wired into `wallet.html` after `wallet.js`. **TDD** — 5 Jasmine specs in `WalletShopSpec.js`: T1 click-on-enabled-BUY opens guard w. correct prompt; T2 click-on-disabled-BUY no-op; T3 onConfirm POSTs `shop_item_slug` to `/shop/buy`; T4 init idempotent (calling twice doesn't double-wire); T5 missing-root no-throw. **2 Jasmine traps caught**: (a) `spyOn(window, 'fetch')` collides if another spec already spied on fetch — switched to save+restore via per-test `_origFetch` capture; (b) T3 async pollution — sync assertion passed, `afterEach` restored `window.Stripe=undefined`, then `_doBuy`'s async continuation hit `Stripe(pubKey)` and threw "Unhandled promise rejection". Fixed by T3-local fetch mock returning a never-resolving promise so the chain pauses at the first await. **3 new FTs** in `test_dash_wallet.py`: tiles + icons + ×5 badge + tooltip prose; BUY click opens guard portal + NVM dismisses; BAND-already-owned shows disabled BUY w. 'Already owned' microtext (reads via `textContent` since `.tt` is `display: none`). FT trap caught: `TransactionTestCase` wipes both migration-seeded Applets + ShopItems → setUp must re-seed both manually (mirrors `test_shop_views.py`'s `_seed_starting_items` pattern). 1208 IT/UT + 9 wallet FTs + 5 Jasmine specs green Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 01:15:05 -04:00
<script src="/static/apps/dashboard/wallet-shop.js"></script>
<script src="/static/apps/billboard/note-page.js"></script>
Game Kit fan stage + FLIP/SPIN; sig/sea/fan refactor — TDD - fan modal: stage block w. idle-reveal/careen-out; carousel shifts left so focused card sits left-of-center; SPIN rotates whole card via Element.animate(); FLIP toggles polarity (Levity ↔ Gravity) via perspective rotateY w. mid-flip repaint; SPIN state retained across FLIP; FLIP btn hover-revealed only when focused card or btn is hovered (:has) - mobile breakpoints: --fan-card-w / --fan-card-h / --fan-stage-shift / --fan-carousel-step lifted to CSS vars on .tarot-fan-wrap; portrait ≤ 480px @ 150×230, landscape ≤ 500h @ 150×235; corners + face text/padding scale w. card width - shared StageCard JS module (apps/epic/stage-card.js): fromDataset, populateCard, populateKeywords, buildInfoData, renderFyi — sig/sea/fan all delegate; ~150 lines de-duplicated - shared @mixin stat-block-shared (SCSS) lifts duplicated stat-face / stat-keywords / sig-info rules; @mixin stage-card-polarity unifies sea-stage--levity/--gravity + fan[data-polarity] coloring - model rename: TarotCard.reversal → reversal_qualifier (migration 0014); render-time fallback to current polarity's qualifier when blank - class unification: .sig-info-open / .sea-info-open / .fyi-open → .fyi-open (on stat block); .sig-flip-btn / .sea-spin-btn / .fan-spin-btn → .spin-btn; same for .fyi-btn / .fyi-prev / .fyi-next - custom combobox (apps/epic/combobox.js) replaces native <select> for PICK SEA spread picker — keyboard nav, click-outside-close, aria roles; Firefox/Chrome OS-rendered <option> ignored CSS - Jasmine: FanStageSpec.js w. idle-reveal / population / SPIN / FYI / FLIP specs; sig + sea fixtures + IT view assertions updated for renamed classes - 748 ITs + Jasmine green Code architected by Disco DeDisco <discodedisco@outlook.com> Git commit message Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 21:01:52 -04:00
<script src="/static/apps/epic/stage-card.js"></script>
<script src="/static/apps/epic/role-select.js"></script>
<script src="/static/apps/epic/tray.js"></script>
tray cards: shadow, hover-tilt w. focus persistence, role-card tooltip — TDD - _tray.scss: drop-shadow on cell child elements (img → filter:drop-shadow so the silhouette is the shadow caster, div → box-shadow); 7° hover-tilt on .tray-role-card > img (-7°) and .tray-sig-card > .sig-stage-card (+7° via the standalone `rotate` property so the existing -5° baseline transform composes); :focus persists the tilt after click; cursor: pointer - tray.js: set tabIndex=0 on placeCard's role cell + on template-rendered .tray-role-card / .tray-sig-card cells at init() so :focus latches the hover state; clear tabindex in reset() for Jasmine afterEach - TraySpec: 4 new specs covering placeCard tabindex, reset cleanup, init-time tabindex on template-rendered sig & role cards, no-tabindex on bare cells - New tray-tooltip.js (#id_tooltip_portal) — Phase 1 of the apps.tooltips integration: hovering .tray-role-card > img copies its sibling .tt's innerHTML into the page-root portal, anchors above/below the trigger, & clamps to the viewport horizontally; mousemove outside the union of [trigger, portal] rects clears the portal (Game-Kit pattern, no btns) - room.html: #id_tooltip_portal mounted at room-page root (outside tray's overflow:hidden); .tt block rendered inline inside .tray-role-card via {% tooltip %} templatetag w. title=role display name & description="[Placeholder description]" - epic/views.py: my_tray_role_tooltip context dict ({title, description}) keyed off the seated role - TrayTooltipSpec: 8 specs covering portal population, .active class, sibling-.tt fallback, viewport-edge clamp left/right, and union-rect mouseleave - 2 FTs in test_component_tray_tooltip.py: hover role img → portal title=Player + description=Placeholder; mouseleave → portal clears Phase 2 (sig-card tooltip mirroring #id_fan_fyi_panel via a DRY refactor) deferred per plan. Code architected by Disco DeDisco <discodedisco@outlook.com> Git commit message Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 18:40:10 -04:00
<script src="/static/apps/epic/tray-tooltip.js"></script>
<script src="/static/apps/epic/sig-select.js"></script>
<script src="/static/apps/epic/sea.js"></script>
Game Kit fan stage + FLIP/SPIN; sig/sea/fan refactor — TDD - fan modal: stage block w. idle-reveal/careen-out; carousel shifts left so focused card sits left-of-center; SPIN rotates whole card via Element.animate(); FLIP toggles polarity (Levity ↔ Gravity) via perspective rotateY w. mid-flip repaint; SPIN state retained across FLIP; FLIP btn hover-revealed only when focused card or btn is hovered (:has) - mobile breakpoints: --fan-card-w / --fan-card-h / --fan-stage-shift / --fan-carousel-step lifted to CSS vars on .tarot-fan-wrap; portrait ≤ 480px @ 150×230, landscape ≤ 500h @ 150×235; corners + face text/padding scale w. card width - shared StageCard JS module (apps/epic/stage-card.js): fromDataset, populateCard, populateKeywords, buildInfoData, renderFyi — sig/sea/fan all delegate; ~150 lines de-duplicated - shared @mixin stat-block-shared (SCSS) lifts duplicated stat-face / stat-keywords / sig-info rules; @mixin stage-card-polarity unifies sea-stage--levity/--gravity + fan[data-polarity] coloring - model rename: TarotCard.reversal → reversal_qualifier (migration 0014); render-time fallback to current polarity's qualifier when blank - class unification: .sig-info-open / .sea-info-open / .fyi-open → .fyi-open (on stat block); .sig-flip-btn / .sea-spin-btn / .fan-spin-btn → .spin-btn; same for .fyi-btn / .fyi-prev / .fyi-next - custom combobox (apps/epic/combobox.js) replaces native <select> for PICK SEA spread picker — keyboard nav, click-outside-close, aria roles; Firefox/Chrome OS-rendered <option> ignored CSS - Jasmine: FanStageSpec.js w. idle-reveal / population / SPIN / FYI / FLIP specs; sig + sea fixtures + IT view assertions updated for renamed classes - 748 ITs + Jasmine green Code architected by Disco DeDisco <discodedisco@outlook.com> Git commit message Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 21:01:52 -04:00
<script src="/static/apps/gameboard/game-kit.js"></script>
<script src="/static/apps/gameboard/d3.min.js"></script>
<script src="/static/apps/gameboard/sky-wheel.js"></script>
<!-- Jasmine env config (optional) -->
<script src="lib/jasmine-6.0.1/boot1.js"></script>
</head>
<body>
</body>
</html>