@schukai/monster 4.136.29 → 4.137.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,192 @@
1
+ import * as chai from "chai";
2
+ import { chaiDom } from "../../../util/chai-dom.mjs";
3
+ import { initJSDOM } from "../../../util/jsdom.mjs";
4
+
5
+ let expect = chai.expect;
6
+ chai.use(chaiDom);
7
+
8
+ let ChoiceCards;
9
+
10
+ function waitForCondition(check, { timeout = 4000, interval = 25 } = {}) {
11
+ return new Promise((resolve, reject) => {
12
+ const start = Date.now();
13
+
14
+ const poll = () => {
15
+ try {
16
+ if (check()) {
17
+ resolve();
18
+ return;
19
+ }
20
+ } catch (e) {
21
+ reject(e);
22
+ return;
23
+ }
24
+
25
+ if (Date.now() - start >= timeout) {
26
+ reject(new Error("Timed out while waiting for test condition."));
27
+ return;
28
+ }
29
+
30
+ setTimeout(poll, interval);
31
+ };
32
+
33
+ poll();
34
+ });
35
+ }
36
+
37
+ describe("ChoiceCards", function () {
38
+ before(function (done) {
39
+ initJSDOM()
40
+ .then(() => {
41
+ return import("element-internals-polyfill");
42
+ })
43
+ .then(() => {
44
+ return import("../../../../source/components/form/form.mjs");
45
+ })
46
+ .then(() => {
47
+ return import("../../../../source/components/form/choice-cards.mjs");
48
+ })
49
+ .then((m) => {
50
+ ChoiceCards = m["ChoiceCards"];
51
+ done();
52
+ })
53
+ .catch((e) => done(e));
54
+ });
55
+
56
+ beforeEach(() => {
57
+ document.getElementById("mocks").innerHTML = '<div id="test"></div>';
58
+ });
59
+
60
+ afterEach(() => {
61
+ document.getElementById("mocks").innerHTML = "";
62
+ });
63
+
64
+ it("creates a custom element instance", function () {
65
+ expect(document.createElement("monster-choice-cards")).is.instanceof(
66
+ ChoiceCards,
67
+ );
68
+ });
69
+
70
+ it("renders choice cards from items", function () {
71
+ const cards = document.createElement("monster-choice-cards");
72
+ cards.setItems([
73
+ { value: "assets", label: "Project assets", icon: "project-assets" },
74
+ { value: "api", label: "API collection", icon: "api-collection" },
75
+ ]);
76
+
77
+ document.getElementById("test").appendChild(cards);
78
+
79
+ const choices = cards.shadowRoot.querySelectorAll(
80
+ '[data-monster-role="choice"]',
81
+ );
82
+ expect(choices.length).is.equal(2);
83
+ expect(choices[0].textContent).contains("Project assets");
84
+ expect(choices[1].textContent).contains("API collection");
85
+ });
86
+
87
+ it("renders custom card content from slots", function () {
88
+ const cards = document.createElement("monster-choice-cards");
89
+ cards.setItems([
90
+ { value: "assets", label: "Project assets", contentSlot: "assets-card" },
91
+ { value: "api", label: "API collection", contentSlot: "api-card" },
92
+ { value: "manual", label: "Manual", contentSlot: "manual-card" },
93
+ ]);
94
+
95
+ const assets = document.createElement("span");
96
+ assets.slot = "assets-card";
97
+ assets.textContent = "Custom assets content";
98
+ cards.appendChild(assets);
99
+
100
+ document.getElementById("test").appendChild(cards);
101
+
102
+ const choices = cards.shadowRoot.querySelectorAll(
103
+ '[data-monster-role="choice"]',
104
+ );
105
+ expect(choices.length).is.equal(3);
106
+ expect(
107
+ cards.shadowRoot
108
+ .querySelector('[data-choice-value="assets"] slot')
109
+ .getAttribute("name"),
110
+ ).is.equal("assets-card");
111
+ });
112
+
113
+ it("selects a card and emits change events", function (done) {
114
+ const cards = document.createElement("monster-choice-cards");
115
+ cards.setItems([
116
+ { value: "assets", label: "Project assets" },
117
+ { value: "api", label: "API collection" },
118
+ ]);
119
+
120
+ cards.addEventListener("monster-change", (event) => {
121
+ expect(event.detail.value).is.equal("api");
122
+ expect(cards.value).is.equal("api");
123
+ expect(
124
+ cards.shadowRoot
125
+ .querySelector('[data-choice-value="api"]')
126
+ .getAttribute("aria-checked"),
127
+ ).is.equal("true");
128
+ done();
129
+ });
130
+
131
+ document.getElementById("test").appendChild(cards);
132
+ cards.shadowRoot.querySelector('[data-choice-value="api"]').click();
133
+ });
134
+
135
+ it("reads from and writes back to a form datasource", async function () {
136
+ this.timeout(6000);
137
+
138
+ document.getElementById("test").innerHTML = `
139
+ <monster-datasource-dom id="choice-ds">
140
+ <script type="application/json">
141
+ [
142
+ {
143
+ "source": "assets"
144
+ }
145
+ ]
146
+ </script>
147
+ </monster-datasource-dom>
148
+ <monster-form
149
+ id="choice-form"
150
+ data-monster-option-datasource-selector="#choice-ds"
151
+ data-monster-option-mapping-data=""
152
+ data-monster-option-mapping-index="0"
153
+ >
154
+ <monster-choice-cards
155
+ id="choice-source"
156
+ data-monster-attributes="value path:data.source"
157
+ data-monster-bind="path:data.source"
158
+ data-monster-options='{
159
+ "items": [
160
+ { "value": "assets", "label": "Assets", "contentSlot": "assets-card" },
161
+ { "value": "api", "label": "API", "contentSlot": "api-card" }
162
+ ]
163
+ }'
164
+ >
165
+ <span slot="assets-card">Assets</span>
166
+ <span slot="api-card">API</span>
167
+ </monster-choice-cards>
168
+ </monster-form>
169
+ `;
170
+
171
+ const datasource = document.getElementById("choice-ds");
172
+ const cards = document.getElementById("choice-source");
173
+
174
+ await waitForCondition(() => cards.value === "assets");
175
+
176
+ cards.select("api");
177
+ await waitForCondition(() => datasource.data?.[0]?.source === "api");
178
+ });
179
+
180
+ it("does not select disabled items", function () {
181
+ const cards = document.createElement("monster-choice-cards");
182
+ cards.setItems([
183
+ { value: "assets", label: "Project assets" },
184
+ { value: "api", label: "API collection", disabled: true },
185
+ ]);
186
+
187
+ document.getElementById("test").appendChild(cards);
188
+ cards.select("api");
189
+
190
+ expect(cards.value).is.equal(null);
191
+ });
192
+ });
@@ -334,5 +334,68 @@ describe("form floating-ui boundary resolution", function () {
334
334
 
335
335
  expect(content.style.overflowX).to.equal("auto");
336
336
  expect(content.style.overflowY).to.equal("visible");
337
+ expect(content.style.height).to.equal("");
338
+ expect(content.style.maxHeight).to.equal("200px");
339
+ });
340
+
341
+ it("should preserve declared nested scroll height when horizontal overlay content fits", function () {
342
+ const mocks = document.getElementById("mocks");
343
+ const popper = document.createElement("div");
344
+ const content = document.createElement("div");
345
+ const options = document.createElement("div");
346
+
347
+ content.setAttribute("part", "content");
348
+ content.setAttribute("data-monster-overflow-mode", "horizontal");
349
+ options.style.overflowY = "auto";
350
+ options.style.height = "72px";
351
+ options.style.maxHeight = "72px";
352
+
353
+ Object.defineProperty(content, "scrollHeight", {
354
+ configurable: true,
355
+ value: 120,
356
+ });
357
+ Object.defineProperty(options, "scrollHeight", {
358
+ configurable: true,
359
+ value: 72,
360
+ });
361
+
362
+ content.appendChild(options);
363
+ popper.appendChild(content);
364
+ mocks.appendChild(popper);
365
+
366
+ applyAdaptiveFloatingElementSize(popper, {
367
+ availableWidth: 240,
368
+ availableHeight: 200,
369
+ });
370
+
371
+ expect(options.style.height).to.equal("72px");
372
+ expect(options.style.maxHeight).to.equal("72px");
373
+ });
374
+
375
+ it("should constrain horizontal overlay-aware content height only when it exceeds available height", function () {
376
+ const mocks = document.getElementById("mocks");
377
+ const popper = document.createElement("div");
378
+ const content = document.createElement("div");
379
+
380
+ content.setAttribute("part", "content");
381
+ content.setAttribute("data-monster-overflow-mode", "horizontal");
382
+
383
+ Object.defineProperty(content, "scrollHeight", {
384
+ configurable: true,
385
+ value: 320,
386
+ });
387
+
388
+ popper.appendChild(content);
389
+ mocks.appendChild(popper);
390
+
391
+ applyAdaptiveFloatingElementSize(popper, {
392
+ availableWidth: 240,
393
+ availableHeight: 200,
394
+ });
395
+
396
+ expect(content.style.overflowX).to.equal("auto");
397
+ expect(content.style.overflowY).to.equal("auto");
398
+ expect(content.style.height).to.equal("200px");
399
+ expect(content.style.maxHeight).to.equal("200px");
337
400
  });
338
401
  });