diff --git a/src/apps/epic/models.py b/src/apps/epic/models.py index 84794cb..c14a269 100644 --- a/src/apps/epic/models.py +++ b/src/apps/epic/models.py @@ -341,6 +341,16 @@ class TarotCard(models.Model): import json return json.dumps(self.cautions) + @property + def mechanisms_json(self): + import json + return json.dumps(self.mechanisms) + + @property + def articulations_json(self): + import json + return json.dumps(self.articulations) + def __str__(self): return self.name diff --git a/src/apps/epic/static/apps/epic/sig-select.js b/src/apps/epic/static/apps/epic/sig-select.js index 6fc49be..232b05c 100644 --- a/src/apps/epic/static/apps/epic/sig-select.js +++ b/src/apps/epic/static/apps/epic/sig-select.js @@ -6,7 +6,7 @@ var SigSelect = (function () { }; var overlay, deckGrid, stage, stageCard, statBlock; - var cautionEl, cautionEffect, cautionPrev, cautionNext, cautionIndexEl; + var cautionEl, cautionEffect, cautionTitle, cautionPrev, cautionNext, cautionIndexEl; var _flipBtn, _cautionBtn, _flipOrigLabel, _cautionOrigLabel; var reserveUrl, readyUrl, userRole, userPolarity; @@ -47,13 +47,16 @@ var SigSelect = (function () { function _renderCaution() { if (_cautionData.length === 0) { - cautionEffect.innerHTML = 'Rival interactions pending.'; + if (cautionTitle) cautionTitle.textContent = 'Ally Interaction'; + cautionEffect.innerHTML = 'No ally interactions defined.'; cautionPrev.disabled = true; cautionNext.disabled = true; cautionIndexEl.textContent = ''; return; } - cautionEffect.innerHTML = _cautionData[_cautionIdx]; + var entry = _cautionData[_cautionIdx]; + if (cautionTitle) cautionTitle.textContent = entry.category || ''; + cautionEffect.innerHTML = entry.effect || ''; cautionPrev.disabled = (_cautionData.length <= 1); cautionNext.disabled = (_cautionData.length <= 1); cautionIndexEl.textContent = _cautionData.length > 1 @@ -64,7 +67,9 @@ var SigSelect = (function () { function _openCaution() { if (!_focusedCardEl) return; try { - _cautionData = JSON.parse(_focusedCardEl.dataset.cautions || '[]'); + var mechanisms = JSON.parse(_focusedCardEl.dataset.mechanisms || '[]'); + var articulations = JSON.parse(_focusedCardEl.dataset.articulations || '[]'); + _cautionData = mechanisms.concat(articulations); } catch (e) { _cautionData = []; } @@ -623,6 +628,7 @@ var SigSelect = (function () { cautionEl = stage.querySelector('.sig-caution-tooltip'); cautionEffect = cautionEl.querySelector('.sig-caution-effect'); + cautionTitle = cautionEl.querySelector('.sig-caution-title'); cautionPrev = statBlock.querySelector('.sig-caution-prev'); cautionNext = statBlock.querySelector('.sig-caution-next'); cautionIndexEl = cautionEl.querySelector('.sig-caution-index'); diff --git a/src/static/tests/SigSelectSpec.js b/src/static/tests/SigSelectSpec.js index a93d148..15f1aef 100644 --- a/src/static/tests/SigSelectSpec.js +++ b/src/static/tests/SigSelectSpec.js @@ -29,21 +29,20 @@ describe("SigSelect", () => {
-

Upright

+

Emanation

-

Reversed

+

Reversal

-

Caution!

- Rival Interaction +

+ Ally Interaction
-

[Shoptalk forthcoming]

@@ -61,6 +60,8 @@ describe("SigSelect", () => { data-keywords-upright="action,impulsiveness,ambition" data-keywords-reversed="no direction,disregard for consequences" data-cautions="${cardCautions.replace(/"/g, '"')}" + data-mechanisms="[]" + data-articulations="[]" data-levity-qualifier="Elevated" data-gravity-qualifier="Graven" data-reversal="Territoriality"> @@ -238,71 +239,96 @@ describe("SigSelect", () => { expect(testDiv.querySelector(".sig-stage").classList.contains("sig-caution-open")).toBe(true); }); - it("shows placeholder text when cautions list is empty", () => { - card.dataset.cautions = "[]"; + it("shows placeholder when both mechanisms and articulations are empty", () => { + card.dataset.mechanisms = "[]"; + card.dataset.articulations = "[]"; openCaution(); - expect(cautionEffect.innerHTML).toContain("pending"); + expect(cautionEffect.innerHTML).toContain("No ally interactions defined"); }); - it("renders first caution effect HTML including .card-ref spans", () => { - card.dataset.cautions = JSON.stringify(['First Card effect.']); + it("renders first mechanism effect HTML including .card-ref spans", () => { + card.dataset.mechanisms = JSON.stringify([ + { category: "Mechanism", effect: 'First Card effect.' } + ]); openCaution(); expect(cautionEffect.querySelector(".card-ref")).not.toBeNull(); expect(cautionEffect.querySelector(".card-ref").textContent).toBe("Card"); }); - it("with 1 caution both nav arrows are disabled", () => { - card.dataset.cautions = JSON.stringify(["Single caution."]); + it("with 1 entry both nav arrows are disabled", () => { + card.dataset.mechanisms = JSON.stringify([{ category: "Mechanism", effect: "Single." }]); openCaution(); expect(cautionPrev.disabled).toBe(true); expect(cautionNext.disabled).toBe(true); }); - it("with multiple cautions both nav arrows are always enabled", () => { - card.dataset.cautions = JSON.stringify(["C1", "C2", "C3", "C4"]); + it("with multiple entries both nav arrows are always enabled", () => { + card.dataset.mechanisms = JSON.stringify([ + { category: "Mechanism", effect: "C1" }, + { category: "Mechanism", effect: "C2" }, + { category: "Mechanism", effect: "C3" }, + { category: "Mechanism", effect: "C4" }, + ]); openCaution(); expect(cautionPrev.disabled).toBe(false); expect(cautionNext.disabled).toBe(false); }); - it("next click advances to second caution", () => { - card.dataset.cautions = JSON.stringify(["First", "Second"]); + it("next click advances to second entry", () => { + card.dataset.mechanisms = JSON.stringify([ + { category: "Mechanism", effect: "First" }, + { category: "Mechanism", effect: "Second" }, + ]); openCaution(); cautionNext.dispatchEvent(new MouseEvent("click", { bubbles: true })); expect(cautionEffect.innerHTML).toContain("Second"); }); - it("next wraps from last caution back to first", () => { - card.dataset.cautions = JSON.stringify(["First", "Last"]); + it("next wraps from last entry back to first", () => { + card.dataset.mechanisms = JSON.stringify([ + { category: "Mechanism", effect: "First" }, + { category: "Mechanism", effect: "Last" }, + ]); openCaution(); cautionNext.dispatchEvent(new MouseEvent("click", { bubbles: true })); cautionNext.dispatchEvent(new MouseEvent("click", { bubbles: true })); expect(cautionEffect.innerHTML).toContain("First"); }); - it("prev click goes back to first caution", () => { - card.dataset.cautions = JSON.stringify(["First", "Second"]); + it("prev click goes back to first entry", () => { + card.dataset.mechanisms = JSON.stringify([ + { category: "Mechanism", effect: "First" }, + { category: "Mechanism", effect: "Second" }, + ]); openCaution(); cautionNext.dispatchEvent(new MouseEvent("click", { bubbles: true })); cautionPrev.dispatchEvent(new MouseEvent("click", { bubbles: true })); expect(cautionEffect.innerHTML).toContain("First"); }); - it("prev wraps from first caution to last", () => { - card.dataset.cautions = JSON.stringify(["First", "Middle", "Last"]); + it("prev wraps from first entry to last", () => { + card.dataset.mechanisms = JSON.stringify([ + { category: "Mechanism", effect: "First" }, + { category: "Mechanism", effect: "Middle" }, + { category: "Mechanism", effect: "Last" }, + ]); openCaution(); cautionPrev.dispatchEvent(new MouseEvent("click", { bubbles: true })); expect(cautionEffect.innerHTML).toContain("Last"); }); - it("index label shows n / total when multiple cautions", () => { - card.dataset.cautions = JSON.stringify(["C1", "C2", "C3"]); + it("index label shows n / total when multiple entries", () => { + card.dataset.mechanisms = JSON.stringify([ + { category: "Mechanism", effect: "C1" }, + { category: "Mechanism", effect: "C2" }, + { category: "Mechanism", effect: "C3" }, + ]); openCaution(); expect(testDiv.querySelector(".sig-caution-index").textContent).toBe("1 / 3"); }); - it("index label is empty when only 1 caution", () => { - card.dataset.cautions = JSON.stringify(["Only one."]); + it("index label is empty when only 1 entry", () => { + card.dataset.mechanisms = JSON.stringify([{ category: "Mechanism", effect: "Only one." }]); openCaution(); expect(testDiv.querySelector(".sig-caution-index").textContent).toBe(""); }); @@ -314,8 +340,11 @@ describe("SigSelect", () => { expect(testDiv.querySelector(".sig-stage").classList.contains("sig-caution-open")).toBe(false); }); - it("opening again resets to first caution", () => { - card.dataset.cautions = JSON.stringify(["First", "Second"]); + it("opening again resets to first entry", () => { + card.dataset.mechanisms = JSON.stringify([ + { category: "Mechanism", effect: "First" }, + { category: "Mechanism", effect: "Second" }, + ]); openCaution(); cautionNext.dispatchEvent(new MouseEvent("click", { bubbles: true })); // Close and reopen @@ -757,4 +786,87 @@ describe("SigSelect", () => { expect(takeSigBtn.classList.contains("btn-cancel")).toBe(false); }); }); + + // ── FYI tooltip — mechanisms + articulations data source ──────────────── // + // + // Sprint 2: the caution tooltip is reworked to draw from data-mechanisms and + // data-articulations instead of data-cautions. Entries are {category, effect} + // dicts; the category label replaces the old "Caution!" title; the caution-type + // reads "Ally Interaction". Shoptalk is absent. + + describe("FYI from mechanisms + articulations", () => { + var cautionEffect, cautionTitle, cautionType, cautionPrev, cautionNext, cautionBtn; + + beforeEach(() => { + makeFixture(); + cautionEffect = testDiv.querySelector(".sig-caution-effect"); + cautionTitle = testDiv.querySelector(".sig-caution-title"); + cautionType = testDiv.querySelector(".sig-caution-type"); + cautionPrev = testDiv.querySelector(".sig-caution-prev"); + cautionNext = testDiv.querySelector(".sig-caution-next"); + cautionBtn = testDiv.querySelector(".sig-caution-btn"); + }); + + function hover() { + card.dispatchEvent(new MouseEvent("mouseenter", { bubbles: true })); + } + function openFYI() { + hover(); + cautionBtn.dispatchEvent(new MouseEvent("click", { bubbles: true })); + } + + it("caution-type label reads 'Ally Interaction'", () => { + openFYI(); + expect(cautionType.textContent).toBe("Ally Interaction"); + }); + + it("shows 'No ally interactions defined.' when both lists are empty", () => { + card.dataset.mechanisms = "[]"; + card.dataset.articulations = "[]"; + openFYI(); + expect(cautionEffect.textContent).toContain("No ally interactions defined"); + }); + + it("renders first mechanism effect and sets title to its category", () => { + card.dataset.mechanisms = JSON.stringify([ + { category: "Mechanism", effect: "The card amplifies adjacent power." } + ]); + openFYI(); + expect(cautionTitle.textContent).toBe("Mechanism"); + expect(cautionEffect.textContent).toContain("amplifies adjacent power"); + }); + + it("mechanisms come before articulations in the combined list", () => { + card.dataset.mechanisms = JSON.stringify([{ category: "Mechanism", effect: "First" }]); + card.dataset.articulations = JSON.stringify([{ category: "Articulation", effect: "Second" }]); + openFYI(); + expect(cautionEffect.textContent).toContain("First"); + cautionNext.dispatchEvent(new MouseEvent("click", { bubbles: true })); + expect(cautionEffect.textContent).toContain("Second"); + }); + + it("articulation title is set from its category field", () => { + card.dataset.mechanisms = JSON.stringify([{ category: "Mechanism", effect: "M1" }]); + card.dataset.articulations = JSON.stringify([{ category: "Articulation", effect: "A1" }]); + openFYI(); + cautionNext.dispatchEvent(new MouseEvent("click", { bubbles: true })); + expect(cautionTitle.textContent).toBe("Articulation"); + }); + + it("effect HTML is injected (supports .card-ref spans)", () => { + card.dataset.mechanisms = JSON.stringify([ + { category: "Mechanism", effect: 'Draw The Occultist.' } + ]); + openFYI(); + expect(cautionEffect.querySelector(".card-ref")).not.toBeNull(); + expect(cautionEffect.querySelector(".card-ref").textContent).toBe("The Occultist"); + }); + + it("shoptalk element is absent or empty", () => { + openFYI(); + var shoptalk = testDiv.querySelector(".sig-caution-shoptalk"); + // Either removed from DOM or has no visible content + expect(!shoptalk || shoptalk.textContent.trim() === "").toBe(true); + }); + }); }); diff --git a/src/static_src/scss/_card-deck.scss b/src/static_src/scss/_card-deck.scss index 06465fa..09fcfb3 100644 --- a/src/static_src/scss/_card-deck.scss +++ b/src/static_src/scss/_card-deck.scss @@ -173,7 +173,6 @@ html:has(.sig-backdrop) { align-items: flex-end; padding-left: 1.5rem; gap: 0.75rem; - // Preview card — width driven by JS via --sig-card-w; aspect-ratio derives height. .sig-stage-card { flex-shrink: 0; @@ -188,6 +187,7 @@ html:has(.sig-backdrop) { position: relative; padding: 0.25rem; overflow: hidden; + transition: transform 0.4s ease; // game-kit sets .fan-card-corner { position: absolute; top/left offsets } // so these just need display/font overrides; the corners land at the card edges. @@ -230,6 +230,26 @@ html:has(.sig-backdrop) { .fan-card-name { font-size: calc(var(--sig-card-w, 120px) * 0.093); font-weight: 600; } .fan-card-arcana { font-size: calc(var(--sig-card-w, 120px) * 0.067); text-transform: uppercase; letter-spacing: 0.06em; opacity: 0.5; } .fan-card-correspondence{ display: none; } // Minchiate equivalence shown in game-kit only + // Reversed face — counter-rotated so they read forward when card is spun + .fan-card-reversal-qualifier, + .fan-card-reversal-name { + transform: rotate(180deg); + opacity: 0.25; + transition: opacity 0.2s; + font-weight: 600; + } + .fan-card-reversal-qualifier { font-size: calc(var(--sig-card-w, 120px) * 0.093); } + .fan-card-reversal-name { font-size: calc(var(--sig-card-w, 120px) * 0.073); opacity: 0.2; } + } + + &.stage-card--reversed { + transform: rotate(180deg); + + .fan-card-reversal-qualifier, + .fan-card-reversal-name { opacity: 1; } + .fan-card-name, + .sig-qualifier-above, + .sig-qualifier-below { opacity: 0.25; } } } diff --git a/src/static_src/tests/SigSelectSpec.js b/src/static_src/tests/SigSelectSpec.js index a93d148..15f1aef 100644 --- a/src/static_src/tests/SigSelectSpec.js +++ b/src/static_src/tests/SigSelectSpec.js @@ -29,21 +29,20 @@ describe("SigSelect", () => {
-

Upright

+

Emanation

-

Reversed

+

Reversal

-

Caution!

- Rival Interaction +

+ Ally Interaction
-

[Shoptalk forthcoming]

@@ -61,6 +60,8 @@ describe("SigSelect", () => { data-keywords-upright="action,impulsiveness,ambition" data-keywords-reversed="no direction,disregard for consequences" data-cautions="${cardCautions.replace(/"/g, '"')}" + data-mechanisms="[]" + data-articulations="[]" data-levity-qualifier="Elevated" data-gravity-qualifier="Graven" data-reversal="Territoriality"> @@ -238,71 +239,96 @@ describe("SigSelect", () => { expect(testDiv.querySelector(".sig-stage").classList.contains("sig-caution-open")).toBe(true); }); - it("shows placeholder text when cautions list is empty", () => { - card.dataset.cautions = "[]"; + it("shows placeholder when both mechanisms and articulations are empty", () => { + card.dataset.mechanisms = "[]"; + card.dataset.articulations = "[]"; openCaution(); - expect(cautionEffect.innerHTML).toContain("pending"); + expect(cautionEffect.innerHTML).toContain("No ally interactions defined"); }); - it("renders first caution effect HTML including .card-ref spans", () => { - card.dataset.cautions = JSON.stringify(['First Card effect.']); + it("renders first mechanism effect HTML including .card-ref spans", () => { + card.dataset.mechanisms = JSON.stringify([ + { category: "Mechanism", effect: 'First Card effect.' } + ]); openCaution(); expect(cautionEffect.querySelector(".card-ref")).not.toBeNull(); expect(cautionEffect.querySelector(".card-ref").textContent).toBe("Card"); }); - it("with 1 caution both nav arrows are disabled", () => { - card.dataset.cautions = JSON.stringify(["Single caution."]); + it("with 1 entry both nav arrows are disabled", () => { + card.dataset.mechanisms = JSON.stringify([{ category: "Mechanism", effect: "Single." }]); openCaution(); expect(cautionPrev.disabled).toBe(true); expect(cautionNext.disabled).toBe(true); }); - it("with multiple cautions both nav arrows are always enabled", () => { - card.dataset.cautions = JSON.stringify(["C1", "C2", "C3", "C4"]); + it("with multiple entries both nav arrows are always enabled", () => { + card.dataset.mechanisms = JSON.stringify([ + { category: "Mechanism", effect: "C1" }, + { category: "Mechanism", effect: "C2" }, + { category: "Mechanism", effect: "C3" }, + { category: "Mechanism", effect: "C4" }, + ]); openCaution(); expect(cautionPrev.disabled).toBe(false); expect(cautionNext.disabled).toBe(false); }); - it("next click advances to second caution", () => { - card.dataset.cautions = JSON.stringify(["First", "Second"]); + it("next click advances to second entry", () => { + card.dataset.mechanisms = JSON.stringify([ + { category: "Mechanism", effect: "First" }, + { category: "Mechanism", effect: "Second" }, + ]); openCaution(); cautionNext.dispatchEvent(new MouseEvent("click", { bubbles: true })); expect(cautionEffect.innerHTML).toContain("Second"); }); - it("next wraps from last caution back to first", () => { - card.dataset.cautions = JSON.stringify(["First", "Last"]); + it("next wraps from last entry back to first", () => { + card.dataset.mechanisms = JSON.stringify([ + { category: "Mechanism", effect: "First" }, + { category: "Mechanism", effect: "Last" }, + ]); openCaution(); cautionNext.dispatchEvent(new MouseEvent("click", { bubbles: true })); cautionNext.dispatchEvent(new MouseEvent("click", { bubbles: true })); expect(cautionEffect.innerHTML).toContain("First"); }); - it("prev click goes back to first caution", () => { - card.dataset.cautions = JSON.stringify(["First", "Second"]); + it("prev click goes back to first entry", () => { + card.dataset.mechanisms = JSON.stringify([ + { category: "Mechanism", effect: "First" }, + { category: "Mechanism", effect: "Second" }, + ]); openCaution(); cautionNext.dispatchEvent(new MouseEvent("click", { bubbles: true })); cautionPrev.dispatchEvent(new MouseEvent("click", { bubbles: true })); expect(cautionEffect.innerHTML).toContain("First"); }); - it("prev wraps from first caution to last", () => { - card.dataset.cautions = JSON.stringify(["First", "Middle", "Last"]); + it("prev wraps from first entry to last", () => { + card.dataset.mechanisms = JSON.stringify([ + { category: "Mechanism", effect: "First" }, + { category: "Mechanism", effect: "Middle" }, + { category: "Mechanism", effect: "Last" }, + ]); openCaution(); cautionPrev.dispatchEvent(new MouseEvent("click", { bubbles: true })); expect(cautionEffect.innerHTML).toContain("Last"); }); - it("index label shows n / total when multiple cautions", () => { - card.dataset.cautions = JSON.stringify(["C1", "C2", "C3"]); + it("index label shows n / total when multiple entries", () => { + card.dataset.mechanisms = JSON.stringify([ + { category: "Mechanism", effect: "C1" }, + { category: "Mechanism", effect: "C2" }, + { category: "Mechanism", effect: "C3" }, + ]); openCaution(); expect(testDiv.querySelector(".sig-caution-index").textContent).toBe("1 / 3"); }); - it("index label is empty when only 1 caution", () => { - card.dataset.cautions = JSON.stringify(["Only one."]); + it("index label is empty when only 1 entry", () => { + card.dataset.mechanisms = JSON.stringify([{ category: "Mechanism", effect: "Only one." }]); openCaution(); expect(testDiv.querySelector(".sig-caution-index").textContent).toBe(""); }); @@ -314,8 +340,11 @@ describe("SigSelect", () => { expect(testDiv.querySelector(".sig-stage").classList.contains("sig-caution-open")).toBe(false); }); - it("opening again resets to first caution", () => { - card.dataset.cautions = JSON.stringify(["First", "Second"]); + it("opening again resets to first entry", () => { + card.dataset.mechanisms = JSON.stringify([ + { category: "Mechanism", effect: "First" }, + { category: "Mechanism", effect: "Second" }, + ]); openCaution(); cautionNext.dispatchEvent(new MouseEvent("click", { bubbles: true })); // Close and reopen @@ -757,4 +786,87 @@ describe("SigSelect", () => { expect(takeSigBtn.classList.contains("btn-cancel")).toBe(false); }); }); + + // ── FYI tooltip — mechanisms + articulations data source ──────────────── // + // + // Sprint 2: the caution tooltip is reworked to draw from data-mechanisms and + // data-articulations instead of data-cautions. Entries are {category, effect} + // dicts; the category label replaces the old "Caution!" title; the caution-type + // reads "Ally Interaction". Shoptalk is absent. + + describe("FYI from mechanisms + articulations", () => { + var cautionEffect, cautionTitle, cautionType, cautionPrev, cautionNext, cautionBtn; + + beforeEach(() => { + makeFixture(); + cautionEffect = testDiv.querySelector(".sig-caution-effect"); + cautionTitle = testDiv.querySelector(".sig-caution-title"); + cautionType = testDiv.querySelector(".sig-caution-type"); + cautionPrev = testDiv.querySelector(".sig-caution-prev"); + cautionNext = testDiv.querySelector(".sig-caution-next"); + cautionBtn = testDiv.querySelector(".sig-caution-btn"); + }); + + function hover() { + card.dispatchEvent(new MouseEvent("mouseenter", { bubbles: true })); + } + function openFYI() { + hover(); + cautionBtn.dispatchEvent(new MouseEvent("click", { bubbles: true })); + } + + it("caution-type label reads 'Ally Interaction'", () => { + openFYI(); + expect(cautionType.textContent).toBe("Ally Interaction"); + }); + + it("shows 'No ally interactions defined.' when both lists are empty", () => { + card.dataset.mechanisms = "[]"; + card.dataset.articulations = "[]"; + openFYI(); + expect(cautionEffect.textContent).toContain("No ally interactions defined"); + }); + + it("renders first mechanism effect and sets title to its category", () => { + card.dataset.mechanisms = JSON.stringify([ + { category: "Mechanism", effect: "The card amplifies adjacent power." } + ]); + openFYI(); + expect(cautionTitle.textContent).toBe("Mechanism"); + expect(cautionEffect.textContent).toContain("amplifies adjacent power"); + }); + + it("mechanisms come before articulations in the combined list", () => { + card.dataset.mechanisms = JSON.stringify([{ category: "Mechanism", effect: "First" }]); + card.dataset.articulations = JSON.stringify([{ category: "Articulation", effect: "Second" }]); + openFYI(); + expect(cautionEffect.textContent).toContain("First"); + cautionNext.dispatchEvent(new MouseEvent("click", { bubbles: true })); + expect(cautionEffect.textContent).toContain("Second"); + }); + + it("articulation title is set from its category field", () => { + card.dataset.mechanisms = JSON.stringify([{ category: "Mechanism", effect: "M1" }]); + card.dataset.articulations = JSON.stringify([{ category: "Articulation", effect: "A1" }]); + openFYI(); + cautionNext.dispatchEvent(new MouseEvent("click", { bubbles: true })); + expect(cautionTitle.textContent).toBe("Articulation"); + }); + + it("effect HTML is injected (supports .card-ref spans)", () => { + card.dataset.mechanisms = JSON.stringify([ + { category: "Mechanism", effect: 'Draw The Occultist.' } + ]); + openFYI(); + expect(cautionEffect.querySelector(".card-ref")).not.toBeNull(); + expect(cautionEffect.querySelector(".card-ref").textContent).toBe("The Occultist"); + }); + + it("shoptalk element is absent or empty", () => { + openFYI(); + var shoptalk = testDiv.querySelector(".sig-caution-shoptalk"); + // Either removed from DOM or has no visible content + expect(!shoptalk || shoptalk.textContent.trim() === "").toBe(true); + }); + }); }); diff --git a/src/templates/apps/gameboard/_partials/_sig_select_overlay.html b/src/templates/apps/gameboard/_partials/_sig_select_overlay.html index e20e40b..a632548 100644 --- a/src/templates/apps/gameboard/_partials/_sig_select_overlay.html +++ b/src/templates/apps/gameboard/_partials/_sig_select_overlay.html @@ -29,6 +29,8 @@ Context: sig_cards, user_polarity, user_seat, sig_reserve_url, sig_reservations_

{# not shown in sig-select — game-kit only #} +

+

@@ -39,19 +41,18 @@ Context: sig_cards, user_polarity, user_seat, sig_reserve_url, sig_reservations_
-

Upright

+

Emanation

-

Reversed

+

Reversal

-

Caution!

-

Rival Interaction

+

+

Ally Interaction

-

[Shoptalk forthcoming]

@@ -72,9 +73,11 @@ Context: sig_cards, user_polarity, user_seat, sig_reserve_url, sig_reservations_ data-correspondence="{{ card.correspondence|default:'' }}" data-keywords-upright="{{ card.keywords_upright|join:',' }}" data-keywords-reversed="{{ card.keywords_reversed|join:',' }}" - data-cautions="{{ card.cautions_json }}" + data-mechanisms="{{ card.mechanisms_json }}" + data-articulations="{{ card.articulations_json }}" data-levity-qualifier="{{ card.levity_qualifier }}" - data-gravity-qualifier="{{ card.gravity_qualifier }}"> + data-gravity-qualifier="{{ card.gravity_qualifier }}" + data-reversal="{{ card.reversal }}">
{{ card.corner_rank }} {% if card.suit_icon %}{% endif %}