ripple 0.2.151 → 0.2.153
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/README.md +3 -3
- package/package.json +5 -5
- package/src/compiler/phases/1-parse/index.js +1 -1
- package/src/compiler/phases/3-transform/client/index.js +37 -16
- package/src/compiler/phases/3-transform/server/index.js +43 -25
- package/src/runtime/internal/client/events.js +5 -1
- package/src/runtime/internal/client/index.js +2 -1
- package/src/runtime/internal/client/render.js +18 -15
- package/src/runtime/internal/client/runtime.js +78 -10
- package/src/runtime/internal/server/index.js +51 -11
- package/src/server/index.js +1 -1
- package/tests/client/array/array.derived.test.ripple +61 -33
- package/tests/client/array/array.iteration.test.ripple +3 -1
- package/tests/client/array/array.mutations.test.ripple +19 -15
- package/tests/client/array/array.static.test.ripple +115 -104
- package/tests/client/array/array.to-methods.test.ripple +3 -3
- package/tests/client/basic/basic.attributes.test.ripple +110 -57
- package/tests/client/basic/basic.collections.test.ripple +41 -22
- package/tests/client/basic/basic.errors.test.ripple +12 -6
- package/tests/client/basic/basic.events.test.ripple +51 -33
- package/tests/client/basic/basic.reactivity.test.ripple +120 -56
- package/tests/client/basic/basic.rendering.test.ripple +49 -19
- package/tests/client/basic/basic.styling.test.ripple +2 -2
- package/tests/client/basic/basic.utilities.test.ripple +1 -1
- package/tests/client/boundaries.test.ripple +70 -58
- package/tests/client/compiler/compiler.assignments.test.ripple +32 -4
- package/tests/client/compiler/compiler.attributes.test.ripple +46 -46
- package/tests/client/compiler/compiler.basic.test.ripple +18 -15
- package/tests/client/compiler/compiler.tracked-access.test.ripple +53 -42
- package/tests/client/compiler/compiler.typescript.test.ripple +1 -2
- package/tests/client/composite/composite.dynamic-components.test.ripple +6 -6
- package/tests/client/composite/composite.generics.test.ripple +39 -36
- package/tests/client/composite/composite.props.test.ripple +4 -3
- package/tests/client/composite/composite.reactivity.test.ripple +112 -27
- package/tests/client/composite/composite.render.test.ripple +9 -8
- package/tests/client/computed-properties.test.ripple +24 -24
- package/tests/client/context.test.ripple +11 -9
- package/tests/client/date.test.ripple +3 -1
- package/tests/client/dynamic-elements.test.ripple +103 -78
- package/tests/client/for.test.ripple +27 -17
- package/tests/client/head.test.ripple +42 -6
- package/tests/client/html.test.ripple +42 -32
- package/tests/client/input-value.test.ripple +4 -4
- package/tests/client/map.test.ripple +140 -141
- package/tests/client/media-query.test.ripple +31 -31
- package/tests/client/object.test.ripple +148 -112
- package/tests/client/portal.test.ripple +29 -15
- package/tests/client/ref.test.ripple +9 -3
- package/tests/client/set.test.ripple +111 -111
- package/tests/client/tracked-expression.test.ripple +16 -17
- package/tests/client/url/url.derived.test.ripple +19 -9
- package/tests/client/url/url.parsing.test.ripple +24 -8
- package/tests/client/url/url.partial-removal.test.ripple +12 -4
- package/tests/client/url/url.reactivity.test.ripple +63 -25
- package/tests/client/url/url.serialization.test.ripple +18 -6
- package/tests/client/url-search-params/url-search-params.derived.test.ripple +10 -6
- package/tests/client/url-search-params/url-search-params.iteration.test.ripple +3 -1
- package/tests/client/url-search-params/url-search-params.mutation.test.ripple +26 -14
- package/tests/client/url-search-params/url-search-params.tracked-url.test.ripple +3 -1
- package/tests/server/await.test.ripple +23 -22
- package/tests/server/basic.test.ripple +1 -1
- package/tests/server/compiler.test.ripple +3 -7
- package/tests/server/composite.test.ripple +38 -36
- package/tests/server/for.test.ripple +9 -5
- package/tests/server/if.test.ripple +1 -1
- package/tests/server/streaming-ssr.test.ripple +67 -0
- package/types/server.d.ts +5 -4
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { flushSync, track, createRefKey, trackSplit } from 'ripple';
|
|
2
2
|
|
|
3
3
|
describe('dynamic DOM elements', () => {
|
|
4
|
-
|
|
5
4
|
it('renders static dynamic element', () => {
|
|
6
5
|
component App() {
|
|
7
6
|
let tag = track('div');
|
|
@@ -19,23 +18,27 @@ describe('dynamic DOM elements', () => {
|
|
|
19
18
|
component App() {
|
|
20
19
|
let tag = track('div');
|
|
21
20
|
|
|
22
|
-
<button
|
|
21
|
+
<button
|
|
22
|
+
onClick={() => {
|
|
23
23
|
@tag = 'span';
|
|
24
|
-
}}
|
|
24
|
+
}}
|
|
25
|
+
>
|
|
26
|
+
{'Change Tag'}
|
|
27
|
+
</button>
|
|
25
28
|
<@tag id="dynamic">{'Hello World'}</@tag>
|
|
26
29
|
}
|
|
27
30
|
render(App);
|
|
28
|
-
|
|
31
|
+
|
|
29
32
|
// Initially should be a div
|
|
30
33
|
let dynamicElement = container.querySelector('#dynamic');
|
|
31
34
|
expect(dynamicElement.tagName).toBe('DIV');
|
|
32
35
|
expect(dynamicElement.textContent).toBe('Hello World');
|
|
33
|
-
|
|
36
|
+
|
|
34
37
|
// Click button to change tag
|
|
35
38
|
const button = container.querySelector('button');
|
|
36
39
|
button.click();
|
|
37
40
|
flushSync();
|
|
38
|
-
|
|
41
|
+
|
|
39
42
|
// Should now be a span
|
|
40
43
|
dynamicElement = container.querySelector('#dynamic');
|
|
41
44
|
expect(dynamicElement.tagName).toBe('SPAN');
|
|
@@ -97,9 +100,7 @@ describe('dynamic DOM elements', () => {
|
|
|
97
100
|
let tag = track('div');
|
|
98
101
|
let active = track(true);
|
|
99
102
|
|
|
100
|
-
<@tag class={{
|
|
101
|
-
{'Element with class object'}
|
|
102
|
-
</@tag>
|
|
103
|
+
<@tag class={{active: @active, 'dynamic-element': true}}>{'Element with class object'}</@tag>
|
|
103
104
|
}
|
|
104
105
|
render(App);
|
|
105
106
|
|
|
@@ -113,11 +114,13 @@ describe('dynamic DOM elements', () => {
|
|
|
113
114
|
component App() {
|
|
114
115
|
let tag = track('span');
|
|
115
116
|
|
|
116
|
-
<@tag
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
117
|
+
<@tag
|
|
118
|
+
style={{
|
|
119
|
+
color: 'red',
|
|
120
|
+
fontSize: '16px',
|
|
121
|
+
fontWeight: 'bold',
|
|
122
|
+
}}
|
|
123
|
+
>
|
|
121
124
|
{'Styled dynamic element'}
|
|
122
125
|
</@tag>
|
|
123
126
|
}
|
|
@@ -139,9 +142,7 @@ describe('dynamic DOM elements', () => {
|
|
|
139
142
|
class: 'spread-class',
|
|
140
143
|
};
|
|
141
144
|
|
|
142
|
-
<@tag {...attrs} data-extra="additional">
|
|
143
|
-
{'Element with spread attributes'}
|
|
144
|
-
</@tag>
|
|
145
|
+
<@tag {...attrs} data-extra="additional">{'Element with spread attributes'}</@tag>
|
|
145
146
|
}
|
|
146
147
|
render(App);
|
|
147
148
|
|
|
@@ -159,13 +160,18 @@ describe('dynamic DOM elements', () => {
|
|
|
159
160
|
component App() {
|
|
160
161
|
let tag = track('article');
|
|
161
162
|
|
|
162
|
-
<@tag
|
|
163
|
+
<@tag
|
|
164
|
+
{ref (node) => {
|
|
165
|
+
capturedElement = node;
|
|
166
|
+
}}
|
|
167
|
+
id="ref-test"
|
|
168
|
+
>
|
|
163
169
|
{'Element with ref'}
|
|
164
170
|
</@tag>
|
|
165
171
|
}
|
|
166
172
|
render(App);
|
|
167
173
|
flushSync();
|
|
168
|
-
|
|
174
|
+
|
|
169
175
|
expect(capturedElement).toBeTruthy();
|
|
170
176
|
expect(capturedElement.tagName).toBe('ARTICLE');
|
|
171
177
|
expect(capturedElement.id).toBe('ref-test');
|
|
@@ -185,7 +191,7 @@ describe('dynamic DOM elements', () => {
|
|
|
185
191
|
const dynamicProps = {
|
|
186
192
|
id: 'spread-ref-test',
|
|
187
193
|
class: 'ref-element',
|
|
188
|
-
[createRefKey()]: elementRef
|
|
194
|
+
[createRefKey()]: elementRef,
|
|
189
195
|
};
|
|
190
196
|
|
|
191
197
|
<@tag {...dynamicProps}>{'Element with spread ref'}</@tag>
|
|
@@ -206,42 +212,49 @@ describe('dynamic DOM elements', () => {
|
|
|
206
212
|
component App() {
|
|
207
213
|
let tag = track('div');
|
|
208
214
|
let count = track(0);
|
|
209
|
-
|
|
210
|
-
<button
|
|
211
|
-
|
|
215
|
+
|
|
216
|
+
<button
|
|
217
|
+
onClick={() => {
|
|
218
|
+
@count++;
|
|
219
|
+
}}
|
|
220
|
+
>
|
|
221
|
+
{'Increment'}
|
|
222
|
+
</button>
|
|
223
|
+
<@tag
|
|
212
224
|
id={@count % 2 ? 'even' : 'odd'}
|
|
213
225
|
class={@count % 2 ? 'even-class' : 'odd-class'}
|
|
214
226
|
data-count={@count}
|
|
215
227
|
>
|
|
216
|
-
{'Count: '}
|
|
228
|
+
{'Count: '}
|
|
229
|
+
{@count}
|
|
217
230
|
</@tag>
|
|
218
231
|
}
|
|
219
232
|
|
|
220
233
|
render(App);
|
|
221
|
-
|
|
234
|
+
|
|
222
235
|
const button = container.querySelector('button');
|
|
223
236
|
const element = container.querySelector('div');
|
|
224
|
-
|
|
237
|
+
|
|
225
238
|
// Initial state
|
|
226
239
|
expect(element.id).toBe('odd');
|
|
227
240
|
expect(element.className).toBe('odd-class');
|
|
228
241
|
expect(element.getAttribute('data-count')).toBe('0');
|
|
229
242
|
expect(element.textContent).toBe('Count: 0');
|
|
230
|
-
|
|
243
|
+
|
|
231
244
|
// Click to increment
|
|
232
245
|
button.click();
|
|
233
246
|
flushSync();
|
|
234
|
-
|
|
247
|
+
|
|
235
248
|
// Attributes should be reactive and update
|
|
236
249
|
expect(element.id).toBe('even');
|
|
237
250
|
expect(element.className).toBe('even-class');
|
|
238
251
|
expect(element.getAttribute('data-count')).toBe('1');
|
|
239
252
|
expect(element.textContent).toBe('Count: 1');
|
|
240
|
-
|
|
253
|
+
|
|
241
254
|
// Click again
|
|
242
255
|
button.click();
|
|
243
256
|
flushSync();
|
|
244
|
-
|
|
257
|
+
|
|
245
258
|
// Should toggle back
|
|
246
259
|
expect(element.id).toBe('odd');
|
|
247
260
|
expect(element.className).toBe('odd-class');
|
|
@@ -252,9 +265,9 @@ describe('dynamic DOM elements', () => {
|
|
|
252
265
|
it('applies scoped CSS to dynamic elements', () => {
|
|
253
266
|
component App() {
|
|
254
267
|
let tag = track('div');
|
|
255
|
-
|
|
268
|
+
|
|
256
269
|
<@tag class="test-class">{'Dynamic element'}</@tag>
|
|
257
|
-
|
|
270
|
+
|
|
258
271
|
<style>
|
|
259
272
|
.test-class {
|
|
260
273
|
color: red;
|
|
@@ -263,15 +276,15 @@ describe('dynamic DOM elements', () => {
|
|
|
263
276
|
}
|
|
264
277
|
|
|
265
278
|
render(App);
|
|
266
|
-
|
|
279
|
+
|
|
267
280
|
const element = container.querySelector('div');
|
|
268
281
|
expect(element).toBeTruthy();
|
|
269
282
|
console.log(element);
|
|
270
283
|
expect(element.classList.contains('test-class')).toBe(true);
|
|
271
|
-
|
|
284
|
+
|
|
272
285
|
// Check if scoped CSS class is present - THIS MIGHT FAIL if CSS pruning issue exists
|
|
273
286
|
const classes = Array.from(element.classList);
|
|
274
|
-
const hasScopedClass = classes.some(cls => cls.startsWith('ripple-'));
|
|
287
|
+
const hasScopedClass = classes.some((cls) => cls.startsWith('ripple-'));
|
|
275
288
|
expect(hasScopedClass).toBe(true);
|
|
276
289
|
});
|
|
277
290
|
|
|
@@ -279,15 +292,18 @@ describe('dynamic DOM elements', () => {
|
|
|
279
292
|
component App() {
|
|
280
293
|
let tag = track('button');
|
|
281
294
|
let count = track(0);
|
|
282
|
-
|
|
283
|
-
<@tag
|
|
295
|
+
|
|
296
|
+
<@tag
|
|
284
297
|
class={@count % 2 ? 'even' : 'odd'}
|
|
285
298
|
id={@count % 2 ? 'even' : 'odd'}
|
|
286
|
-
onClick={() => {
|
|
299
|
+
onClick={() => {
|
|
300
|
+
@count++;
|
|
301
|
+
}}
|
|
287
302
|
>
|
|
288
|
-
{'Count: '}
|
|
303
|
+
{'Count: '}
|
|
304
|
+
{@count}
|
|
289
305
|
</@tag>
|
|
290
|
-
|
|
306
|
+
|
|
291
307
|
<style>
|
|
292
308
|
.even {
|
|
293
309
|
background-color: green;
|
|
@@ -301,40 +317,40 @@ describe('dynamic DOM elements', () => {
|
|
|
301
317
|
}
|
|
302
318
|
|
|
303
319
|
render(App);
|
|
304
|
-
|
|
320
|
+
|
|
305
321
|
const button = container.querySelector('button');
|
|
306
322
|
expect(button).toBeTruthy();
|
|
307
|
-
|
|
323
|
+
|
|
308
324
|
// Initial state: should be odd (count=0, 0%2=false)
|
|
309
325
|
expect(button.classList.contains('odd')).toBe(true);
|
|
310
326
|
expect(button.classList.contains('even')).toBe(false);
|
|
311
327
|
expect(button.id).toBe('odd');
|
|
312
328
|
expect(button.textContent).toBe('Count: 0');
|
|
313
|
-
|
|
329
|
+
|
|
314
330
|
// Check if scoped CSS hash is applied to dynamic element
|
|
315
331
|
const classes = Array.from(button.classList);
|
|
316
|
-
const hasScopedClass = classes.some(cls => cls.startsWith('ripple-'));
|
|
332
|
+
const hasScopedClass = classes.some((cls) => cls.startsWith('ripple-'));
|
|
317
333
|
expect(hasScopedClass).toBe(true);
|
|
318
|
-
|
|
334
|
+
|
|
319
335
|
// Click to increment
|
|
320
336
|
button.click();
|
|
321
337
|
flushSync();
|
|
322
|
-
|
|
323
|
-
// Should now be even (count=1, 1%2=true)
|
|
338
|
+
|
|
339
|
+
// Should now be even (count=1, 1%2=true)
|
|
324
340
|
expect(button.classList.contains('even')).toBe(true);
|
|
325
341
|
expect(button.classList.contains('odd')).toBe(false);
|
|
326
342
|
expect(button.id).toBe('even');
|
|
327
343
|
expect(button.textContent).toBe('Count: 1');
|
|
328
|
-
|
|
344
|
+
|
|
329
345
|
// Scoped CSS class should still be present
|
|
330
346
|
const newClasses = Array.from(button.classList);
|
|
331
|
-
const stillHasScopedClass = newClasses.some(cls => cls.startsWith('ripple-'));
|
|
347
|
+
const stillHasScopedClass = newClasses.some((cls) => cls.startsWith('ripple-'));
|
|
332
348
|
expect(stillHasScopedClass).toBe(true);
|
|
333
|
-
|
|
349
|
+
|
|
334
350
|
// Click again
|
|
335
351
|
button.click();
|
|
336
352
|
flushSync();
|
|
337
|
-
|
|
353
|
+
|
|
338
354
|
// Should toggle back to odd (count=2, 2%2=false)
|
|
339
355
|
expect(button.classList.contains('odd')).toBe(true);
|
|
340
356
|
expect(button.classList.contains('even')).toBe(false);
|
|
@@ -347,7 +363,7 @@ describe('dynamic DOM elements', () => {
|
|
|
347
363
|
const tag = track('button');
|
|
348
364
|
const [children, rest] = trackSplit(props, ['children']);
|
|
349
365
|
<@tag {...@rest}>{@rest.class}</@tag>
|
|
350
|
-
|
|
366
|
+
|
|
351
367
|
<style>
|
|
352
368
|
.even {
|
|
353
369
|
background-color: green;
|
|
@@ -363,38 +379,39 @@ describe('dynamic DOM elements', () => {
|
|
|
363
379
|
<DyanamicButton
|
|
364
380
|
class={@count % 2 ? 'even' : 'odd'}
|
|
365
381
|
id={@count % 2 ? 'even' : 'odd'}
|
|
366
|
-
onClick={() => {
|
|
382
|
+
onClick={() => {
|
|
383
|
+
@count++;
|
|
384
|
+
}}
|
|
367
385
|
/>
|
|
368
386
|
}
|
|
369
387
|
|
|
370
388
|
render(App);
|
|
371
|
-
|
|
389
|
+
|
|
372
390
|
const button = container.querySelector('button');
|
|
373
391
|
expect(button).toBeTruthy();
|
|
374
|
-
|
|
375
|
-
|
|
392
|
+
|
|
376
393
|
// Initial state: should be odd (count=0, 0%2=false)
|
|
377
394
|
expect(button.classList.contains('odd')).toBe(true);
|
|
378
395
|
expect(button.classList.contains('even')).toBe(false);
|
|
379
396
|
expect(button.id).toBe('odd');
|
|
380
|
-
|
|
397
|
+
|
|
381
398
|
// Check if scoped CSS hash is applied (this is the critical test)
|
|
382
399
|
const classes = Array.from(button.classList);
|
|
383
|
-
const hasScopedClass = classes.some(cls => cls.startsWith('ripple-'));
|
|
400
|
+
const hasScopedClass = classes.some((cls) => cls.startsWith('ripple-'));
|
|
384
401
|
expect(hasScopedClass).toBe(true);
|
|
385
|
-
|
|
402
|
+
|
|
386
403
|
// Click to increment
|
|
387
404
|
button.click();
|
|
388
405
|
flushSync();
|
|
389
|
-
|
|
390
|
-
// Should now be even (count=1, 1%2=true)
|
|
406
|
+
|
|
407
|
+
// Should now be even (count=1, 1%2=true)
|
|
391
408
|
expect(button.classList.contains('even')).toBe(true);
|
|
392
409
|
expect(button.classList.contains('odd')).toBe(false);
|
|
393
410
|
expect(button.id).toBe('even');
|
|
394
|
-
|
|
411
|
+
|
|
395
412
|
// Both classes should still be present
|
|
396
413
|
const newClasses = Array.from(button.classList);
|
|
397
|
-
const stillHasScopedClass = newClasses.some(cls => cls.startsWith('ripple-'));
|
|
414
|
+
const stillHasScopedClass = newClasses.some((cls) => cls.startsWith('ripple-'));
|
|
398
415
|
expect(stillHasScopedClass).toBe(true);
|
|
399
416
|
expect(newClasses.includes('even')).toBe(true);
|
|
400
417
|
});
|
|
@@ -403,7 +420,9 @@ describe('dynamic DOM elements', () => {
|
|
|
403
420
|
component App() {
|
|
404
421
|
let tag = track('div');
|
|
405
422
|
|
|
406
|
-
<@tag class="scoped"
|
|
423
|
+
<@tag class="scoped">
|
|
424
|
+
<p>{'Scoped dynamic element'}</p>
|
|
425
|
+
</@tag>
|
|
407
426
|
|
|
408
427
|
<style>
|
|
409
428
|
.scoped {
|
|
@@ -416,15 +435,17 @@ describe('dynamic DOM elements', () => {
|
|
|
416
435
|
const div = container.querySelector('div');
|
|
417
436
|
const p = div.querySelector('p');
|
|
418
437
|
|
|
419
|
-
expect(Array.from(div.classList).some(c => c.startsWith('ripple-'))).toBe(true);
|
|
420
|
-
expect(Array.from(p.classList).some(c => c.startsWith('ripple-'))).toBe(true);
|
|
438
|
+
expect(Array.from(div.classList).some((c) => c.startsWith('ripple-'))).toBe(true);
|
|
439
|
+
expect(Array.from(p.classList).some((c) => c.startsWith('ripple-'))).toBe(true);
|
|
421
440
|
});
|
|
422
441
|
|
|
423
442
|
it('adds scoping class to dynamic elements when selector targets by tag name', () => {
|
|
424
443
|
component App() {
|
|
425
444
|
let tag = track('div');
|
|
426
445
|
|
|
427
|
-
<@tag class="scoped"
|
|
446
|
+
<@tag class="scoped">
|
|
447
|
+
<p>{'Scoped dynamic element'}</p>
|
|
448
|
+
</@tag>
|
|
428
449
|
|
|
429
450
|
<style>
|
|
430
451
|
div {
|
|
@@ -437,13 +458,15 @@ describe('dynamic DOM elements', () => {
|
|
|
437
458
|
const div = container.querySelector('div');
|
|
438
459
|
const p = div.querySelector('p');
|
|
439
460
|
|
|
440
|
-
expect(Array.from(div.classList).some(c => c.startsWith('ripple-'))).toBe(true);
|
|
441
|
-
expect(Array.from(p.classList).some(c => c.startsWith('ripple-'))).toBe(true);
|
|
461
|
+
expect(Array.from(div.classList).some((c) => c.startsWith('ripple-'))).toBe(true);
|
|
462
|
+
expect(Array.from(p.classList).some((c) => c.startsWith('ripple-'))).toBe(true);
|
|
442
463
|
});
|
|
443
464
|
|
|
444
|
-
it(
|
|
465
|
+
it('doesn\'t add scoping class to components inside dynamic element', () => {
|
|
445
466
|
component Child() {
|
|
446
|
-
<div class="child"
|
|
467
|
+
<div class="child">
|
|
468
|
+
<p>{'I am a child component'}</p>
|
|
469
|
+
</div>
|
|
447
470
|
|
|
448
471
|
<style>
|
|
449
472
|
.child {
|
|
@@ -472,9 +495,9 @@ describe('dynamic DOM elements', () => {
|
|
|
472
495
|
const innerDiv = outerDiv.querySelector('.child');
|
|
473
496
|
const innerP = innerDiv.querySelector('p');
|
|
474
497
|
|
|
475
|
-
const outerScope = Array.from(outerDiv.classList).find(c => c.startsWith('ripple-'));
|
|
476
|
-
const innerScopes = Array.from(innerDiv.classList).filter(c => c.startsWith('ripple-'));
|
|
477
|
-
const innerInnerScopes = Array.from(innerP.classList).filter(c => c.startsWith('ripple-'));
|
|
498
|
+
const outerScope = Array.from(outerDiv.classList).find((c) => c.startsWith('ripple-'));
|
|
499
|
+
const innerScopes = Array.from(innerDiv.classList).filter((c) => c.startsWith('ripple-'));
|
|
500
|
+
const innerInnerScopes = Array.from(innerP.classList).filter((c) => c.startsWith('ripple-'));
|
|
478
501
|
|
|
479
502
|
expect(outerScope).toBeTruthy();
|
|
480
503
|
|
|
@@ -484,9 +507,11 @@ describe('dynamic DOM elements', () => {
|
|
|
484
507
|
expect(innerInnerScopes).toHaveLength(0);
|
|
485
508
|
});
|
|
486
509
|
|
|
487
|
-
it(
|
|
510
|
+
it('doesn\'t add scoping class to dynamically rendered component', () => {
|
|
488
511
|
component Child() {
|
|
489
|
-
<div class="child"
|
|
512
|
+
<div class="child">
|
|
513
|
+
<p>{'I am a child component'}</p>
|
|
514
|
+
</div>
|
|
490
515
|
|
|
491
516
|
<style>
|
|
492
517
|
.child {
|
|
@@ -511,8 +536,8 @@ describe('dynamic DOM elements', () => {
|
|
|
511
536
|
const div = container.querySelector('.child');
|
|
512
537
|
const p = div.querySelector('p');
|
|
513
538
|
|
|
514
|
-
const outerScopes = Array.from(div.classList).filter(c => c.startsWith('ripple-'));
|
|
515
|
-
const innerScopes = Array.from(p.classList).filter(c => c.startsWith('ripple-'));
|
|
539
|
+
const outerScopes = Array.from(div.classList).filter((c) => c.startsWith('ripple-'));
|
|
540
|
+
const innerScopes = Array.from(p.classList).filter((c) => c.startsWith('ripple-'));
|
|
516
541
|
|
|
517
542
|
expect(outerScopes).toHaveLength(1);
|
|
518
543
|
expect(innerScopes).toHaveLength(0);
|
|
@@ -51,7 +51,7 @@ describe('for statements', () => {
|
|
|
51
51
|
}
|
|
52
52
|
</div>
|
|
53
53
|
|
|
54
|
-
<button onClick={() => items.push(items.length + 1)}>{
|
|
54
|
+
<button onClick={() => items.push(items.length + 1)}>{'Add Item'}</button>
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
render(App);
|
|
@@ -76,7 +76,9 @@ describe('for statements', () => {
|
|
|
76
76
|
}
|
|
77
77
|
</div>
|
|
78
78
|
|
|
79
|
-
<button onClick={() => items.push(String.fromCharCode(97 + items.length))}>
|
|
79
|
+
<button onClick={() => items.push(String.fromCharCode(97 + items.length))}>
|
|
80
|
+
{'Add Item'}
|
|
81
|
+
</button>
|
|
80
82
|
<button onClick={() => items.reverse()}>{'Reverse'}</button>
|
|
81
83
|
}
|
|
82
84
|
|
|
@@ -109,9 +111,13 @@ describe('for statements', () => {
|
|
|
109
111
|
<div>{i + ':' + item.text}</div>
|
|
110
112
|
}
|
|
111
113
|
|
|
112
|
-
<button
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
<button
|
|
115
|
+
onClick={() => {
|
|
116
|
+
@items = @items.toReversed();
|
|
117
|
+
}}
|
|
118
|
+
>
|
|
119
|
+
{'Reverse'}
|
|
120
|
+
</button>
|
|
115
121
|
}
|
|
116
122
|
|
|
117
123
|
render(App);
|
|
@@ -138,17 +144,21 @@ describe('for statements', () => {
|
|
|
138
144
|
<div>{i + ':' + item.text}</div>
|
|
139
145
|
}
|
|
140
146
|
|
|
141
|
-
<button
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
147
|
+
<button
|
|
148
|
+
onClick={() => {
|
|
149
|
+
@items[0].id = 3;
|
|
150
|
+
@items[1].id = 2;
|
|
151
|
+
@items[2].id = 1;
|
|
152
|
+
|
|
153
|
+
@items = [
|
|
154
|
+
{ ...@items[0], text: 'Item 1!' },
|
|
155
|
+
{ ...@items[1], text: 'Item 2!' },
|
|
156
|
+
{ ...@items[2], text: 'Item 3!' },
|
|
157
|
+
];
|
|
158
|
+
}}
|
|
159
|
+
>
|
|
160
|
+
{'Reverse'}
|
|
161
|
+
</button>
|
|
152
162
|
}
|
|
153
163
|
|
|
154
164
|
render(App);
|
|
@@ -159,5 +169,5 @@ describe('for statements', () => {
|
|
|
159
169
|
flushSync();
|
|
160
170
|
|
|
161
171
|
expect(container).toMatchSnapshot();
|
|
162
|
-
})
|
|
172
|
+
});
|
|
163
173
|
});
|
|
@@ -35,7 +35,13 @@ describe('head elements', () => {
|
|
|
35
35
|
<title>{@title}</title>
|
|
36
36
|
</head>
|
|
37
37
|
<div>
|
|
38
|
-
<button
|
|
38
|
+
<button
|
|
39
|
+
onClick={() => {
|
|
40
|
+
@title = 'Updated Title';
|
|
41
|
+
}}
|
|
42
|
+
>
|
|
43
|
+
{'Update Title'}
|
|
44
|
+
</button>
|
|
39
45
|
<span>{@title}</span>
|
|
40
46
|
</div>
|
|
41
47
|
}
|
|
@@ -61,7 +67,13 @@ describe('head elements', () => {
|
|
|
61
67
|
<title>{`Hello ${@name}!`}</title>
|
|
62
68
|
</head>
|
|
63
69
|
<div>
|
|
64
|
-
<button
|
|
70
|
+
<button
|
|
71
|
+
onClick={() => {
|
|
72
|
+
@name = 'Ripple';
|
|
73
|
+
}}
|
|
74
|
+
>
|
|
75
|
+
{'Change Name'}
|
|
76
|
+
</button>
|
|
65
77
|
</div>
|
|
66
78
|
}
|
|
67
79
|
|
|
@@ -85,7 +97,13 @@ describe('head elements', () => {
|
|
|
85
97
|
<title>{prefix + @count}</title>
|
|
86
98
|
</head>
|
|
87
99
|
<div>
|
|
88
|
-
<button
|
|
100
|
+
<button
|
|
101
|
+
onClick={() => {
|
|
102
|
+
@count++;
|
|
103
|
+
}}
|
|
104
|
+
>
|
|
105
|
+
{'Increment'}
|
|
106
|
+
</button>
|
|
89
107
|
<span>{@count}</span>
|
|
90
108
|
</div>
|
|
91
109
|
}
|
|
@@ -110,7 +128,13 @@ describe('head elements', () => {
|
|
|
110
128
|
<title>{`Step ${@step} of 3`}</title>
|
|
111
129
|
</head>
|
|
112
130
|
<div>
|
|
113
|
-
<button
|
|
131
|
+
<button
|
|
132
|
+
onClick={() => {
|
|
133
|
+
@step = @step % 3 + 1;
|
|
134
|
+
}}
|
|
135
|
+
>
|
|
136
|
+
{'Next Step'}
|
|
137
|
+
</button>
|
|
114
138
|
</div>
|
|
115
139
|
}
|
|
116
140
|
|
|
@@ -155,8 +179,20 @@ describe('head elements', () => {
|
|
|
155
179
|
<title>{@showPrefix ? 'App - ' + @title : @title}</title>
|
|
156
180
|
</head>
|
|
157
181
|
<div>
|
|
158
|
-
<button
|
|
159
|
-
|
|
182
|
+
<button
|
|
183
|
+
onClick={() => {
|
|
184
|
+
@showPrefix = !@showPrefix;
|
|
185
|
+
}}
|
|
186
|
+
>
|
|
187
|
+
{'Toggle Prefix'}
|
|
188
|
+
</button>
|
|
189
|
+
<button
|
|
190
|
+
onClick={() => {
|
|
191
|
+
@title = @title === 'Main Page' ? 'Settings' : 'Main Page';
|
|
192
|
+
}}
|
|
193
|
+
>
|
|
194
|
+
{'Change Page'}
|
|
195
|
+
</button>
|
|
160
196
|
</div>
|
|
161
197
|
}
|
|
162
198
|
|
|
@@ -1,35 +1,41 @@
|
|
|
1
1
|
import { flushSync, track } from 'ripple';
|
|
2
2
|
|
|
3
3
|
describe('html directive', () => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
it('renders static html', () => {
|
|
5
|
+
component App() {
|
|
6
|
+
let str = '<div>Test</div>';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
{html str}
|
|
9
|
+
}
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
render(App);
|
|
12
|
+
expect(container).toMatchSnapshot();
|
|
13
|
+
});
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
it('renders dynamic html', () => {
|
|
16
|
+
component App() {
|
|
17
|
+
let str = track('<div>Test</div>');
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
{html @str}
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
<button
|
|
22
|
+
onClick={() => {
|
|
23
|
+
@str = '<div>Updated</div>';
|
|
24
|
+
}}
|
|
25
|
+
>
|
|
26
|
+
{'Update'}
|
|
27
|
+
</button>
|
|
28
|
+
}
|
|
23
29
|
|
|
24
|
-
|
|
25
|
-
|
|
30
|
+
render(App);
|
|
31
|
+
expect(container).toMatchSnapshot();
|
|
26
32
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
33
|
+
const button = container.querySelector('button');
|
|
34
|
+
button.click();
|
|
35
|
+
flushSync();
|
|
30
36
|
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
expect(container).toMatchSnapshot();
|
|
38
|
+
});
|
|
33
39
|
|
|
34
40
|
it('renders the correct namespace for child svg element when html is surrounded by <svg>', () => {
|
|
35
41
|
component App() {
|
|
@@ -44,18 +50,22 @@ describe('html directive', () => {
|
|
|
44
50
|
expect(circle.namespaceURI).toBe('http://www.w3.org/2000/svg');
|
|
45
51
|
});
|
|
46
52
|
|
|
47
|
-
it(
|
|
48
|
-
|
|
49
|
-
|
|
53
|
+
it(
|
|
54
|
+
'renders the correct namespace for child math element when html is surrounded by <math>',
|
|
55
|
+
() => {
|
|
56
|
+
component App() {
|
|
57
|
+
let str = '<mi>x</mi><mo>+</mo><mi>y</mi>';
|
|
50
58
|
|
|
51
|
-
|
|
52
|
-
}
|
|
59
|
+
<math>{html str}</math>
|
|
53
60
|
|
|
54
|
-
|
|
61
|
+
}
|
|
55
62
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
63
|
+
render(App);
|
|
64
|
+
|
|
65
|
+
const mi = container.querySelector('mi');
|
|
66
|
+
const mo = container.querySelector('mo');
|
|
67
|
+
expect(mi.namespaceURI).toBe('http://www.w3.org/1998/Math/MathML');
|
|
68
|
+
expect(mo.namespaceURI).toBe('http://www.w3.org/1998/Math/MathML');
|
|
69
|
+
},
|
|
70
|
+
);
|
|
61
71
|
});
|