ripple 0.2.33 → 0.2.34
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/package.json
CHANGED
|
@@ -148,6 +148,45 @@ const visitors = {
|
|
|
148
148
|
return context.next();
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
+
// Handle array methods that access the array
|
|
152
|
+
if (
|
|
153
|
+
callee.type === 'MemberExpression' &&
|
|
154
|
+
!callee.optional &&
|
|
155
|
+
callee.property.type === 'Identifier'
|
|
156
|
+
) {
|
|
157
|
+
const name = callee.property.name;
|
|
158
|
+
if (
|
|
159
|
+
// TODO support the missing array methods
|
|
160
|
+
name === 'reduce' ||
|
|
161
|
+
name === 'map' ||
|
|
162
|
+
name === 'forEach' ||
|
|
163
|
+
name === 'join' ||
|
|
164
|
+
name === 'includes' ||
|
|
165
|
+
name === 'indexOf' ||
|
|
166
|
+
name === 'lastIndexOf' ||
|
|
167
|
+
name === 'filter' ||
|
|
168
|
+
name === 'every' ||
|
|
169
|
+
name === 'some' ||
|
|
170
|
+
name === 'toSpliced' ||
|
|
171
|
+
name === 'toSorted' ||
|
|
172
|
+
name === 'toString' ||
|
|
173
|
+
name === 'values' ||
|
|
174
|
+
name === 'entries'
|
|
175
|
+
) {
|
|
176
|
+
return b.call(
|
|
177
|
+
'$.with_scope',
|
|
178
|
+
b.id('__block'),
|
|
179
|
+
b.thunk(
|
|
180
|
+
b.call(
|
|
181
|
+
'$.array_' + name,
|
|
182
|
+
context.visit(callee.object),
|
|
183
|
+
...node.arguments.map((arg) => context.visit(arg)),
|
|
184
|
+
),
|
|
185
|
+
),
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
151
190
|
return b.call(
|
|
152
191
|
'$.with_scope',
|
|
153
192
|
b.id('__block'),
|
|
@@ -975,43 +1014,37 @@ const visitors = {
|
|
|
975
1014
|
},
|
|
976
1015
|
|
|
977
1016
|
ArrayExpression(node, context) {
|
|
978
|
-
//
|
|
979
|
-
//
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
// i++;
|
|
1010
|
-
// }
|
|
1011
|
-
|
|
1012
|
-
// if (tracked.length > 0) {
|
|
1013
|
-
// return b.call('$.tracked_object', { ...node, elements }, b.array(tracked), b.id('__block'));
|
|
1014
|
-
// }
|
|
1017
|
+
// TODO we can bail out of all of this if we know we're inside a computed fn expression
|
|
1018
|
+
// as the reactivity will hold from the reference of the $ binding itself
|
|
1019
|
+
const elements = [];
|
|
1020
|
+
const tracked = [];
|
|
1021
|
+
let i = 0;
|
|
1022
|
+
|
|
1023
|
+
for (const element of node.elements) {
|
|
1024
|
+
if (element === null) {
|
|
1025
|
+
elements.push(null);
|
|
1026
|
+
} else if (element.type === 'Identifier' && is_tracked_name(element.name)) {
|
|
1027
|
+
const metadata = { tracking: false, await: false };
|
|
1028
|
+
const tracked_identifier = context.visit(element, { ...context.state, metadata });
|
|
1029
|
+
|
|
1030
|
+
if (metadata.tracking) {
|
|
1031
|
+
tracked.push(b.literal(i));
|
|
1032
|
+
elements.push(
|
|
1033
|
+
b.call('$.computed_property', b.thunk(tracked_identifier), b.id('__block')),
|
|
1034
|
+
);
|
|
1035
|
+
} else {
|
|
1036
|
+
elements.push(tracked_identifier);
|
|
1037
|
+
}
|
|
1038
|
+
} else {
|
|
1039
|
+
const metadata = { tracking: false, await: false };
|
|
1040
|
+
elements.push(context.visit(element, { ...context.state, metadata }));
|
|
1041
|
+
}
|
|
1042
|
+
i++;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
if (tracked.length > 0) {
|
|
1046
|
+
return b.call('$.tracked_object', { ...node, elements }, b.array(tracked), b.id('__block'));
|
|
1047
|
+
}
|
|
1015
1048
|
|
|
1016
1049
|
context.next();
|
|
1017
1050
|
},
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import { TRACKED_OBJECT } from './constants';
|
|
2
|
+
import { get_property } from './runtime';
|
|
3
|
+
|
|
4
|
+
const array_proto = Array.prototype;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @template T
|
|
8
|
+
* @param {Array<T>} array
|
|
9
|
+
* @param {(previousValue: T, currentValue: T, currentIndex: number, array: Array<T>) => T} callback
|
|
10
|
+
* @param {T} initial_value
|
|
11
|
+
* @returns {T}
|
|
12
|
+
*/
|
|
13
|
+
export function array_reduce(array, callback, initial_value) {
|
|
14
|
+
// @ts-expect-error
|
|
15
|
+
var tracked_properties = array[TRACKED_OBJECT];
|
|
16
|
+
|
|
17
|
+
if (tracked_properties === undefined || array.reduce !== array_proto.reduce) {
|
|
18
|
+
return array.reduce(callback, initial_value);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let accumulator = initial_value;
|
|
22
|
+
|
|
23
|
+
for (let i = 0; i < array.length; i++) {
|
|
24
|
+
accumulator = callback(accumulator, get_property(array, i), i, array);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return accumulator;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @template T
|
|
32
|
+
* @param {Array<T>} array
|
|
33
|
+
* @param {string} [separator]
|
|
34
|
+
* @returns {string}
|
|
35
|
+
*/
|
|
36
|
+
export function array_join(array, separator) {
|
|
37
|
+
// @ts-expect-error
|
|
38
|
+
var tracked_properties = array[TRACKED_OBJECT];
|
|
39
|
+
if (tracked_properties === undefined || array.join !== array_proto.join) {
|
|
40
|
+
return array.join(separator);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let result = '';
|
|
44
|
+
for (let i = 0; i < array.length; i++) {
|
|
45
|
+
if (i > 0 && separator !== undefined) {
|
|
46
|
+
result += separator;
|
|
47
|
+
}
|
|
48
|
+
result += String(get_property(array, i));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @template T
|
|
56
|
+
* @template U
|
|
57
|
+
* @param {Array<T>} array
|
|
58
|
+
* @param {(value: T, index: number, array: Array<T>) => U} callback
|
|
59
|
+
* @returns {Array<U>}
|
|
60
|
+
*/
|
|
61
|
+
export function array_map(array, callback) {
|
|
62
|
+
// @ts-expect-error
|
|
63
|
+
var tracked_properties = array[TRACKED_OBJECT];
|
|
64
|
+
if (tracked_properties === undefined || array.map !== array_proto.map) {
|
|
65
|
+
return array.map(callback);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const result = [];
|
|
69
|
+
for (let i = 0; i < array.length; i++) {
|
|
70
|
+
if (i in array) {
|
|
71
|
+
result[i] = callback(get_property(array, i), i, array);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @template T
|
|
80
|
+
* @param {Array<T>} array
|
|
81
|
+
* @param {(value: T, index: number, array: Array<T>) => boolean} callback
|
|
82
|
+
* @returns {Array<T>}
|
|
83
|
+
*/
|
|
84
|
+
export function array_filter(array, callback) {
|
|
85
|
+
// @ts-expect-error
|
|
86
|
+
var tracked_properties = array[TRACKED_OBJECT];
|
|
87
|
+
if (tracked_properties === undefined || array.filter !== array_proto.filter) {
|
|
88
|
+
return array.filter(callback);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const result = [];
|
|
92
|
+
for (let i = 0; i < array.length; i++) {
|
|
93
|
+
if (i in array) {
|
|
94
|
+
const value = get_property(array, i);
|
|
95
|
+
if (callback(value, i, array)) {
|
|
96
|
+
result.push(value);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @template T
|
|
106
|
+
* @param {Array<T>} array
|
|
107
|
+
* @param {(value: T, index: number, array: Array<T>) => boolean} callback
|
|
108
|
+
* @returns {void}
|
|
109
|
+
*/
|
|
110
|
+
export function array_forEach(array, callback) {
|
|
111
|
+
// @ts-expect-error
|
|
112
|
+
var tracked_properties = array[TRACKED_OBJECT];
|
|
113
|
+
if (tracked_properties === undefined || array.forEach !== array_proto.forEach) {
|
|
114
|
+
return array.forEach(callback);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
for (let i = 0; i < array.length; i++) {
|
|
118
|
+
if (i in array) {
|
|
119
|
+
callback(get_property(array, i), i, array);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @template T
|
|
126
|
+
* @param {Array<T>} array
|
|
127
|
+
* @param {T} value
|
|
128
|
+
* @returns {boolean}
|
|
129
|
+
*/
|
|
130
|
+
export function array_includes(array, value) {
|
|
131
|
+
// @ts-expect-error
|
|
132
|
+
var tracked_properties = array[TRACKED_OBJECT];
|
|
133
|
+
if (tracked_properties === undefined || array.includes !== array_proto.includes) {
|
|
134
|
+
return array.includes(value);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
for (let i = 0; i < array.length; i++) {
|
|
138
|
+
if (i in array && get_property(array, i) === value) {
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @template T
|
|
148
|
+
* @param {Array<T>} array
|
|
149
|
+
* @param {T} value
|
|
150
|
+
* @returns {number}
|
|
151
|
+
*/
|
|
152
|
+
export function array_indexOf(array, value) {
|
|
153
|
+
// @ts-expect-error
|
|
154
|
+
var tracked_properties = array[TRACKED_OBJECT];
|
|
155
|
+
if (tracked_properties === undefined || array.indexOf !== array_proto.indexOf) {
|
|
156
|
+
return array.indexOf(value);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
for (let i = 0; i < array.length; i++) {
|
|
160
|
+
if (i in array && get_property(array, i) === value) {
|
|
161
|
+
return i;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return -1;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @template T
|
|
170
|
+
* @param {Array<T>} array
|
|
171
|
+
* @param {T} value
|
|
172
|
+
* @returns {number}
|
|
173
|
+
*/
|
|
174
|
+
export function array_lastIndexOf(array, value) {
|
|
175
|
+
// @ts-expect-error
|
|
176
|
+
var tracked_properties = array[TRACKED_OBJECT];
|
|
177
|
+
if (tracked_properties === undefined || array.lastIndexOf !== array_proto.lastIndexOf) {
|
|
178
|
+
return array.lastIndexOf(value);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
for (let i = array.length - 1; i >= 0; i--) {
|
|
182
|
+
if (i in array && get_property(array, i) === value) {
|
|
183
|
+
return i;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return -1;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* @template T
|
|
192
|
+
* @param {Array<T>} array
|
|
193
|
+
* @param {(value: T, index: number, array: Array<T>) => boolean} callback
|
|
194
|
+
* @returns {boolean}
|
|
195
|
+
*/
|
|
196
|
+
export function array_every(array, callback) {
|
|
197
|
+
// @ts-expect-error
|
|
198
|
+
var tracked_properties = array[TRACKED_OBJECT];
|
|
199
|
+
if (tracked_properties === undefined || array.every !== array_proto.every) {
|
|
200
|
+
return array.every(callback);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
for (let i = 0; i < array.length; i++) {
|
|
204
|
+
if (i in array && !callback(get_property(array, i), i, array)) {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* @template T
|
|
214
|
+
* @param {Array<T>} array
|
|
215
|
+
* @param {(value: T, index: number, array: Array<T>) => boolean} callback
|
|
216
|
+
* @returns {boolean}
|
|
217
|
+
*/
|
|
218
|
+
export function array_some(array, callback) {
|
|
219
|
+
// @ts-expect-error
|
|
220
|
+
var tracked_properties = array[TRACKED_OBJECT];
|
|
221
|
+
if (tracked_properties === undefined || array.some !== array_proto.some) {
|
|
222
|
+
return array.some(callback);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
for (let i = 0; i < array.length; i++) {
|
|
226
|
+
if (i in array && callback(get_property(array, i), i, array)) {
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* @template T
|
|
236
|
+
* @param {Array<T>} array
|
|
237
|
+
* @returns {string}
|
|
238
|
+
*/
|
|
239
|
+
export function array_toString(array) {
|
|
240
|
+
// @ts-expect-error
|
|
241
|
+
var tracked_properties = array[TRACKED_OBJECT];
|
|
242
|
+
if (tracked_properties === undefined || array.toString !== array_proto.toString) {
|
|
243
|
+
return array.toString();
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
let result = '';
|
|
247
|
+
for (let i = 0; i < array.length; i++) {
|
|
248
|
+
if (i > 0) {
|
|
249
|
+
result += ',';
|
|
250
|
+
}
|
|
251
|
+
if (i in array) {
|
|
252
|
+
result += String(get_property(array, i));
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return result;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* @template T
|
|
261
|
+
* @param {Array<T>} array
|
|
262
|
+
* @param {((a: T, b: T) => number) | undefined} compare_fn
|
|
263
|
+
* @returns {Array<T>}
|
|
264
|
+
*/
|
|
265
|
+
export function array_toSorted(array, compare_fn) {
|
|
266
|
+
// @ts-expect-error
|
|
267
|
+
var tracked_properties = array[TRACKED_OBJECT];
|
|
268
|
+
if (tracked_properties === undefined || array.toSorted !== array_proto.toSorted) {
|
|
269
|
+
return array.toSorted(compare_fn);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const result = [];
|
|
273
|
+
for (let i = 0; i < array.length; i++) {
|
|
274
|
+
if (i in array) {
|
|
275
|
+
result.push(get_property(array, i));
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return result.sort(compare_fn);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* @template T
|
|
284
|
+
* @param {Array<T>} array
|
|
285
|
+
* @param {number} start
|
|
286
|
+
* @param {number} delete_count
|
|
287
|
+
* @param {...T} items
|
|
288
|
+
* @returns {Array<T>}
|
|
289
|
+
*/
|
|
290
|
+
export function array_toSpliced(array, start, delete_count, ...items) {
|
|
291
|
+
// @ts-expect-error
|
|
292
|
+
var tracked_properties = array[TRACKED_OBJECT];
|
|
293
|
+
if (tracked_properties === undefined || array.toSpliced !== array_proto.toSpliced) {
|
|
294
|
+
return array.toSpliced(start, delete_count, ...items);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const result = [];
|
|
298
|
+
for (let i = 0; i < array.length; i++) {
|
|
299
|
+
if (i in array) {
|
|
300
|
+
result.push(get_property(array, i));
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
result.splice(start, delete_count, ...items);
|
|
305
|
+
|
|
306
|
+
return result;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* @template T
|
|
311
|
+
* @param {Array<T>} array
|
|
312
|
+
* @returns {IterableIterator<T>}
|
|
313
|
+
*/
|
|
314
|
+
export function array_values(array) {
|
|
315
|
+
// @ts-expect-error
|
|
316
|
+
var tracked_properties = array[TRACKED_OBJECT];
|
|
317
|
+
if (tracked_properties === undefined || array.values !== array_proto.values) {
|
|
318
|
+
return array.values();
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const result = [];
|
|
322
|
+
for (let i = 0; i < array.length; i++) {
|
|
323
|
+
if (i in array) {
|
|
324
|
+
result.push(get_property(array, i));
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return result[Symbol.iterator]();
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* @template T
|
|
333
|
+
* @param {Array<T>} array
|
|
334
|
+
* @returns {IterableIterator<[number, T]>}
|
|
335
|
+
*/
|
|
336
|
+
export function array_entries(array) {
|
|
337
|
+
// @ts-expect-error
|
|
338
|
+
var tracked_properties = array[TRACKED_OBJECT];
|
|
339
|
+
if (tracked_properties === undefined || array.entries !== array_proto.entries) {
|
|
340
|
+
return array.entries();
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/** @type {Array<[number, T]>} */
|
|
344
|
+
const result = [];
|
|
345
|
+
for (let i = 0; i < array.length; i++) {
|
|
346
|
+
if (i in array) {
|
|
347
|
+
result.push([i, get_property(array, i)]);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
return result[Symbol.iterator]();
|
|
352
|
+
}
|
|
@@ -46,6 +46,24 @@ export {
|
|
|
46
46
|
exclude_from_object,
|
|
47
47
|
} from './runtime.js';
|
|
48
48
|
|
|
49
|
+
export {
|
|
50
|
+
array_reduce,
|
|
51
|
+
array_join,
|
|
52
|
+
array_map,
|
|
53
|
+
array_filter,
|
|
54
|
+
array_forEach,
|
|
55
|
+
array_includes,
|
|
56
|
+
array_indexOf,
|
|
57
|
+
array_lastIndexOf,
|
|
58
|
+
array_every,
|
|
59
|
+
array_some,
|
|
60
|
+
array_toString,
|
|
61
|
+
array_toSorted,
|
|
62
|
+
array_toSpliced,
|
|
63
|
+
array_values,
|
|
64
|
+
array_entries,
|
|
65
|
+
} from './array.js';
|
|
66
|
+
|
|
49
67
|
export { for_block as for } from './for.js';
|
|
50
68
|
|
|
51
69
|
export { if_block as if } from './if.js';
|
package/tests/basic.test.ripple
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import { mount, flushSync } from 'ripple';
|
|
2
|
+
import { mount, flushSync, effect } from 'ripple';
|
|
3
3
|
|
|
4
4
|
describe('basic', () => {
|
|
5
5
|
let container;
|
|
@@ -832,4 +832,70 @@ describe('basic', () => {
|
|
|
832
832
|
expect(paragraphs[0].className).toBe('parent-class');
|
|
833
833
|
expect(paragraphs[1].className).toBe('nested-class');
|
|
834
834
|
});
|
|
835
|
+
|
|
836
|
+
it('basic reactivity with standard arrays should work', () => {
|
|
837
|
+
let logs = [];
|
|
838
|
+
|
|
839
|
+
component App() {
|
|
840
|
+
let $first = 0;
|
|
841
|
+
let $second = 0;
|
|
842
|
+
const arr = [$first, $second];
|
|
843
|
+
|
|
844
|
+
const $total = arr.reduce((a, b) => a + b, 0);
|
|
845
|
+
|
|
846
|
+
<button onClick={() => { $first++; }}>{'first:' + $first}</button>
|
|
847
|
+
<button onClick={() => { $second++; }}>{'second: ' + $second}</button>
|
|
848
|
+
|
|
849
|
+
effect(() => {
|
|
850
|
+
let _arr = [];
|
|
851
|
+
|
|
852
|
+
arr.forEach((item) => {
|
|
853
|
+
_arr.push(item);
|
|
854
|
+
});
|
|
855
|
+
|
|
856
|
+
logs.push(_arr.join(', '));
|
|
857
|
+
});
|
|
858
|
+
|
|
859
|
+
effect(() => {
|
|
860
|
+
if (arr.includes(1)) {
|
|
861
|
+
logs.push('arr includes 1');
|
|
862
|
+
}
|
|
863
|
+
});
|
|
864
|
+
|
|
865
|
+
<div>{'Sum: ' + $total}</div>
|
|
866
|
+
<div>{'Comma Separated: ' + arr.join(', ')}</div>
|
|
867
|
+
<div>{'Number to string: ' + arr.map(a => String(a))}</div>
|
|
868
|
+
<div>{'Even numbers: ' + arr.filter(a => a % 2 === 0)}</div>
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
render(App);
|
|
872
|
+
flushSync();
|
|
873
|
+
|
|
874
|
+
const buttons = container.querySelectorAll('button');
|
|
875
|
+
const divs = container.querySelectorAll('div');
|
|
876
|
+
|
|
877
|
+
expect(divs[0].textContent).toBe('Sum: 0');
|
|
878
|
+
expect(divs[1].textContent).toBe('Comma Separated: 0, 0');
|
|
879
|
+
expect(divs[2].textContent).toBe('Number to string: 0,0');
|
|
880
|
+
expect(divs[3].textContent).toBe('Even numbers: 0,0');
|
|
881
|
+
expect(logs).toEqual(['0, 0']);
|
|
882
|
+
|
|
883
|
+
buttons[0].click();
|
|
884
|
+
flushSync();
|
|
885
|
+
|
|
886
|
+
expect(divs[0].textContent).toBe('Sum: 1');
|
|
887
|
+
expect(divs[1].textContent).toBe('Comma Separated: 1, 0');
|
|
888
|
+
expect(divs[2].textContent).toBe('Number to string: 1,0');
|
|
889
|
+
expect(divs[3].textContent).toBe('Even numbers: 0');
|
|
890
|
+
expect(logs).toEqual(['0, 0', '1, 0', 'arr includes 1']);
|
|
891
|
+
|
|
892
|
+
buttons[1].click();
|
|
893
|
+
flushSync();
|
|
894
|
+
|
|
895
|
+
expect(divs[0].textContent).toBe('Sum: 2');
|
|
896
|
+
expect(divs[1].textContent).toBe('Comma Separated: 1, 1');
|
|
897
|
+
expect(divs[2].textContent).toBe('Number to string: 1,1');
|
|
898
|
+
expect(divs[3].textContent).toBe('Even numbers: ');
|
|
899
|
+
expect(logs).toEqual(['0, 0', '1, 0', 'arr includes 1', '1, 1']);
|
|
900
|
+
})
|
|
835
901
|
});
|