onejs-react 0.1.0 → 0.1.2
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 +265 -0
- package/package.json +3 -1
- package/src/__tests__/components.test.tsx +36 -0
- package/src/__tests__/host-config.test.ts +141 -99
- package/src/__tests__/mocks.ts +17 -1
- package/src/__tests__/setup.ts +23 -11
- package/src/components.tsx +77 -48
- package/src/error-boundary.tsx +175 -0
- package/src/host-config.ts +503 -162
- package/src/index.ts +46 -2
- package/src/renderer.ts +50 -23
- package/src/screen.tsx +1 -1
- package/src/style-parser.ts +171 -79
- package/src/types.ts +326 -8
- package/src/vector.ts +312 -0
|
@@ -10,9 +10,17 @@
|
|
|
10
10
|
* - Child management (appendChild, insertBefore, removeChild)
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import { describe, it, expect, vi
|
|
14
|
-
import { hostConfig, type Instance } from
|
|
15
|
-
import { MockVisualElement, MockLength, MockColor, getEventAPI
|
|
13
|
+
import { describe, it, expect, vi } from "vitest";
|
|
14
|
+
import { hostConfig, type Instance } from "../host-config";
|
|
15
|
+
import { MockVisualElement, MockLength, MockColor, getEventAPI } from "./mocks";
|
|
16
|
+
import type { BaseProps } from "../types";
|
|
17
|
+
|
|
18
|
+
// Props type that includes component-specific properties for testing
|
|
19
|
+
type TestProps = BaseProps & {
|
|
20
|
+
text?: string;
|
|
21
|
+
value?: unknown;
|
|
22
|
+
label?: string;
|
|
23
|
+
};
|
|
16
24
|
|
|
17
25
|
// Helper to extract value from style (handles both raw values and MockLength/MockColor)
|
|
18
26
|
function getStyleValue(style: unknown): unknown {
|
|
@@ -21,10 +29,43 @@ function getStyleValue(style: unknown): unknown {
|
|
|
21
29
|
return style;
|
|
22
30
|
}
|
|
23
31
|
|
|
32
|
+
// Type-safe wrapper for createInstance (accepts extra args for backward compat)
|
|
33
|
+
function createInstance(type: string, props: TestProps, ..._extra: unknown[]): Instance {
|
|
34
|
+
return hostConfig.createInstance(type, props as BaseProps, {} as any, null as any, null);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Type-safe wrapper for commitUpdate (accepts extra args for backward compat)
|
|
38
|
+
function commitUpdate(instance: Instance, type: string, oldProps: TestProps, newProps: TestProps, ..._extra: unknown[]): void {
|
|
39
|
+
(hostConfig.commitUpdate as any)(instance, type, oldProps as BaseProps, newProps as BaseProps, null);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Type-safe wrapper to get element as MockVisualElement for assertions
|
|
43
|
+
function getMockElement(instance: Instance): MockVisualElement {
|
|
44
|
+
return instance.element as unknown as MockVisualElement;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Type-safe wrappers for hostConfig methods that may be undefined
|
|
48
|
+
const appendChild = hostConfig.appendChild!;
|
|
49
|
+
const appendInitialChild = hostConfig.appendInitialChild!;
|
|
50
|
+
const insertBefore = hostConfig.insertBefore!;
|
|
51
|
+
const removeChild = hostConfig.removeChild!;
|
|
52
|
+
const appendChildToContainer = hostConfig.appendChildToContainer!;
|
|
53
|
+
const removeChildFromContainer = hostConfig.removeChildFromContainer!;
|
|
54
|
+
const clearContainer = hostConfig.clearContainer!;
|
|
55
|
+
const hideInstance = hostConfig.hideInstance!;
|
|
56
|
+
const unhideInstance = hostConfig.unhideInstance!;
|
|
57
|
+
const commitTextUpdate = hostConfig.commitTextUpdate!;
|
|
58
|
+
const prepareUpdate = hostConfig.prepareUpdate!;
|
|
59
|
+
|
|
60
|
+
// Type-safe wrapper for createTextInstance
|
|
61
|
+
function createTextInstance(text: string): Instance {
|
|
62
|
+
return hostConfig.createTextInstance(text, {} as any, null as any, null as any);
|
|
63
|
+
}
|
|
64
|
+
|
|
24
65
|
describe('host-config', () => {
|
|
25
66
|
describe('createInstance', () => {
|
|
26
67
|
it('creates a VisualElement for ojs-view', () => {
|
|
27
|
-
const instance =
|
|
68
|
+
const instance = createInstance('ojs-view', {});
|
|
28
69
|
|
|
29
70
|
expect(instance).toBeDefined();
|
|
30
71
|
expect(instance.type).toBe('ojs-view');
|
|
@@ -34,28 +75,28 @@ describe('host-config', () => {
|
|
|
34
75
|
});
|
|
35
76
|
|
|
36
77
|
it('creates a Label for ojs-label', () => {
|
|
37
|
-
const instance =
|
|
78
|
+
const instance = createInstance('ojs-label', { text: 'Hello' });
|
|
38
79
|
|
|
39
80
|
expect(instance.type).toBe('ojs-label');
|
|
40
81
|
expect(instance.element.text).toBe('Hello');
|
|
41
82
|
});
|
|
42
83
|
|
|
43
84
|
it('creates a Button for ojs-button', () => {
|
|
44
|
-
const instance =
|
|
85
|
+
const instance = createInstance('ojs-button', { text: 'Click me' });
|
|
45
86
|
|
|
46
87
|
expect(instance.type).toBe('ojs-button');
|
|
47
88
|
expect(instance.element.text).toBe('Click me');
|
|
48
89
|
});
|
|
49
90
|
|
|
50
91
|
it('creates a TextField for ojs-textfield', () => {
|
|
51
|
-
const instance =
|
|
92
|
+
const instance = createInstance('ojs-textfield', { value: 'test' });
|
|
52
93
|
|
|
53
94
|
expect(instance.type).toBe('ojs-textfield');
|
|
54
95
|
expect(instance.element.value).toBe('test');
|
|
55
96
|
});
|
|
56
97
|
|
|
57
98
|
it('creates a Toggle for ojs-toggle', () => {
|
|
58
|
-
const instance =
|
|
99
|
+
const instance = createInstance('ojs-toggle', { value: true, label: 'Enable' });
|
|
59
100
|
|
|
60
101
|
expect(instance.type).toBe('ojs-toggle');
|
|
61
102
|
expect(instance.element.value).toBe(true);
|
|
@@ -64,14 +105,14 @@ describe('host-config', () => {
|
|
|
64
105
|
|
|
65
106
|
it('throws for unknown element type', () => {
|
|
66
107
|
expect(() => {
|
|
67
|
-
|
|
108
|
+
createInstance('unknown-type', {});
|
|
68
109
|
}).toThrow('Unknown element type: unknown-type');
|
|
69
110
|
});
|
|
70
111
|
});
|
|
71
112
|
|
|
72
113
|
describe('style application', () => {
|
|
73
114
|
it('applies style properties on creation', () => {
|
|
74
|
-
const instance =
|
|
115
|
+
const instance = createInstance(
|
|
75
116
|
'ojs-view',
|
|
76
117
|
{ style: { width: 100, height: 50, backgroundColor: 'red' } },
|
|
77
118
|
null as any,
|
|
@@ -87,7 +128,7 @@ describe('host-config', () => {
|
|
|
87
128
|
});
|
|
88
129
|
|
|
89
130
|
it('tracks applied style keys', () => {
|
|
90
|
-
const instance =
|
|
131
|
+
const instance = createInstance(
|
|
91
132
|
'ojs-view',
|
|
92
133
|
{ style: { width: 100, height: 50 } },
|
|
93
134
|
null as any,
|
|
@@ -101,7 +142,7 @@ describe('host-config', () => {
|
|
|
101
142
|
});
|
|
102
143
|
|
|
103
144
|
it('expands shorthand padding to individual properties', () => {
|
|
104
|
-
const instance =
|
|
145
|
+
const instance = createInstance(
|
|
105
146
|
'ojs-view',
|
|
106
147
|
{ style: { padding: 10 } },
|
|
107
148
|
null as any,
|
|
@@ -117,7 +158,7 @@ describe('host-config', () => {
|
|
|
117
158
|
});
|
|
118
159
|
|
|
119
160
|
it('expands shorthand margin to individual properties', () => {
|
|
120
|
-
const instance =
|
|
161
|
+
const instance = createInstance(
|
|
121
162
|
'ojs-view',
|
|
122
163
|
{ style: { margin: 20 } },
|
|
123
164
|
null as any,
|
|
@@ -132,7 +173,7 @@ describe('host-config', () => {
|
|
|
132
173
|
});
|
|
133
174
|
|
|
134
175
|
it('expands shorthand borderRadius', () => {
|
|
135
|
-
const instance =
|
|
176
|
+
const instance = createInstance(
|
|
136
177
|
'ojs-view',
|
|
137
178
|
{ style: { borderRadius: 8 } },
|
|
138
179
|
null as any,
|
|
@@ -149,7 +190,7 @@ describe('host-config', () => {
|
|
|
149
190
|
|
|
150
191
|
describe('style updates (commitUpdate)', () => {
|
|
151
192
|
it('updates style properties', () => {
|
|
152
|
-
const instance =
|
|
193
|
+
const instance = createInstance(
|
|
153
194
|
'ojs-view',
|
|
154
195
|
{ style: { width: 100 } },
|
|
155
196
|
null as any,
|
|
@@ -158,7 +199,7 @@ describe('host-config', () => {
|
|
|
158
199
|
);
|
|
159
200
|
|
|
160
201
|
// Simulate React calling commitUpdate
|
|
161
|
-
|
|
202
|
+
commitUpdate(
|
|
162
203
|
instance,
|
|
163
204
|
'ojs-view',
|
|
164
205
|
{ style: { width: 100 } },
|
|
@@ -170,7 +211,7 @@ describe('host-config', () => {
|
|
|
170
211
|
});
|
|
171
212
|
|
|
172
213
|
it('clears removed style properties', () => {
|
|
173
|
-
const instance =
|
|
214
|
+
const instance = createInstance(
|
|
174
215
|
'ojs-view',
|
|
175
216
|
{ style: { width: 100, height: 50, backgroundColor: 'red' } },
|
|
176
217
|
null as any,
|
|
@@ -179,7 +220,7 @@ describe('host-config', () => {
|
|
|
179
220
|
);
|
|
180
221
|
|
|
181
222
|
// Update: remove width and backgroundColor, keep height
|
|
182
|
-
|
|
223
|
+
commitUpdate(
|
|
183
224
|
instance,
|
|
184
225
|
'ojs-view',
|
|
185
226
|
{ style: { width: 100, height: 50, backgroundColor: 'red' } },
|
|
@@ -193,7 +234,7 @@ describe('host-config', () => {
|
|
|
193
234
|
});
|
|
194
235
|
|
|
195
236
|
it('clears expanded shorthand properties when shorthand is removed', () => {
|
|
196
|
-
const instance =
|
|
237
|
+
const instance = createInstance(
|
|
197
238
|
'ojs-view',
|
|
198
239
|
{ style: { padding: 10, width: 100 } },
|
|
199
240
|
null as any,
|
|
@@ -202,7 +243,7 @@ describe('host-config', () => {
|
|
|
202
243
|
);
|
|
203
244
|
|
|
204
245
|
// Remove padding shorthand
|
|
205
|
-
|
|
246
|
+
commitUpdate(
|
|
206
247
|
instance,
|
|
207
248
|
'ojs-view',
|
|
208
249
|
{ style: { padding: 10, width: 100 } },
|
|
@@ -218,7 +259,7 @@ describe('host-config', () => {
|
|
|
218
259
|
});
|
|
219
260
|
|
|
220
261
|
it('clears all styles when style prop becomes undefined', () => {
|
|
221
|
-
const instance =
|
|
262
|
+
const instance = createInstance(
|
|
222
263
|
'ojs-view',
|
|
223
264
|
{ style: { width: 100, height: 50 } },
|
|
224
265
|
null as any,
|
|
@@ -226,7 +267,7 @@ describe('host-config', () => {
|
|
|
226
267
|
null
|
|
227
268
|
);
|
|
228
269
|
|
|
229
|
-
|
|
270
|
+
commitUpdate(
|
|
230
271
|
instance,
|
|
231
272
|
'ojs-view',
|
|
232
273
|
{ style: { width: 100, height: 50 } },
|
|
@@ -239,7 +280,7 @@ describe('host-config', () => {
|
|
|
239
280
|
});
|
|
240
281
|
|
|
241
282
|
it('updates appliedStyleKeys after style change', () => {
|
|
242
|
-
const instance =
|
|
283
|
+
const instance = createInstance(
|
|
243
284
|
'ojs-view',
|
|
244
285
|
{ style: { width: 100 } },
|
|
245
286
|
null as any,
|
|
@@ -250,7 +291,7 @@ describe('host-config', () => {
|
|
|
250
291
|
expect(instance.appliedStyleKeys.has('width')).toBe(true);
|
|
251
292
|
expect(instance.appliedStyleKeys.has('height')).toBe(false);
|
|
252
293
|
|
|
253
|
-
|
|
294
|
+
commitUpdate(
|
|
254
295
|
instance,
|
|
255
296
|
'ojs-view',
|
|
256
297
|
{ style: { width: 100 } },
|
|
@@ -265,7 +306,7 @@ describe('host-config', () => {
|
|
|
265
306
|
|
|
266
307
|
describe('className management', () => {
|
|
267
308
|
it('applies className on creation', () => {
|
|
268
|
-
const instance =
|
|
309
|
+
const instance = createInstance(
|
|
269
310
|
'ojs-view',
|
|
270
311
|
{ className: 'foo bar' },
|
|
271
312
|
null as any,
|
|
@@ -273,13 +314,13 @@ describe('host-config', () => {
|
|
|
273
314
|
null
|
|
274
315
|
);
|
|
275
316
|
|
|
276
|
-
const el = instance
|
|
317
|
+
const el = getMockElement(instance);
|
|
277
318
|
expect(el.hasClass('foo')).toBe(true);
|
|
278
319
|
expect(el.hasClass('bar')).toBe(true);
|
|
279
320
|
});
|
|
280
321
|
|
|
281
322
|
it('handles multiple spaces in className', () => {
|
|
282
|
-
const instance =
|
|
323
|
+
const instance = createInstance(
|
|
283
324
|
'ojs-view',
|
|
284
325
|
{ className: 'foo bar baz' },
|
|
285
326
|
null as any,
|
|
@@ -287,14 +328,14 @@ describe('host-config', () => {
|
|
|
287
328
|
null
|
|
288
329
|
);
|
|
289
330
|
|
|
290
|
-
const el = instance
|
|
331
|
+
const el = getMockElement(instance);
|
|
291
332
|
expect(el.hasClass('foo')).toBe(true);
|
|
292
333
|
expect(el.hasClass('bar')).toBe(true);
|
|
293
334
|
expect(el.hasClass('baz')).toBe(true);
|
|
294
335
|
});
|
|
295
336
|
|
|
296
337
|
it('selectively adds new classes on update', () => {
|
|
297
|
-
const instance =
|
|
338
|
+
const instance = createInstance(
|
|
298
339
|
'ojs-view',
|
|
299
340
|
{ className: 'foo bar' },
|
|
300
341
|
null as any,
|
|
@@ -302,7 +343,7 @@ describe('host-config', () => {
|
|
|
302
343
|
null
|
|
303
344
|
);
|
|
304
345
|
|
|
305
|
-
|
|
346
|
+
commitUpdate(
|
|
306
347
|
instance,
|
|
307
348
|
'ojs-view',
|
|
308
349
|
{ className: 'foo bar' },
|
|
@@ -310,14 +351,14 @@ describe('host-config', () => {
|
|
|
310
351
|
null as any
|
|
311
352
|
);
|
|
312
353
|
|
|
313
|
-
const el = instance
|
|
354
|
+
const el = getMockElement(instance);
|
|
314
355
|
expect(el.hasClass('foo')).toBe(true);
|
|
315
356
|
expect(el.hasClass('bar')).toBe(true);
|
|
316
357
|
expect(el.hasClass('baz')).toBe(true);
|
|
317
358
|
});
|
|
318
359
|
|
|
319
360
|
it('selectively removes old classes on update', () => {
|
|
320
|
-
const instance =
|
|
361
|
+
const instance = createInstance(
|
|
321
362
|
'ojs-view',
|
|
322
363
|
{ className: 'foo bar baz' },
|
|
323
364
|
null as any,
|
|
@@ -325,7 +366,7 @@ describe('host-config', () => {
|
|
|
325
366
|
null
|
|
326
367
|
);
|
|
327
368
|
|
|
328
|
-
|
|
369
|
+
commitUpdate(
|
|
329
370
|
instance,
|
|
330
371
|
'ojs-view',
|
|
331
372
|
{ className: 'foo bar baz' },
|
|
@@ -333,14 +374,14 @@ describe('host-config', () => {
|
|
|
333
374
|
null as any
|
|
334
375
|
);
|
|
335
376
|
|
|
336
|
-
const el = instance
|
|
377
|
+
const el = getMockElement(instance);
|
|
337
378
|
expect(el.hasClass('foo')).toBe(true);
|
|
338
379
|
expect(el.hasClass('bar')).toBe(false);
|
|
339
380
|
expect(el.hasClass('baz')).toBe(false);
|
|
340
381
|
});
|
|
341
382
|
|
|
342
383
|
it('handles complete className replacement', () => {
|
|
343
|
-
const instance =
|
|
384
|
+
const instance = createInstance(
|
|
344
385
|
'ojs-view',
|
|
345
386
|
{ className: 'old-class' },
|
|
346
387
|
null as any,
|
|
@@ -348,7 +389,7 @@ describe('host-config', () => {
|
|
|
348
389
|
null
|
|
349
390
|
);
|
|
350
391
|
|
|
351
|
-
|
|
392
|
+
commitUpdate(
|
|
352
393
|
instance,
|
|
353
394
|
'ojs-view',
|
|
354
395
|
{ className: 'old-class' },
|
|
@@ -356,13 +397,13 @@ describe('host-config', () => {
|
|
|
356
397
|
null as any
|
|
357
398
|
);
|
|
358
399
|
|
|
359
|
-
const el = instance
|
|
400
|
+
const el = getMockElement(instance);
|
|
360
401
|
expect(el.hasClass('old-class')).toBe(false);
|
|
361
402
|
expect(el.hasClass('new-class')).toBe(true);
|
|
362
403
|
});
|
|
363
404
|
|
|
364
405
|
it('removes all classes when className becomes undefined', () => {
|
|
365
|
-
const instance =
|
|
406
|
+
const instance = createInstance(
|
|
366
407
|
'ojs-view',
|
|
367
408
|
{ className: 'foo bar' },
|
|
368
409
|
null as any,
|
|
@@ -370,7 +411,7 @@ describe('host-config', () => {
|
|
|
370
411
|
null
|
|
371
412
|
);
|
|
372
413
|
|
|
373
|
-
|
|
414
|
+
commitUpdate(
|
|
374
415
|
instance,
|
|
375
416
|
'ojs-view',
|
|
376
417
|
{ className: 'foo bar' },
|
|
@@ -378,7 +419,7 @@ describe('host-config', () => {
|
|
|
378
419
|
null as any
|
|
379
420
|
);
|
|
380
421
|
|
|
381
|
-
const el = instance
|
|
422
|
+
const el = getMockElement(instance);
|
|
382
423
|
expect(el.hasClass('foo')).toBe(false);
|
|
383
424
|
expect(el.hasClass('bar')).toBe(false);
|
|
384
425
|
});
|
|
@@ -387,7 +428,7 @@ describe('host-config', () => {
|
|
|
387
428
|
describe('event handlers', () => {
|
|
388
429
|
it('registers onClick handler on creation', () => {
|
|
389
430
|
const handler = vi.fn();
|
|
390
|
-
const instance =
|
|
431
|
+
const instance = createInstance(
|
|
391
432
|
'ojs-button',
|
|
392
433
|
{ onClick: handler },
|
|
393
434
|
null as any,
|
|
@@ -407,7 +448,7 @@ describe('host-config', () => {
|
|
|
407
448
|
it('registers multiple event handlers', () => {
|
|
408
449
|
const onClick = vi.fn();
|
|
409
450
|
const onPointerDown = vi.fn();
|
|
410
|
-
const instance =
|
|
451
|
+
const instance = createInstance(
|
|
411
452
|
'ojs-view',
|
|
412
453
|
{ onClick, onPointerDown },
|
|
413
454
|
null as any,
|
|
@@ -430,7 +471,7 @@ describe('host-config', () => {
|
|
|
430
471
|
|
|
431
472
|
it('removes event handler on update', () => {
|
|
432
473
|
const handler = vi.fn();
|
|
433
|
-
const instance =
|
|
474
|
+
const instance = createInstance(
|
|
434
475
|
'ojs-button',
|
|
435
476
|
{ onClick: handler },
|
|
436
477
|
null as any,
|
|
@@ -443,7 +484,7 @@ describe('host-config', () => {
|
|
|
443
484
|
eventAPI.addEventListener.mockClear();
|
|
444
485
|
eventAPI.removeEventListener.mockClear();
|
|
445
486
|
|
|
446
|
-
|
|
487
|
+
commitUpdate(
|
|
447
488
|
instance,
|
|
448
489
|
'ojs-button',
|
|
449
490
|
{ onClick: handler },
|
|
@@ -462,7 +503,7 @@ describe('host-config', () => {
|
|
|
462
503
|
it('replaces event handler on update', () => {
|
|
463
504
|
const oldHandler = vi.fn();
|
|
464
505
|
const newHandler = vi.fn();
|
|
465
|
-
const instance =
|
|
506
|
+
const instance = createInstance(
|
|
466
507
|
'ojs-button',
|
|
467
508
|
{ onClick: oldHandler },
|
|
468
509
|
null as any,
|
|
@@ -474,7 +515,7 @@ describe('host-config', () => {
|
|
|
474
515
|
eventAPI.addEventListener.mockClear();
|
|
475
516
|
eventAPI.removeEventListener.mockClear();
|
|
476
517
|
|
|
477
|
-
|
|
518
|
+
commitUpdate(
|
|
478
519
|
instance,
|
|
479
520
|
'ojs-button',
|
|
480
521
|
{ onClick: oldHandler },
|
|
@@ -498,63 +539,63 @@ describe('host-config', () => {
|
|
|
498
539
|
|
|
499
540
|
describe('child management', () => {
|
|
500
541
|
it('appendChild adds child to parent', () => {
|
|
501
|
-
const parent =
|
|
502
|
-
const child =
|
|
542
|
+
const parent = createInstance('ojs-view', {});
|
|
543
|
+
const child = createInstance('ojs-label', { text: 'Hello' });
|
|
503
544
|
|
|
504
|
-
|
|
545
|
+
appendChild(parent, child);
|
|
505
546
|
|
|
506
|
-
const parentEl = parent
|
|
547
|
+
const parentEl = getMockElement(parent);
|
|
507
548
|
expect(parentEl.children).toContain(child.element);
|
|
508
549
|
});
|
|
509
550
|
|
|
510
551
|
it('appendInitialChild adds child during initial render', () => {
|
|
511
|
-
const parent =
|
|
512
|
-
const child =
|
|
552
|
+
const parent = createInstance('ojs-view', {});
|
|
553
|
+
const child = createInstance('ojs-label', {});
|
|
513
554
|
|
|
514
|
-
|
|
555
|
+
appendInitialChild(parent, child);
|
|
515
556
|
|
|
516
|
-
const parentEl = parent
|
|
557
|
+
const parentEl = getMockElement(parent);
|
|
517
558
|
expect(parentEl.children).toContain(child.element);
|
|
518
559
|
});
|
|
519
560
|
|
|
520
561
|
it('insertBefore inserts child at correct position', () => {
|
|
521
|
-
const parent =
|
|
522
|
-
const child1 =
|
|
523
|
-
const child2 =
|
|
524
|
-
const child3 =
|
|
562
|
+
const parent = createInstance('ojs-view', {});
|
|
563
|
+
const child1 = createInstance('ojs-label', { text: '1' });
|
|
564
|
+
const child2 = createInstance('ojs-label', { text: '2' });
|
|
565
|
+
const child3 = createInstance('ojs-label', { text: '3' });
|
|
525
566
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
567
|
+
appendChild(parent, child1);
|
|
568
|
+
appendChild(parent, child3);
|
|
569
|
+
insertBefore(parent, child2, child3);
|
|
529
570
|
|
|
530
|
-
const parentEl = parent
|
|
571
|
+
const parentEl = getMockElement(parent);
|
|
531
572
|
expect(parentEl.children[0]).toBe(child1.element);
|
|
532
573
|
expect(parentEl.children[1]).toBe(child2.element);
|
|
533
574
|
expect(parentEl.children[2]).toBe(child3.element);
|
|
534
575
|
});
|
|
535
576
|
|
|
536
577
|
it('removeChild removes child from parent', () => {
|
|
537
|
-
const parent =
|
|
538
|
-
const child =
|
|
578
|
+
const parent = createInstance('ojs-view', {});
|
|
579
|
+
const child = createInstance('ojs-label', {});
|
|
539
580
|
|
|
540
|
-
|
|
541
|
-
|
|
581
|
+
appendChild(parent, child);
|
|
582
|
+
removeChild(parent, child);
|
|
542
583
|
|
|
543
|
-
const parentEl = parent
|
|
584
|
+
const parentEl = getMockElement(parent);
|
|
544
585
|
expect(parentEl.children).not.toContain(child.element);
|
|
545
586
|
});
|
|
546
587
|
|
|
547
588
|
it('removeChild cleans up event listeners', () => {
|
|
548
589
|
const handler = vi.fn();
|
|
549
|
-
const parent =
|
|
550
|
-
const child =
|
|
590
|
+
const parent = createInstance('ojs-view', {});
|
|
591
|
+
const child = createInstance('ojs-button', { onClick: handler });
|
|
551
592
|
|
|
552
|
-
|
|
593
|
+
appendChild(parent, child);
|
|
553
594
|
|
|
554
595
|
const eventAPI = getEventAPI();
|
|
555
596
|
eventAPI.removeAllEventListeners.mockClear();
|
|
556
597
|
|
|
557
|
-
|
|
598
|
+
removeChild(parent, child);
|
|
558
599
|
|
|
559
600
|
expect(eventAPI.removeAllEventListeners).toHaveBeenCalledWith(child.element);
|
|
560
601
|
});
|
|
@@ -563,9 +604,9 @@ describe('host-config', () => {
|
|
|
563
604
|
describe('container operations', () => {
|
|
564
605
|
it('appendChildToContainer adds child to container', () => {
|
|
565
606
|
const container = new MockVisualElement('Container');
|
|
566
|
-
const child =
|
|
607
|
+
const child = createInstance('ojs-view', {});
|
|
567
608
|
|
|
568
|
-
|
|
609
|
+
appendChildToContainer(container as any, child);
|
|
569
610
|
|
|
570
611
|
expect(container.children).toContain(child.element);
|
|
571
612
|
});
|
|
@@ -573,14 +614,14 @@ describe('host-config', () => {
|
|
|
573
614
|
it('removeChildFromContainer removes child and cleans up events', () => {
|
|
574
615
|
const container = new MockVisualElement('Container');
|
|
575
616
|
const handler = vi.fn();
|
|
576
|
-
const child =
|
|
617
|
+
const child = createInstance('ojs-button', { onClick: handler });
|
|
577
618
|
|
|
578
|
-
|
|
619
|
+
appendChildToContainer(container as any, child);
|
|
579
620
|
|
|
580
621
|
const eventAPI = getEventAPI();
|
|
581
622
|
eventAPI.removeAllEventListeners.mockClear();
|
|
582
623
|
|
|
583
|
-
|
|
624
|
+
removeChildFromContainer(container as any, child);
|
|
584
625
|
|
|
585
626
|
expect(container.children).not.toContain(child.element);
|
|
586
627
|
expect(eventAPI.removeAllEventListeners).toHaveBeenCalledWith(child.element);
|
|
@@ -588,33 +629,34 @@ describe('host-config', () => {
|
|
|
588
629
|
|
|
589
630
|
it('clearContainer removes all children', () => {
|
|
590
631
|
const container = new MockVisualElement('Container');
|
|
591
|
-
const child1 =
|
|
592
|
-
const child2 =
|
|
632
|
+
const child1 = createInstance('ojs-view', {});
|
|
633
|
+
const child2 = createInstance('ojs-view', {});
|
|
593
634
|
|
|
594
|
-
|
|
595
|
-
|
|
635
|
+
appendChildToContainer(container as any, child1);
|
|
636
|
+
appendChildToContainer(container as any, child2);
|
|
596
637
|
|
|
597
638
|
expect(container.childCount).toBe(2);
|
|
598
639
|
|
|
599
|
-
|
|
640
|
+
clearContainer(container as any);
|
|
600
641
|
|
|
601
642
|
expect(container.childCount).toBe(0);
|
|
602
643
|
});
|
|
603
644
|
});
|
|
604
645
|
|
|
605
646
|
describe('text instances', () => {
|
|
606
|
-
it('createTextInstance creates a
|
|
607
|
-
const textInstance =
|
|
647
|
+
it('createTextInstance creates a TextElement with text', () => {
|
|
648
|
+
const textInstance = createTextInstance('Hello World');
|
|
608
649
|
|
|
609
650
|
expect(textInstance.type).toBe('text');
|
|
651
|
+
expect(textInstance.element.__csType).toBe('UnityEngine.UIElements.TextElement');
|
|
610
652
|
expect(textInstance.element.text).toBe('Hello World');
|
|
611
653
|
expect(textInstance.appliedStyleKeys).toBeInstanceOf(Set);
|
|
612
654
|
});
|
|
613
655
|
|
|
614
656
|
it('commitTextUpdate updates the text', () => {
|
|
615
|
-
const textInstance =
|
|
657
|
+
const textInstance = createTextInstance('Old text');
|
|
616
658
|
|
|
617
|
-
|
|
659
|
+
commitTextUpdate(textInstance, 'Old text', 'New text');
|
|
618
660
|
|
|
619
661
|
expect(textInstance.element.text).toBe('New text');
|
|
620
662
|
});
|
|
@@ -622,18 +664,18 @@ describe('host-config', () => {
|
|
|
622
664
|
|
|
623
665
|
describe('visibility', () => {
|
|
624
666
|
it('hideInstance sets display to none', () => {
|
|
625
|
-
const instance =
|
|
667
|
+
const instance = createInstance('ojs-view', {});
|
|
626
668
|
|
|
627
|
-
|
|
669
|
+
hideInstance(instance);
|
|
628
670
|
|
|
629
671
|
expect(instance.element.style.display).toBe('none');
|
|
630
672
|
});
|
|
631
673
|
|
|
632
674
|
it('unhideInstance clears display', () => {
|
|
633
|
-
const instance =
|
|
675
|
+
const instance = createInstance('ojs-view', {});
|
|
634
676
|
instance.element.style.display = 'none';
|
|
635
677
|
|
|
636
|
-
|
|
678
|
+
unhideInstance(instance, {});
|
|
637
679
|
|
|
638
680
|
expect(instance.element.style.display).toBe('');
|
|
639
681
|
});
|
|
@@ -641,15 +683,15 @@ describe('host-config', () => {
|
|
|
641
683
|
|
|
642
684
|
describe('prepareUpdate', () => {
|
|
643
685
|
it('returns true when props differ', () => {
|
|
644
|
-
const instance =
|
|
686
|
+
const instance = createInstance('ojs-view', { style: { width: 100 } });
|
|
645
687
|
|
|
646
|
-
const result =
|
|
688
|
+
const result = prepareUpdate(
|
|
647
689
|
instance,
|
|
648
690
|
'ojs-view',
|
|
649
|
-
{ style: { width: 100 } },
|
|
650
|
-
{ style: { width: 200 } },
|
|
691
|
+
{ style: { width: 100 } } as BaseProps,
|
|
692
|
+
{ style: { width: 200 } } as BaseProps,
|
|
651
693
|
null as any,
|
|
652
|
-
null
|
|
694
|
+
null as any
|
|
653
695
|
);
|
|
654
696
|
|
|
655
697
|
expect(result).toBe(true);
|
|
@@ -657,15 +699,15 @@ describe('host-config', () => {
|
|
|
657
699
|
|
|
658
700
|
it('returns null when props are same reference', () => {
|
|
659
701
|
const props = { style: { width: 100 } };
|
|
660
|
-
const instance =
|
|
702
|
+
const instance = createInstance('ojs-view', props);
|
|
661
703
|
|
|
662
|
-
const result =
|
|
704
|
+
const result = prepareUpdate(
|
|
663
705
|
instance,
|
|
664
706
|
'ojs-view',
|
|
665
|
-
props,
|
|
666
|
-
props,
|
|
707
|
+
props as BaseProps,
|
|
708
|
+
props as BaseProps,
|
|
667
709
|
null as any,
|
|
668
|
-
null
|
|
710
|
+
null as any
|
|
669
711
|
);
|
|
670
712
|
|
|
671
713
|
expect(result).toBeNull();
|