ripple 0.3.72 → 0.3.76
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/CHANGELOG.md +116 -0
- package/package.json +3 -3
- package/src/jsx-runtime.d.ts +4 -10
- package/src/runtime/dynamic-client.js +33 -0
- package/src/runtime/dynamic-server.js +80 -0
- package/src/runtime/index-client.js +5 -13
- package/src/runtime/index-server.js +2 -0
- package/src/runtime/internal/client/blocks.js +6 -27
- package/src/runtime/internal/client/composite.js +11 -6
- package/src/runtime/internal/client/for.js +80 -5
- package/src/runtime/internal/client/index.js +0 -2
- package/src/runtime/internal/client/render.js +5 -2
- package/src/runtime/internal/client/types.d.ts +0 -10
- package/src/runtime/internal/server/index.js +8 -1
- package/tests/client/__snapshots__/computed-properties.test.tsrx.snap +8 -0
- package/tests/client/__snapshots__/for.test.tsrx.snap +22 -0
- package/tests/client/__snapshots__/html.test.tsrx.snap +4 -0
- package/tests/client/array/array.copy-within.test.tsrx +19 -19
- package/tests/client/array/array.derived.test.tsrx +97 -109
- package/tests/client/array/array.iteration.test.tsrx +28 -28
- package/tests/client/array/array.mutations.test.tsrx +68 -68
- package/tests/client/array/array.static.test.tsrx +82 -92
- package/tests/client/array/array.to-methods.test.tsrx +15 -15
- package/tests/client/async-suspend.test.tsrx +180 -179
- package/tests/client/basic/__snapshots__/basic.attributes.test.tsrx.snap +2 -0
- package/tests/client/basic/__snapshots__/basic.rendering.test.tsrx.snap +4 -0
- package/tests/client/basic/basic.attributes.test.tsrx +273 -317
- package/tests/client/basic/basic.collections.test.tsrx +55 -61
- package/tests/client/basic/basic.components.test.tsrx +198 -220
- package/tests/client/basic/basic.errors.test.tsrx +70 -76
- package/tests/client/basic/basic.events.test.tsrx +80 -85
- package/tests/client/basic/basic.get-set.test.tsrx +54 -64
- package/tests/client/basic/basic.hmr.test.tsrx +15 -19
- package/tests/client/basic/basic.reactivity.test.tsrx +121 -135
- package/tests/client/basic/basic.rendering.test.tsrx +273 -178
- package/tests/client/basic/basic.styling.test.tsrx +16 -14
- package/tests/client/basic/basic.utilities.test.tsrx +8 -10
- package/tests/client/boundaries.test.tsrx +18 -18
- package/tests/client/compiler/compiler.assignments.test.tsrx +77 -76
- package/tests/client/compiler/compiler.attributes.test.tsrx +18 -14
- package/tests/client/compiler/compiler.basic.test.tsrx +357 -288
- package/tests/client/compiler/compiler.regex.test.tsrx +40 -44
- package/tests/client/compiler/compiler.tracked-access.test.tsrx +57 -38
- package/tests/client/compiler/compiler.try-in-function.test.tsrx +16 -16
- package/tests/client/compiler/compiler.typescript.test.tsrx +4 -3
- package/tests/client/composite/composite.dynamic-components.test.tsrx +62 -47
- package/tests/client/composite/composite.generics.test.tsrx +165 -167
- package/tests/client/composite/composite.props.test.tsrx +66 -74
- package/tests/client/composite/composite.reactivity.test.tsrx +132 -166
- package/tests/client/composite/composite.render.test.tsrx +92 -101
- package/tests/client/computed-properties.test.tsrx +14 -18
- package/tests/client/context.test.tsrx +14 -18
- package/tests/client/css/global-additional-cases.test.tsrx +493 -439
- package/tests/client/css/global-advanced-selectors.test.tsrx +169 -153
- package/tests/client/css/global-at-rules.test.tsrx +71 -66
- package/tests/client/css/global-basic.test.tsrx +105 -98
- package/tests/client/css/global-classes-ids.test.tsrx +128 -114
- package/tests/client/css/global-combinators.test.tsrx +83 -78
- package/tests/client/css/global-complex-nesting.test.tsrx +134 -120
- package/tests/client/css/global-edge-cases.test.tsrx +138 -120
- package/tests/client/css/global-keyframes.test.tsrx +108 -96
- package/tests/client/css/global-nested.test.tsrx +88 -78
- package/tests/client/css/global-pseudo.test.tsrx +104 -98
- package/tests/client/css/global-scoping.test.tsrx +145 -125
- package/tests/client/css/style-identifier.test.tsrx +65 -72
- package/tests/client/date.test.tsrx +83 -83
- package/tests/client/dynamic-elements.test.tsrx +318 -299
- package/tests/client/events.test.tsrx +252 -266
- package/tests/client/for.test.tsrx +120 -127
- package/tests/client/head.test.tsrx +74 -48
- package/tests/client/html.test.tsrx +37 -49
- package/tests/client/input-value.test.tsrx +1125 -1354
- package/tests/client/lazy-array.test.tsrx +10 -16
- package/tests/client/lazy-destructuring.test.tsrx +169 -221
- package/tests/client/map.test.tsrx +39 -41
- package/tests/client/media-query.test.tsrx +15 -19
- package/tests/client/object.test.tsrx +46 -56
- package/tests/client/portal.test.tsrx +31 -37
- package/tests/client/ref.test.tsrx +173 -193
- package/tests/client/return.test.tsrx +62 -37
- package/tests/client/set.test.tsrx +33 -33
- package/tests/client/svg.test.tsrx +197 -216
- package/tests/client/switch.test.tsrx +201 -191
- package/tests/client/track-async-hydration.test.tsrx +14 -18
- package/tests/client/tracked-index-access.test.tsrx +18 -28
- package/tests/client/try.test.tsrx +494 -619
- package/tests/client/tsx.test.tsrx +286 -292
- package/tests/client/typescript-generics.test.tsrx +121 -129
- package/tests/client/url/url.derived.test.tsrx +21 -25
- package/tests/client/url/url.parsing.test.tsrx +35 -35
- package/tests/client/url/url.partial-removal.test.tsrx +32 -32
- package/tests/client/url/url.reactivity.test.tsrx +68 -72
- package/tests/client/url/url.serialization.test.tsrx +8 -8
- package/tests/client/url-search-params/url-search-params.derived.test.tsrx +21 -27
- package/tests/client/url-search-params/url-search-params.initialization.test.tsrx +16 -16
- package/tests/client/url-search-params/url-search-params.iteration.test.tsrx +37 -37
- package/tests/client/url-search-params/url-search-params.mutation.test.tsrx +56 -60
- package/tests/client/url-search-params/url-search-params.retrieval.test.tsrx +32 -34
- package/tests/client/url-search-params/url-search-params.serialization.test.tsrx +9 -9
- package/tests/client/url-search-params/url-search-params.tracked-url.test.tsrx +10 -10
- package/tests/hydration/compiled/client/basic.js +390 -319
- package/tests/hydration/compiled/client/composite.js +52 -44
- package/tests/hydration/compiled/client/for.js +734 -604
- package/tests/hydration/compiled/client/head.js +183 -103
- package/tests/hydration/compiled/client/html.js +93 -86
- package/tests/hydration/compiled/client/if-children.js +95 -71
- package/tests/hydration/compiled/client/if.js +113 -89
- package/tests/hydration/compiled/client/mixed-control-flow.js +225 -209
- package/tests/hydration/compiled/client/nested-control-flow.js +94 -98
- package/tests/hydration/compiled/client/reactivity.js +26 -24
- package/tests/hydration/compiled/client/return.js +8 -42
- package/tests/hydration/compiled/client/switch.js +208 -173
- package/tests/hydration/compiled/client/track-async-serialization.js +176 -128
- package/tests/hydration/compiled/client/try.js +29 -21
- package/tests/hydration/compiled/server/basic.js +210 -221
- package/tests/hydration/compiled/server/composite.js +13 -14
- package/tests/hydration/compiled/server/for.js +427 -444
- package/tests/hydration/compiled/server/head.js +199 -189
- package/tests/hydration/compiled/server/html.js +33 -41
- package/tests/hydration/compiled/server/if-children.js +114 -117
- package/tests/hydration/compiled/server/if.js +77 -83
- package/tests/hydration/compiled/server/mixed-control-flow.js +145 -150
- package/tests/hydration/compiled/server/nested-control-flow.js +10 -0
- package/tests/hydration/compiled/server/reactivity.js +24 -22
- package/tests/hydration/compiled/server/return.js +6 -18
- package/tests/hydration/compiled/server/switch.js +179 -176
- package/tests/hydration/compiled/server/track-async-serialization.js +88 -70
- package/tests/hydration/compiled/server/try.js +31 -35
- package/tests/hydration/components/basic.tsrx +216 -258
- package/tests/hydration/components/composite.tsrx +32 -42
- package/tests/hydration/components/events.tsrx +81 -101
- package/tests/hydration/components/for.tsrx +270 -336
- package/tests/hydration/components/head.tsrx +43 -39
- package/tests/hydration/components/hmr.tsrx +16 -22
- package/tests/hydration/components/html-in-template.tsrx +15 -21
- package/tests/hydration/components/html.tsrx +442 -526
- package/tests/hydration/components/if-children.tsrx +107 -125
- package/tests/hydration/components/if.tsrx +68 -90
- package/tests/hydration/components/mixed-control-flow.tsrx +65 -72
- package/tests/hydration/components/nested-control-flow.tsrx +202 -216
- package/tests/hydration/components/portal.tsrx +33 -41
- package/tests/hydration/components/reactivity.tsrx +26 -34
- package/tests/hydration/components/return.tsrx +4 -6
- package/tests/hydration/components/switch.tsrx +73 -78
- package/tests/hydration/components/track-async-serialization.tsrx +83 -93
- package/tests/hydration/components/try.tsrx +37 -51
- package/tests/hydration/switch.test.js +8 -8
- package/tests/server/await.test.tsrx +3 -3
- package/tests/server/basic.attributes.test.tsrx +117 -162
- package/tests/server/basic.components.test.tsrx +164 -194
- package/tests/server/basic.test.tsrx +299 -199
- package/tests/server/compiler.test.tsrx +142 -72
- package/tests/server/composite.props.test.tsrx +54 -58
- package/tests/server/composite.test.tsrx +165 -167
- package/tests/server/context.test.tsrx +13 -17
- package/tests/server/dynamic-elements.test.tsrx +147 -148
- package/tests/server/for.test.tsrx +115 -84
- package/tests/server/head.test.tsrx +54 -31
- package/tests/server/html-nesting-validation.test.tsrx +16 -8
- package/tests/server/if.test.tsrx +49 -59
- package/tests/server/lazy-destructuring.test.tsrx +288 -366
- package/tests/server/return.test.tsrx +58 -36
- package/tests/server/streaming-ssr.test.tsrx +4 -4
- package/tests/server/style-identifier.test.tsrx +61 -69
- package/tests/server/switch.test.tsrx +89 -97
- package/tests/server/track-async-serialization.test.tsrx +85 -103
- package/tests/server/try.test.tsrx +275 -360
- package/tests/utils/ref-types.test.js +72 -0
- package/tests/utils/vite-plugin-config.test.js +41 -74
- package/types/index.d.ts +29 -4
- package/src/runtime/internal/client/compat.js +0 -40
- package/tests/utils/compiler-compat-config.test.js +0 -38
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
describe('for statements in SSR', () => {
|
|
2
2
|
it('renders a simple static array', async () => {
|
|
3
|
-
function App() {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
</>;
|
|
3
|
+
function App() @{
|
|
4
|
+
const items = ['Item 1', 'Item 2', 'Item 3'];
|
|
5
|
+
@for (const item of items) {
|
|
6
|
+
<div class={item}>{item}</div>
|
|
7
|
+
}
|
|
10
8
|
}
|
|
11
9
|
|
|
12
10
|
const { body } = await render(App);
|
|
@@ -15,28 +13,43 @@ describe('for statements in SSR', () => {
|
|
|
15
13
|
);
|
|
16
14
|
});
|
|
17
15
|
|
|
16
|
+
it('allows plain JavaScript control flow in setup when rendered output follows', () => {
|
|
17
|
+
expect(
|
|
18
|
+
() => compile(
|
|
19
|
+
`function App() @{
|
|
20
|
+
const items = [1, 2, 3];
|
|
21
|
+
for (const item of items) {
|
|
22
|
+
<div class="selected">{item}</div>
|
|
23
|
+
}
|
|
24
|
+
}`,
|
|
25
|
+
'App.tsrx',
|
|
26
|
+
{ mode: 'server' },
|
|
27
|
+
),
|
|
28
|
+
).not.toThrow();
|
|
29
|
+
});
|
|
30
|
+
|
|
18
31
|
it('renders nested for...of loops', async () => {
|
|
19
|
-
function App() {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
function App() @{
|
|
33
|
+
const groups = [
|
|
34
|
+
{
|
|
35
|
+
name: 'Group 1',
|
|
36
|
+
items: ['Item 1.1', 'Item 1.2'],
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'Group 2',
|
|
40
|
+
items: ['Item 2.1', 'Item 2.2'],
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
@for (const group of groups) {
|
|
44
|
+
<>
|
|
32
45
|
<h1>{group.name}</h1>
|
|
33
46
|
<ul>
|
|
34
|
-
for (const item of group.items) {
|
|
47
|
+
@for (const item of group.items) {
|
|
35
48
|
<li>{item}</li>
|
|
36
49
|
}
|
|
37
50
|
</ul>
|
|
38
|
-
|
|
39
|
-
|
|
51
|
+
</>
|
|
52
|
+
}
|
|
40
53
|
}
|
|
41
54
|
|
|
42
55
|
const { body } = await render(App);
|
|
@@ -46,13 +59,11 @@ describe('for statements in SSR', () => {
|
|
|
46
59
|
});
|
|
47
60
|
|
|
48
61
|
it('renders an array with index', async () => {
|
|
49
|
-
function App() {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
</>;
|
|
62
|
+
function App() @{
|
|
63
|
+
const items = ['Item 1', 'Item 2', 'Item 3'];
|
|
64
|
+
@for (const item of items; index i) {
|
|
65
|
+
<div class={`${item} ${i}`}>{`${item} ${i}`}</div>
|
|
66
|
+
}
|
|
56
67
|
}
|
|
57
68
|
|
|
58
69
|
const { body } = await render(App);
|
|
@@ -62,17 +73,15 @@ describe('for statements in SSR', () => {
|
|
|
62
73
|
});
|
|
63
74
|
|
|
64
75
|
it('renders an array with key', async () => {
|
|
65
|
-
function App() {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
</>;
|
|
76
|
+
function App() @{
|
|
77
|
+
const items = [
|
|
78
|
+
{ id: 1, name: 'Item' },
|
|
79
|
+
{ id: 2, name: 'Item' },
|
|
80
|
+
{ id: 3, name: 'Item' },
|
|
81
|
+
];
|
|
82
|
+
@for (const item of items; key item.id) {
|
|
83
|
+
<div class={`${item.name} ${item.id}`}>{`${item.name} ${item.id}`}</div>
|
|
84
|
+
}
|
|
76
85
|
}
|
|
77
86
|
|
|
78
87
|
const { body } = await render(App);
|
|
@@ -82,17 +91,15 @@ describe('for statements in SSR', () => {
|
|
|
82
91
|
});
|
|
83
92
|
|
|
84
93
|
it('renders an array with index and key', async () => {
|
|
85
|
-
function App() {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
</>;
|
|
94
|
+
function App() @{
|
|
95
|
+
const items = [
|
|
96
|
+
{ id: 1, name: 'Item' },
|
|
97
|
+
{ id: 2, name: 'Item' },
|
|
98
|
+
{ id: 3, name: 'Item' },
|
|
99
|
+
];
|
|
100
|
+
@for (const item of items; index i; key item.id) {
|
|
101
|
+
<div class={`${item.name} ${item.id} ${i}`}>{`${item.name} ${item.id} ${i}`}</div>
|
|
102
|
+
}
|
|
96
103
|
}
|
|
97
104
|
|
|
98
105
|
const { body } = await render(App);
|
|
@@ -101,39 +108,48 @@ describe('for statements in SSR', () => {
|
|
|
101
108
|
);
|
|
102
109
|
});
|
|
103
110
|
|
|
104
|
-
it('
|
|
105
|
-
function App() {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
<div>{item}</div>
|
|
111
|
-
}
|
|
112
|
-
</>;
|
|
111
|
+
it('renders filtered items before passing them to @for', async () => {
|
|
112
|
+
function App() @{
|
|
113
|
+
const items = ['Item 1', '', 'Item 3'].filter(Boolean);
|
|
114
|
+
@for (const item of items) {
|
|
115
|
+
<div>{item}</div>
|
|
116
|
+
}
|
|
113
117
|
}
|
|
114
118
|
|
|
115
119
|
const { body } = await render(App);
|
|
116
120
|
expect(body).toBeHtml('<div>Item 1</div><div>Item 3</div>');
|
|
117
121
|
});
|
|
118
122
|
|
|
123
|
+
it('renders an empty fallback', async () => {
|
|
124
|
+
function App() @{
|
|
125
|
+
const items = [];
|
|
126
|
+
@for (const item of items) {
|
|
127
|
+
<div>{item}</div>
|
|
128
|
+
} @empty {
|
|
129
|
+
<p>No items</p>
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const { body } = await render(App);
|
|
134
|
+
expect(body).toBeHtml('<p>No items</p>');
|
|
135
|
+
});
|
|
136
|
+
|
|
119
137
|
it('allows ordinary function control flow inside for...of loops', async () => {
|
|
120
|
-
function App() {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
break;
|
|
128
|
-
}
|
|
129
|
-
if (!value) return 'missing';
|
|
138
|
+
function App() @{
|
|
139
|
+
const items = ['Item 1', '', 'Item 3'];
|
|
140
|
+
@for (const item of items) {
|
|
141
|
+
function label(value) {
|
|
142
|
+
for (let i = 0; i < 1; i++) {
|
|
143
|
+
while (i < 0) {
|
|
144
|
+
break;
|
|
130
145
|
}
|
|
131
|
-
return
|
|
146
|
+
if (!value) return 'missing';
|
|
132
147
|
}
|
|
133
|
-
|
|
134
|
-
<div>{label(item)}</div>
|
|
148
|
+
return value;
|
|
135
149
|
}
|
|
136
|
-
|
|
150
|
+
|
|
151
|
+
<div>{label(item)}</div>
|
|
152
|
+
}
|
|
137
153
|
}
|
|
138
154
|
|
|
139
155
|
const { body } = await render(App);
|
|
@@ -143,30 +159,45 @@ describe('for statements in SSR', () => {
|
|
|
143
159
|
it('throws for return statements inside for...of loops', () => {
|
|
144
160
|
expect(
|
|
145
161
|
() => compile(
|
|
146
|
-
`function App(items) {
|
|
147
|
-
|
|
148
|
-
|
|
162
|
+
`function App(items) @{
|
|
163
|
+
@for (const item of items) {
|
|
164
|
+
if (!item) return
|
|
149
165
|
<div>{item}</div>
|
|
150
166
|
}
|
|
151
|
-
|
|
167
|
+
}`,
|
|
152
168
|
'App.tsrx',
|
|
153
169
|
{ mode: 'server' },
|
|
154
170
|
),
|
|
155
|
-
).toThrow('Return statements are not allowed inside TSRX
|
|
171
|
+
).toThrow('Return statements are not allowed inside TSRX template for...of loops.');
|
|
156
172
|
});
|
|
157
173
|
|
|
158
174
|
it('throws for break statements targeting for...of loops', () => {
|
|
159
175
|
expect(
|
|
160
176
|
() => compile(
|
|
161
|
-
`function App(items) {
|
|
162
|
-
|
|
163
|
-
|
|
177
|
+
`function App(items) @{
|
|
178
|
+
@for (const item of items) {
|
|
179
|
+
if (!item) break
|
|
164
180
|
<div>{item}</div>
|
|
165
181
|
}
|
|
166
|
-
|
|
182
|
+
}`,
|
|
167
183
|
'App.tsrx',
|
|
168
184
|
{ mode: 'server' },
|
|
169
185
|
),
|
|
170
186
|
).toThrow('Break statements are not allowed inside TSRX template for...of loops');
|
|
171
187
|
});
|
|
188
|
+
|
|
189
|
+
it('throws for continue statements inside for...of loops', () => {
|
|
190
|
+
expect(
|
|
191
|
+
() => compile(
|
|
192
|
+
`function App(items) @{
|
|
193
|
+
@for (const item of items) {
|
|
194
|
+
if (!item) continue
|
|
195
|
+
<div>{item}</div>
|
|
196
|
+
}
|
|
197
|
+
}`,
|
|
198
|
+
'App.tsrx',
|
|
199
|
+
{ mode: 'server' },
|
|
200
|
+
),
|
|
201
|
+
).toThrow('Continue statements are not allowed inside TSRX template for...of loops');
|
|
202
|
+
});
|
|
172
203
|
});
|
|
@@ -2,13 +2,13 @@ import { track } from 'ripple';
|
|
|
2
2
|
|
|
3
3
|
describe('head elements', () => {
|
|
4
4
|
it('renders static title element', async () => {
|
|
5
|
-
function App() {
|
|
6
|
-
|
|
5
|
+
function App() @{
|
|
6
|
+
<>
|
|
7
7
|
<head>
|
|
8
8
|
<title>{'Static Test Title'}</title>
|
|
9
9
|
</head>
|
|
10
10
|
<div>{'Content'}</div>
|
|
11
|
-
|
|
11
|
+
</>
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
const { head, body } = await render(App);
|
|
@@ -19,16 +19,16 @@ describe('head elements', () => {
|
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
it('renders reactive title element', async () => {
|
|
22
|
-
function App() {
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
function App() @{
|
|
23
|
+
let &[title] = track('Initial Title');
|
|
24
|
+
<>
|
|
25
25
|
<head>
|
|
26
26
|
<title>{title}</title>
|
|
27
27
|
</head>
|
|
28
28
|
<div>
|
|
29
29
|
<span>{title}</span>
|
|
30
30
|
</div>
|
|
31
|
-
|
|
31
|
+
</>
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
const { head, body } = await render(App);
|
|
@@ -39,13 +39,11 @@ describe('head elements', () => {
|
|
|
39
39
|
});
|
|
40
40
|
|
|
41
41
|
it('renders title with template literal', async () => {
|
|
42
|
-
function App() {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
</head>
|
|
48
|
-
</>;
|
|
42
|
+
function App() @{
|
|
43
|
+
let &[name] = track('World');
|
|
44
|
+
<head>
|
|
45
|
+
<title>{`Hello ${name}!`}</title>
|
|
46
|
+
</head>
|
|
49
47
|
}
|
|
50
48
|
|
|
51
49
|
const { head, body } = await render(App);
|
|
@@ -55,17 +53,19 @@ describe('head elements', () => {
|
|
|
55
53
|
});
|
|
56
54
|
|
|
57
55
|
it('renders title with computed value', async () => {
|
|
58
|
-
function App() {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
function App() @{
|
|
57
|
+
let &[count] = track(0);
|
|
58
|
+
let prefix = 'Count: ';
|
|
59
|
+
<>
|
|
62
60
|
<head>
|
|
63
|
-
<title>
|
|
61
|
+
<title>
|
|
62
|
+
{prefix + count}
|
|
63
|
+
</title>
|
|
64
64
|
</head>
|
|
65
65
|
<div>
|
|
66
66
|
<span>{count}</span>
|
|
67
67
|
</div>
|
|
68
|
-
|
|
68
|
+
</>
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
const { head, body } = await render(App);
|
|
@@ -75,13 +75,13 @@ describe('head elements', () => {
|
|
|
75
75
|
});
|
|
76
76
|
|
|
77
77
|
it('renders empty title', async () => {
|
|
78
|
-
function App() {
|
|
79
|
-
|
|
78
|
+
function App() @{
|
|
79
|
+
<>
|
|
80
80
|
<head>
|
|
81
81
|
<title>{''}</title>
|
|
82
82
|
</head>
|
|
83
83
|
<div>{'Empty title test'}</div>
|
|
84
|
-
|
|
84
|
+
</>
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
const { head, body } = await render(App);
|
|
@@ -90,15 +90,38 @@ describe('head elements', () => {
|
|
|
90
90
|
expect(document.title).toBe('');
|
|
91
91
|
});
|
|
92
92
|
|
|
93
|
+
it('renders external scripts with src attributes from a loop', async () => {
|
|
94
|
+
const Head = ({ scripts }: { scripts: { src: string }[] }) => @{
|
|
95
|
+
<head>
|
|
96
|
+
@for (const script of scripts) {
|
|
97
|
+
<script src={script.src} />
|
|
98
|
+
}
|
|
99
|
+
</head>
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
function App() @{
|
|
103
|
+
<Head scripts={[{ src: '/a.js' }, { src: '/b.js' }]} />
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const { head, body } = await render(App);
|
|
107
|
+
const { document } = parseAsFullHtml(head, body);
|
|
108
|
+
|
|
109
|
+
const srcs = Array.from(document.querySelectorAll('head script[src]')).map(
|
|
110
|
+
(node) => node.getAttribute('src'),
|
|
111
|
+
).sort();
|
|
112
|
+
|
|
113
|
+
expect(srcs).toEqual(['/a.js', '/b.js']);
|
|
114
|
+
});
|
|
115
|
+
|
|
93
116
|
it('renders title with conditional content', async () => {
|
|
94
|
-
function App() {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
<
|
|
99
|
-
|
|
100
|
-
</
|
|
101
|
-
|
|
117
|
+
function App() @{
|
|
118
|
+
let &[showPrefix] = track(true);
|
|
119
|
+
let &[title] = track('Main Page');
|
|
120
|
+
<head>
|
|
121
|
+
<title>
|
|
122
|
+
{showPrefix ? 'App - ' + title : title}
|
|
123
|
+
</title>
|
|
124
|
+
</head>
|
|
102
125
|
}
|
|
103
126
|
|
|
104
127
|
const { head, body } = await render(App);
|
|
@@ -180,11 +180,13 @@ describe('HTML nesting validation', () => {
|
|
|
180
180
|
describe('compiler dev mode output', () => {
|
|
181
181
|
it('emits push_element and pop_element calls in dev mode', () => {
|
|
182
182
|
const lines = [];
|
|
183
|
-
lines.push('function App() {
|
|
183
|
+
lines.push('function App() @{');
|
|
184
|
+
lines.push(' <>');
|
|
184
185
|
lines.push(' <div>');
|
|
185
186
|
lines.push(' <span>{"Hello"}</span>');
|
|
186
187
|
lines.push(' </div>');
|
|
187
|
-
lines.push('
|
|
188
|
+
lines.push(' </>');
|
|
189
|
+
lines.push('}');
|
|
188
190
|
const source = lines.join('\n');
|
|
189
191
|
|
|
190
192
|
const result = compile(source, 'test.tsrx', { mode: 'server', dev: true });
|
|
@@ -195,11 +197,13 @@ describe('HTML nesting validation', () => {
|
|
|
195
197
|
|
|
196
198
|
it('does not emit push_element or pop_element in non-dev mode', () => {
|
|
197
199
|
const lines = [];
|
|
198
|
-
lines.push('function App() {
|
|
200
|
+
lines.push('function App() @{');
|
|
201
|
+
lines.push(' <>');
|
|
199
202
|
lines.push(' <div>');
|
|
200
203
|
lines.push(' <span>{"Hello"}</span>');
|
|
201
204
|
lines.push(' </div>');
|
|
202
|
-
lines.push('
|
|
205
|
+
lines.push(' </>');
|
|
206
|
+
lines.push('}');
|
|
203
207
|
const source = lines.join('\n');
|
|
204
208
|
|
|
205
209
|
const result = compile(source, 'test.tsrx', { mode: 'server', dev: false });
|
|
@@ -210,9 +214,11 @@ describe('HTML nesting validation', () => {
|
|
|
210
214
|
|
|
211
215
|
it('emits push_element with correct tag name', () => {
|
|
212
216
|
const lines = [];
|
|
213
|
-
lines.push('function App() {
|
|
217
|
+
lines.push('function App() @{');
|
|
218
|
+
lines.push(' <>');
|
|
214
219
|
lines.push(' <button>{"Click"}</button>');
|
|
215
|
-
lines.push('
|
|
220
|
+
lines.push(' </>');
|
|
221
|
+
lines.push('}');
|
|
216
222
|
const source = lines.join('\n');
|
|
217
223
|
|
|
218
224
|
const result = compile(source, 'test.tsrx', { mode: 'server', dev: true });
|
|
@@ -222,9 +228,11 @@ describe('HTML nesting validation', () => {
|
|
|
222
228
|
|
|
223
229
|
it('does not emit push_element for client mode', () => {
|
|
224
230
|
const lines = [];
|
|
225
|
-
lines.push('function App() {
|
|
231
|
+
lines.push('function App() @{');
|
|
232
|
+
lines.push(' <>');
|
|
226
233
|
lines.push(' <div>{"Hello"}</div>');
|
|
227
|
-
lines.push('
|
|
234
|
+
lines.push(' </>');
|
|
235
|
+
lines.push('}');
|
|
228
236
|
const source = lines.join('\n');
|
|
229
237
|
|
|
230
238
|
const result = compile(source, 'test.tsrx', { mode: 'client', dev: true });
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
describe('if statements in SSR', () => {
|
|
2
2
|
it('renders if block when condition is true', async () => {
|
|
3
|
-
function App() {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
</>;
|
|
3
|
+
function App() @{
|
|
4
|
+
let condition = true;
|
|
5
|
+
@if (condition) {
|
|
6
|
+
<div>{'If block'}</div>
|
|
7
|
+
}
|
|
10
8
|
}
|
|
11
9
|
|
|
12
10
|
const { body } = await render(App);
|
|
@@ -14,29 +12,27 @@ describe('if statements in SSR', () => {
|
|
|
14
12
|
});
|
|
15
13
|
|
|
16
14
|
it('renders else block when condition is false', async () => {
|
|
17
|
-
function App() {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
</>;
|
|
15
|
+
function App() @{
|
|
16
|
+
let condition = false;
|
|
17
|
+
@if (condition) {
|
|
18
|
+
<div>{'If block'}</div>
|
|
19
|
+
} @else {
|
|
20
|
+
<div>{'Else block'}</div>
|
|
21
|
+
}
|
|
26
22
|
}
|
|
27
23
|
|
|
28
24
|
const { body } = await render(App);
|
|
29
25
|
expect(body).toBeHtml('<div>Else block</div>');
|
|
30
26
|
});
|
|
31
27
|
|
|
32
|
-
it('renders bare
|
|
33
|
-
function App() {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
28
|
+
it('renders bare JSX text in if-else branches', async () => {
|
|
29
|
+
function App() @{
|
|
30
|
+
let condition = false;
|
|
31
|
+
@if (condition) {
|
|
32
|
+
<>Hello Ripple</>
|
|
33
|
+
} @else {
|
|
34
|
+
<>Hello React</>
|
|
35
|
+
}
|
|
40
36
|
}
|
|
41
37
|
|
|
42
38
|
const { body } = await render(App);
|
|
@@ -44,17 +40,15 @@ describe('if statements in SSR', () => {
|
|
|
44
40
|
});
|
|
45
41
|
|
|
46
42
|
it('renders else if block when condition is true', async () => {
|
|
47
|
-
function App() {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
</>;
|
|
43
|
+
function App() @{
|
|
44
|
+
let value = 'b';
|
|
45
|
+
@if (value === 'a') {
|
|
46
|
+
<div>Case A</div>
|
|
47
|
+
} @else if (value === 'b') {
|
|
48
|
+
<div>Case B</div>
|
|
49
|
+
} @else {
|
|
50
|
+
<div>{'Default Case'}</div>
|
|
51
|
+
}
|
|
58
52
|
}
|
|
59
53
|
|
|
60
54
|
const { body } = await render(App);
|
|
@@ -62,17 +56,15 @@ describe('if statements in SSR', () => {
|
|
|
62
56
|
});
|
|
63
57
|
|
|
64
58
|
it('renders final else block in an if-else if-else chain', async () => {
|
|
65
|
-
function App() {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
</>;
|
|
59
|
+
function App() @{
|
|
60
|
+
let value = 'c';
|
|
61
|
+
@if (value === 'a') {
|
|
62
|
+
<div>Case A</div>
|
|
63
|
+
} @else if (value === 'b') {
|
|
64
|
+
<div>Case B</div>
|
|
65
|
+
} @else {
|
|
66
|
+
<div>{'Default Case'}</div>
|
|
67
|
+
}
|
|
76
68
|
}
|
|
77
69
|
|
|
78
70
|
const { body } = await render(App);
|
|
@@ -80,20 +72,18 @@ describe('if statements in SSR', () => {
|
|
|
80
72
|
});
|
|
81
73
|
|
|
82
74
|
it('renders nested if-else blocks correctly', async () => {
|
|
83
|
-
function App() {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
<div>{'Outer true, Inner false'}</div>
|
|
92
|
-
}
|
|
93
|
-
} else {
|
|
94
|
-
<div>{'Outer false'}</div>
|
|
75
|
+
function App() @{
|
|
76
|
+
let outer = true;
|
|
77
|
+
let inner = false;
|
|
78
|
+
@if (outer) {
|
|
79
|
+
@if (inner) {
|
|
80
|
+
<div>{'Outer true, Inner true'}</div>
|
|
81
|
+
} @else {
|
|
82
|
+
<div>{'Outer true, Inner false'}</div>
|
|
95
83
|
}
|
|
96
|
-
|
|
84
|
+
} @else {
|
|
85
|
+
<div>{'Outer false'}</div>
|
|
86
|
+
}
|
|
97
87
|
}
|
|
98
88
|
|
|
99
89
|
const { body } = await render(App);
|