p-elements-core 1.2.30 → 1.2.32-rc-10
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.
- package/.editorconfig +17 -17
- package/.gitlab-ci.yml +18 -18
- package/CHANGELOG.md +201 -0
- package/demo/sample.js +1 -1
- package/demo/screen.css +16 -16
- package/demo/theme.css +1 -0
- package/dist/p-elements-core-modern.js +1 -1
- package/dist/p-elements-core.js +1 -1
- package/docs/package-lock.json +6897 -6897
- package/docs/package.json +27 -27
- package/docs/src/404.md +8 -8
- package/docs/src/_data/demos/hello-world/hello-world.tsx +35 -35
- package/docs/src/_data/demos/hello-world/index.html +10 -10
- package/docs/src/_data/demos/hello-world/project.json +7 -7
- package/docs/src/_data/demos/timer/demo-timer.tsx +120 -120
- package/docs/src/_data/demos/timer/icons.tsx +62 -62
- package/docs/src/_data/demos/timer/index.html +12 -12
- package/docs/src/_data/demos/timer/project.json +8 -8
- package/docs/src/_data/global.js +13 -13
- package/docs/src/_data/helpers.js +19 -19
- package/docs/src/_includes/layouts/base.njk +30 -30
- package/docs/src/_includes/layouts/playground.njk +40 -40
- package/docs/src/_includes/partials/app-header.njk +8 -8
- package/docs/src/_includes/partials/head.njk +14 -14
- package/docs/src/_includes/partials/nav.njk +19 -19
- package/docs/src/_includes/partials/top-nav.njk +51 -51
- package/docs/src/documentation/custom-element.md +221 -221
- package/docs/src/documentation/decorators/bind.md +71 -71
- package/docs/src/documentation/decorators/custom-element-config.md +63 -63
- package/docs/src/documentation/decorators/property.md +83 -83
- package/docs/src/documentation/decorators/query.md +66 -66
- package/docs/src/documentation/decorators/render-property-on-set.md +60 -60
- package/docs/src/documentation/decorators.md +9 -9
- package/docs/src/documentation/reactive-properties.md +53 -53
- package/docs/src/index.d.ts +25 -25
- package/docs/src/index.md +3 -3
- package/docs/src/scripts/components/app-mode-switch/app-mode-switch.css +78 -78
- package/docs/src/scripts/components/app-mode-switch/app-mode-switch.tsx +166 -166
- package/docs/src/scripts/components/app-playground/app-playground.tsx +189 -189
- package/docs/tsconfig.json +22 -22
- package/index.html +15 -2
- package/p-elements-core.d.ts +12 -3
- package/package.json +11 -4
- package/readme.md +206 -206
- package/src/custom-element-controller.test.ts +226 -0
- package/src/custom-element-controller.ts +31 -31
- package/src/custom-element.test.ts +906 -0
- package/src/custom-element.ts +471 -188
- package/src/custom-style-element.ts +4 -1
- package/src/decorators/bind.test.ts +163 -0
- package/src/decorators/bind.ts +46 -46
- package/src/decorators/custom-element-config.ts +17 -17
- package/src/decorators/property.test.ts +279 -0
- package/src/decorators/property.ts +822 -150
- package/src/decorators/query.test.ts +146 -0
- package/src/decorators/query.ts +12 -12
- package/src/decorators/render-property-on-set.ts +3 -3
- package/src/helpers/css.test.ts +150 -0
- package/src/helpers/css.ts +71 -71
- package/src/maquette/cache.test.ts +150 -0
- package/src/maquette/cache.ts +35 -35
- package/src/maquette/dom.test.ts +263 -0
- package/src/maquette/dom.ts +115 -115
- package/src/maquette/h.test.ts +165 -0
- package/src/maquette/h.ts +100 -100
- package/src/maquette/index.ts +12 -12
- package/src/maquette/interfaces.ts +536 -536
- package/src/maquette/jsx.ts +61 -61
- package/src/maquette/mapping.test.ts +294 -0
- package/src/maquette/mapping.ts +56 -56
- package/src/maquette/maquette.test.ts +493 -0
- package/src/maquette/projection.test.ts +366 -0
- package/src/maquette/projection.ts +666 -666
- package/src/maquette/projector.test.ts +351 -0
- package/src/maquette/projector.ts +200 -200
- package/src/sample/mixin/highlight.tsx +33 -32
- package/src/sample/sample.tsx +167 -7
- package/src/test-setup.ts +85 -0
- package/src/test-utils.ts +223 -0
- package/tsconfig.json +1 -0
- package/vitest.config.ts +41 -0
- package/webpack.config.js +1 -1
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for Maquette integration with CustomElement
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, it, expect } from 'vitest';
|
|
6
|
+
import '../test-setup.js';
|
|
7
|
+
import { CustomElement } from '../custom-element.js';
|
|
8
|
+
import { customElementConfig } from '../decorators/custom-element-config.js';
|
|
9
|
+
import { property } from '../decorators/property.js';
|
|
10
|
+
import { h } from './h.js';
|
|
11
|
+
import { generateUniqueTagName } from '../test-setup.js';
|
|
12
|
+
import { waitForRender } from '../test-utils.js';
|
|
13
|
+
|
|
14
|
+
describe('Maquette rendering', () => {
|
|
15
|
+
describe('h() function', () => {
|
|
16
|
+
it('should render simple vnodes', async () => {
|
|
17
|
+
const tagName = generateUniqueTagName('maquette-test');
|
|
18
|
+
|
|
19
|
+
@customElementConfig({ tagName })
|
|
20
|
+
class MaquetteTest extends CustomElement {
|
|
21
|
+
static style = ':host { display: block; }';
|
|
22
|
+
|
|
23
|
+
render() {
|
|
24
|
+
return h('div', ['Hello World']);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const el = document.createElement(tagName) as MaquetteTest;
|
|
29
|
+
document.body.appendChild(el);
|
|
30
|
+
await waitForRender(el);
|
|
31
|
+
|
|
32
|
+
const div = el.shadowRoot.querySelector('div');
|
|
33
|
+
expect(div).toBeDefined();
|
|
34
|
+
expect(div.textContent).toBe('Hello World');
|
|
35
|
+
|
|
36
|
+
document.body.removeChild(el);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should render nested vnodes', async () => {
|
|
40
|
+
const tagName = generateUniqueTagName('maquette-test');
|
|
41
|
+
|
|
42
|
+
@customElementConfig({ tagName })
|
|
43
|
+
class MaquetteTest extends CustomElement {
|
|
44
|
+
static style = ':host { display: block; }';
|
|
45
|
+
|
|
46
|
+
render() {
|
|
47
|
+
return h('div', [
|
|
48
|
+
h('span', { class: 'child' }, ['Child 1']),
|
|
49
|
+
h('span', { class: 'child' }, ['Child 2'])
|
|
50
|
+
]);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const el = document.createElement(tagName) as MaquetteTest;
|
|
55
|
+
document.body.appendChild(el);
|
|
56
|
+
await waitForRender(el);
|
|
57
|
+
|
|
58
|
+
const spans = el.shadowRoot.querySelectorAll('span');
|
|
59
|
+
expect(spans.length).toBe(2);
|
|
60
|
+
expect(spans[0].textContent).toBe('Child 1');
|
|
61
|
+
expect(spans[1].textContent).toBe('Child 2');
|
|
62
|
+
|
|
63
|
+
document.body.removeChild(el);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should render with properties', async () => {
|
|
67
|
+
const tagName = generateUniqueTagName('maquette-test');
|
|
68
|
+
|
|
69
|
+
@customElementConfig({ tagName })
|
|
70
|
+
class MaquetteTest extends CustomElement {
|
|
71
|
+
static style = ':host { display: block; }';
|
|
72
|
+
|
|
73
|
+
render() {
|
|
74
|
+
return h('button', {
|
|
75
|
+
class: 'btn',
|
|
76
|
+
disabled: true,
|
|
77
|
+
'data-test': 'value'
|
|
78
|
+
}, ['Click me']);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const el = document.createElement(tagName) as MaquetteTest;
|
|
83
|
+
document.body.appendChild(el);
|
|
84
|
+
await waitForRender(el);
|
|
85
|
+
|
|
86
|
+
const button = el.shadowRoot.querySelector('button');
|
|
87
|
+
expect(button).toBeDefined();
|
|
88
|
+
expect(button.className).toBe('btn');
|
|
89
|
+
expect(button.disabled).toBe(true);
|
|
90
|
+
expect(button.getAttribute('data-test')).toBe('value');
|
|
91
|
+
|
|
92
|
+
document.body.removeChild(el);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('should handle dynamic content updates', async () => {
|
|
96
|
+
const tagName = generateUniqueTagName('maquette-test');
|
|
97
|
+
|
|
98
|
+
@customElementConfig({ tagName })
|
|
99
|
+
class MaquetteTest extends CustomElement {
|
|
100
|
+
static style = ':host { display: block; }';
|
|
101
|
+
|
|
102
|
+
@property({ type: String })
|
|
103
|
+
message = 'Initial';
|
|
104
|
+
|
|
105
|
+
render() {
|
|
106
|
+
return h('p', [this.message]);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const el = document.createElement(tagName) as MaquetteTest;
|
|
111
|
+
document.body.appendChild(el);
|
|
112
|
+
await waitForRender(el);
|
|
113
|
+
|
|
114
|
+
let p = el.shadowRoot.querySelector('p');
|
|
115
|
+
expect(p.textContent).toBe('Initial');
|
|
116
|
+
|
|
117
|
+
el.message = 'Updated';
|
|
118
|
+
await waitForRender(el);
|
|
119
|
+
|
|
120
|
+
p = el.shadowRoot.querySelector('p');
|
|
121
|
+
expect(p.textContent).toBe('Updated');
|
|
122
|
+
|
|
123
|
+
document.body.removeChild(el);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('should render lists of items', async () => {
|
|
127
|
+
const tagName = generateUniqueTagName('maquette-test');
|
|
128
|
+
|
|
129
|
+
@customElementConfig({ tagName })
|
|
130
|
+
class MaquetteTest extends CustomElement {
|
|
131
|
+
static style = ':host { display: block; }';
|
|
132
|
+
|
|
133
|
+
@property()
|
|
134
|
+
items = ['a', 'b', 'c'];
|
|
135
|
+
|
|
136
|
+
render() {
|
|
137
|
+
return h('ul', this.items.map(item =>
|
|
138
|
+
h('li', { key: item }, [item])
|
|
139
|
+
));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const el = document.createElement(tagName) as MaquetteTest;
|
|
144
|
+
document.body.appendChild(el);
|
|
145
|
+
await waitForRender(el);
|
|
146
|
+
|
|
147
|
+
const lis = el.shadowRoot.querySelectorAll('li');
|
|
148
|
+
expect(lis.length).toBe(3);
|
|
149
|
+
expect(lis[0].textContent).toBe('a');
|
|
150
|
+
expect(lis[1].textContent).toBe('b');
|
|
151
|
+
expect(lis[2].textContent).toBe('c');
|
|
152
|
+
|
|
153
|
+
document.body.removeChild(el);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('should handle conditional rendering', async () => {
|
|
157
|
+
const tagName = generateUniqueTagName('maquette-test');
|
|
158
|
+
|
|
159
|
+
@customElementConfig({ tagName })
|
|
160
|
+
class MaquetteTest extends CustomElement {
|
|
161
|
+
static style = ':host { display: block; }';
|
|
162
|
+
|
|
163
|
+
@property({ type: Boolean })
|
|
164
|
+
showContent = false;
|
|
165
|
+
|
|
166
|
+
render() {
|
|
167
|
+
return h('div', [
|
|
168
|
+
this.showContent ? h('p', ['Visible']) : null
|
|
169
|
+
]);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const el = document.createElement(tagName) as MaquetteTest;
|
|
174
|
+
document.body.appendChild(el);
|
|
175
|
+
await waitForRender(el);
|
|
176
|
+
|
|
177
|
+
let p = el.shadowRoot.querySelector('p');
|
|
178
|
+
expect(p).toBeNull();
|
|
179
|
+
|
|
180
|
+
el.showContent = true;
|
|
181
|
+
await waitForRender(el);
|
|
182
|
+
|
|
183
|
+
p = el.shadowRoot.querySelector('p');
|
|
184
|
+
expect(p).toBeDefined();
|
|
185
|
+
expect(p.textContent).toBe('Visible');
|
|
186
|
+
|
|
187
|
+
document.body.removeChild(el);
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
describe('Event handlers', () => {
|
|
192
|
+
it('should attach event handlers', async () => {
|
|
193
|
+
const tagName = generateUniqueTagName('event-test');
|
|
194
|
+
let clicked = false;
|
|
195
|
+
|
|
196
|
+
@customElementConfig({ tagName })
|
|
197
|
+
class EventTest extends CustomElement {
|
|
198
|
+
static style = ':host { display: block; }';
|
|
199
|
+
|
|
200
|
+
handleClick() {
|
|
201
|
+
clicked = true;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
render() {
|
|
205
|
+
return h('button', { onclick: () => this.handleClick() }, ['Click']);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const el = document.createElement(tagName) as EventTest;
|
|
210
|
+
document.body.appendChild(el);
|
|
211
|
+
await waitForRender(el);
|
|
212
|
+
|
|
213
|
+
const button = el.shadowRoot.querySelector('button');
|
|
214
|
+
button.click();
|
|
215
|
+
|
|
216
|
+
expect(clicked).toBe(true);
|
|
217
|
+
|
|
218
|
+
document.body.removeChild(el);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it('should update event handlers', async () => {
|
|
222
|
+
const tagName = generateUniqueTagName('event-test');
|
|
223
|
+
let counter = 0;
|
|
224
|
+
|
|
225
|
+
@customElementConfig({ tagName })
|
|
226
|
+
class EventTest extends CustomElement {
|
|
227
|
+
static style = ':host { display: block; }';
|
|
228
|
+
|
|
229
|
+
@property({ type: Number })
|
|
230
|
+
multiplier = 1;
|
|
231
|
+
|
|
232
|
+
handleClick() {
|
|
233
|
+
counter += this.multiplier;
|
|
234
|
+
this.renderNow();
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
render() {
|
|
238
|
+
return h('button', { onclick: () => this.handleClick() }, [`Count: ${counter}`]);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const el = document.createElement(tagName) as EventTest;
|
|
243
|
+
document.body.appendChild(el);
|
|
244
|
+
await waitForRender(el);
|
|
245
|
+
|
|
246
|
+
const button = el.shadowRoot.querySelector('button');
|
|
247
|
+
|
|
248
|
+
button.click();
|
|
249
|
+
await waitForRender(el);
|
|
250
|
+
expect(counter).toBe(1);
|
|
251
|
+
|
|
252
|
+
el.multiplier = 5;
|
|
253
|
+
await waitForRender(el);
|
|
254
|
+
button.click();
|
|
255
|
+
await waitForRender(el);
|
|
256
|
+
expect(counter).toBe(6); // 1 + 5
|
|
257
|
+
|
|
258
|
+
document.body.removeChild(el);
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
describe('Advanced rendering patterns', () => {
|
|
263
|
+
it('should handle conditional rendering', async () => {
|
|
264
|
+
const tagName = generateUniqueTagName('maquette-test');
|
|
265
|
+
|
|
266
|
+
@customElementConfig({ tagName })
|
|
267
|
+
class MaquetteTest extends CustomElement {
|
|
268
|
+
static style = ':host { display: block; }';
|
|
269
|
+
|
|
270
|
+
@property({ type: Boolean })
|
|
271
|
+
showMessage = false;
|
|
272
|
+
|
|
273
|
+
render() {
|
|
274
|
+
return h('div', [
|
|
275
|
+
this.showMessage ? h('span.message', ['Visible']) : null
|
|
276
|
+
].filter(Boolean) as any);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const el = document.createElement(tagName) as MaquetteTest;
|
|
281
|
+
document.body.appendChild(el);
|
|
282
|
+
await waitForRender(el);
|
|
283
|
+
|
|
284
|
+
expect(el.shadowRoot.querySelector('.message')).toBeNull();
|
|
285
|
+
|
|
286
|
+
el.showMessage = true;
|
|
287
|
+
await waitForRender(el);
|
|
288
|
+
|
|
289
|
+
expect(el.shadowRoot.querySelector('.message')).toBeDefined();
|
|
290
|
+
expect(el.shadowRoot.querySelector('.message')?.textContent).toBe('Visible');
|
|
291
|
+
|
|
292
|
+
document.body.removeChild(el);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it('should handle list rendering with keys', async () => {
|
|
296
|
+
const tagName = generateUniqueTagName('maquette-test');
|
|
297
|
+
|
|
298
|
+
@customElementConfig({ tagName })
|
|
299
|
+
class MaquetteTest extends CustomElement {
|
|
300
|
+
static style = ':host { display: block; }';
|
|
301
|
+
|
|
302
|
+
@property()
|
|
303
|
+
items: string[] = ['a', 'b', 'c'];
|
|
304
|
+
|
|
305
|
+
render() {
|
|
306
|
+
return h('ul', this.items.map(item =>
|
|
307
|
+
h('li', { key: item }, [item])
|
|
308
|
+
));
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const el = document.createElement(tagName) as MaquetteTest;
|
|
313
|
+
document.body.appendChild(el);
|
|
314
|
+
await waitForRender(el);
|
|
315
|
+
|
|
316
|
+
expect(el.shadowRoot.querySelectorAll('li').length).toBe(3);
|
|
317
|
+
|
|
318
|
+
el.items = ['b', 'c', 'd'];
|
|
319
|
+
await waitForRender(el);
|
|
320
|
+
|
|
321
|
+
expect(el.shadowRoot.querySelectorAll('li').length).toBe(3);
|
|
322
|
+
expect(el.shadowRoot.querySelectorAll('li')[0].textContent).toBe('b');
|
|
323
|
+
|
|
324
|
+
document.body.removeChild(el);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it('should handle nested component structures', async () => {
|
|
328
|
+
const tagName = generateUniqueTagName('maquette-test');
|
|
329
|
+
|
|
330
|
+
@customElementConfig({ tagName })
|
|
331
|
+
class MaquetteTest extends CustomElement {
|
|
332
|
+
static style = ':host { display: block; }';
|
|
333
|
+
|
|
334
|
+
render() {
|
|
335
|
+
return h('div.container', [
|
|
336
|
+
h('header', [
|
|
337
|
+
h('h1', ['Title']),
|
|
338
|
+
h('nav', [
|
|
339
|
+
h('a', { href: '#' }, ['Link 1']),
|
|
340
|
+
h('a', { href: '#' }, ['Link 2']),
|
|
341
|
+
])
|
|
342
|
+
]),
|
|
343
|
+
h('main', [
|
|
344
|
+
h('article', [
|
|
345
|
+
h('p', ['Content'])
|
|
346
|
+
])
|
|
347
|
+
]),
|
|
348
|
+
h('footer', ['Footer'])
|
|
349
|
+
]);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const el = document.createElement(tagName) as MaquetteTest;
|
|
354
|
+
document.body.appendChild(el);
|
|
355
|
+
await waitForRender(el);
|
|
356
|
+
|
|
357
|
+
expect(el.shadowRoot.querySelector('h1')?.textContent).toBe('Title');
|
|
358
|
+
expect(el.shadowRoot.querySelectorAll('nav a').length).toBe(2);
|
|
359
|
+
expect(el.shadowRoot.querySelector('article p')?.textContent).toBe('Content');
|
|
360
|
+
|
|
361
|
+
document.body.removeChild(el);
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
it('should handle dynamic styles', async () => {
|
|
365
|
+
const tagName = generateUniqueTagName('maquette-test');
|
|
366
|
+
|
|
367
|
+
@customElementConfig({ tagName })
|
|
368
|
+
class MaquetteTest extends CustomElement {
|
|
369
|
+
static style = ':host { display: block; }';
|
|
370
|
+
|
|
371
|
+
@property({ type: String })
|
|
372
|
+
color = 'red';
|
|
373
|
+
|
|
374
|
+
render() {
|
|
375
|
+
return h('div', {
|
|
376
|
+
styles: {
|
|
377
|
+
color: this.color,
|
|
378
|
+
fontSize: '16px'
|
|
379
|
+
}
|
|
380
|
+
}, ['Styled text']);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const el = document.createElement(tagName) as MaquetteTest;
|
|
385
|
+
document.body.appendChild(el);
|
|
386
|
+
await waitForRender(el);
|
|
387
|
+
|
|
388
|
+
const div = el.shadowRoot.querySelector('div') as HTMLElement;
|
|
389
|
+
expect(div.style.color).toBe('red');
|
|
390
|
+
|
|
391
|
+
el.color = 'blue';
|
|
392
|
+
await waitForRender(el);
|
|
393
|
+
|
|
394
|
+
expect(div.style.color).toBe('blue');
|
|
395
|
+
|
|
396
|
+
document.body.removeChild(el);
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
it('should handle classes object', async () => {
|
|
400
|
+
const tagName = generateUniqueTagName('maquette-test');
|
|
401
|
+
|
|
402
|
+
@customElementConfig({ tagName })
|
|
403
|
+
class MaquetteTest extends CustomElement {
|
|
404
|
+
static style = ':host { display: block; }';
|
|
405
|
+
|
|
406
|
+
@property({ type: Boolean })
|
|
407
|
+
active = false;
|
|
408
|
+
|
|
409
|
+
render() {
|
|
410
|
+
return h('div', {
|
|
411
|
+
classes: {
|
|
412
|
+
'item': true,
|
|
413
|
+
'active': this.active,
|
|
414
|
+
'disabled': false
|
|
415
|
+
}
|
|
416
|
+
}, ['Item']);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const el = document.createElement(tagName) as MaquetteTest;
|
|
421
|
+
document.body.appendChild(el);
|
|
422
|
+
await waitForRender(el);
|
|
423
|
+
|
|
424
|
+
const div = el.shadowRoot.querySelector('div') as HTMLElement;
|
|
425
|
+
expect(div.classList.contains('item')).toBe(true);
|
|
426
|
+
expect(div.classList.contains('active')).toBe(false);
|
|
427
|
+
expect(div.classList.contains('disabled')).toBe(false);
|
|
428
|
+
|
|
429
|
+
el.active = true;
|
|
430
|
+
await waitForRender(el);
|
|
431
|
+
|
|
432
|
+
expect(div.classList.contains('active')).toBe(true);
|
|
433
|
+
|
|
434
|
+
document.body.removeChild(el);
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
it('should handle afterCreate callback', async () => {
|
|
438
|
+
const tagName = generateUniqueTagName('maquette-test');
|
|
439
|
+
let afterCreateCalled = false;
|
|
440
|
+
|
|
441
|
+
@customElementConfig({ tagName })
|
|
442
|
+
class MaquetteTest extends CustomElement {
|
|
443
|
+
static style = ':host { display: block; }';
|
|
444
|
+
|
|
445
|
+
render() {
|
|
446
|
+
return h('div', {
|
|
447
|
+
afterCreate: (element: HTMLElement) => {
|
|
448
|
+
afterCreateCalled = true;
|
|
449
|
+
element.setAttribute('data-created', 'true');
|
|
450
|
+
}
|
|
451
|
+
}, ['Content']);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
const el = document.createElement(tagName) as MaquetteTest;
|
|
456
|
+
document.body.appendChild(el);
|
|
457
|
+
await waitForRender(el);
|
|
458
|
+
|
|
459
|
+
expect(afterCreateCalled).toBe(true);
|
|
460
|
+
expect(el.shadowRoot.querySelector('div')?.getAttribute('data-created')).toBe('true');
|
|
461
|
+
|
|
462
|
+
document.body.removeChild(el);
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
it('should handle data attributes', async () => {
|
|
466
|
+
const tagName = generateUniqueTagName('maquette-test');
|
|
467
|
+
|
|
468
|
+
@customElementConfig({ tagName })
|
|
469
|
+
class MaquetteTest extends CustomElement {
|
|
470
|
+
static style = ':host { display: block; }';
|
|
471
|
+
|
|
472
|
+
render() {
|
|
473
|
+
return h('div', {
|
|
474
|
+
'data-test': 'value',
|
|
475
|
+
'data-id': '123',
|
|
476
|
+
'aria-label': 'Test element'
|
|
477
|
+
}, ['Content']);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
const el = document.createElement(tagName) as MaquetteTest;
|
|
482
|
+
document.body.appendChild(el);
|
|
483
|
+
await waitForRender(el);
|
|
484
|
+
|
|
485
|
+
const div = el.shadowRoot.querySelector('div') as HTMLElement;
|
|
486
|
+
expect(div.getAttribute('data-test')).toBe('value');
|
|
487
|
+
expect(div.getAttribute('data-id')).toBe('123');
|
|
488
|
+
expect(div.getAttribute('aria-label')).toBe('Test element');
|
|
489
|
+
|
|
490
|
+
document.body.removeChild(el);
|
|
491
|
+
});
|
|
492
|
+
});
|
|
493
|
+
});
|