@rezi-ui/testkit 0.1.0-alpha.1

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.
Files changed (86) hide show
  1. package/README.md +8 -0
  2. package/dist/__tests__/fixtures.test.d.ts +2 -0
  3. package/dist/__tests__/fixtures.test.d.ts.map +1 -0
  4. package/dist/__tests__/fixtures.test.js +7 -0
  5. package/dist/__tests__/fixtures.test.js.map +1 -0
  6. package/dist/__tests__/golden.test.d.ts +2 -0
  7. package/dist/__tests__/golden.test.d.ts.map +1 -0
  8. package/dist/__tests__/golden.test.js +22 -0
  9. package/dist/__tests__/golden.test.js.map +1 -0
  10. package/dist/__tests__/rng.test.d.ts +2 -0
  11. package/dist/__tests__/rng.test.d.ts.map +1 -0
  12. package/dist/__tests__/rng.test.js +33 -0
  13. package/dist/__tests__/rng.test.js.map +1 -0
  14. package/dist/__tests__/test-runner-smoke.test.d.ts +2 -0
  15. package/dist/__tests__/test-runner-smoke.test.d.ts.map +1 -0
  16. package/dist/__tests__/test-runner-smoke.test.js +5 -0
  17. package/dist/__tests__/test-runner-smoke.test.js.map +1 -0
  18. package/dist/fixtures.d.ts +2 -0
  19. package/dist/fixtures.d.ts.map +1 -0
  20. package/dist/fixtures.js +19 -0
  21. package/dist/fixtures.js.map +1 -0
  22. package/dist/golden.d.ts +7 -0
  23. package/dist/golden.d.ts.map +1 -0
  24. package/dist/golden.js +75 -0
  25. package/dist/golden.js.map +1 -0
  26. package/dist/index.d.ts +5 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +5 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/nodeTest.d.ts +4 -0
  31. package/dist/nodeTest.d.ts.map +1 -0
  32. package/dist/nodeTest.js +4 -0
  33. package/dist/nodeTest.js.map +1 -0
  34. package/dist/rng.d.ts +6 -0
  35. package/dist/rng.d.ts.map +1 -0
  36. package/dist/rng.js +43 -0
  37. package/dist/rng.js.map +1 -0
  38. package/fixtures/README.md +99 -0
  39. package/fixtures/__selftest__/hello.bin +1 -0
  40. package/fixtures/focus/.gitkeep +1 -0
  41. package/fixtures/focus/focus_list.json +68 -0
  42. package/fixtures/layout/hit_test_cases.json +93 -0
  43. package/fixtures/layout/hit_test_ties.json +43 -0
  44. package/fixtures/layout/layout_cases.json +138 -0
  45. package/fixtures/routing/.gitkeep +1 -0
  46. package/fixtures/routing/input_editing.json +316 -0
  47. package/fixtures/routing/key_routing.json +81 -0
  48. package/fixtures/routing/mouse_routing.json +167 -0
  49. package/fixtures/text-measure/graphemes.json +18 -0
  50. package/fixtures/text-measure/invalid-surrogates.json +12 -0
  51. package/fixtures/text-measure/strings.json +15 -0
  52. package/fixtures/zrdl-v1/.gitkeep +1 -0
  53. package/fixtures/zrdl-v1/README.md +78 -0
  54. package/fixtures/zrdl-v1/golden/clear_only.bin +0 -0
  55. package/fixtures/zrdl-v1/golden/clip_nested.bin +0 -0
  56. package/fixtures/zrdl-v1/golden/draw_text_interned.bin +0 -0
  57. package/fixtures/zrdl-v1/golden/fill_rect.bin +0 -0
  58. package/fixtures/zrdl-v1/ink-compat/border_styles.bin +0 -0
  59. package/fixtures/zrdl-v1/ink-compat/box_layout.bin +0 -0
  60. package/fixtures/zrdl-v1/ink-compat/flex_layout.bin +0 -0
  61. package/fixtures/zrdl-v1/ink-compat/simple_text.bin +0 -0
  62. package/fixtures/zrdl-v1/widgets/box_with_title.bin +0 -0
  63. package/fixtures/zrdl-v1/widgets/button_focus_states.bin +0 -0
  64. package/fixtures/zrdl-v1/widgets/divider_horizontal.bin +0 -0
  65. package/fixtures/zrdl-v1/widgets/divider_with_label.bin +0 -0
  66. package/fixtures/zrdl-v1/widgets/input_basic.bin +0 -0
  67. package/fixtures/zrdl-v1/widgets/input_disabled.bin +0 -0
  68. package/fixtures/zrdl-v1/widgets/input_focused_inverse.bin +0 -0
  69. package/fixtures/zrdl-v1/widgets/text_in_stack.bin +0 -0
  70. package/fixtures/zrev-v1/.gitkeep +1 -0
  71. package/fixtures/zrev-v1/README.md +102 -0
  72. package/fixtures/zrev-v1/invalid/bad_magic.bin +0 -0
  73. package/fixtures/zrev-v1/invalid/bad_version.bin +0 -0
  74. package/fixtures/zrev-v1/invalid/misaligned_record_size.bin +0 -0
  75. package/fixtures/zrev-v1/invalid/total_size_mismatch.bin +0 -0
  76. package/fixtures/zrev-v1/invalid/truncated_header.bin +0 -0
  77. package/fixtures/zrev-v1/invalid/truncated_payload.bin +0 -0
  78. package/fixtures/zrev-v1/invalid/truncated_record_header.bin +0 -0
  79. package/fixtures/zrev-v1/valid/key.bin +0 -0
  80. package/fixtures/zrev-v1/valid/mouse.bin +0 -0
  81. package/fixtures/zrev-v1/valid/paste.bin +0 -0
  82. package/fixtures/zrev-v1/valid/resize.bin +0 -0
  83. package/fixtures/zrev-v1/valid/text.bin +0 -0
  84. package/fixtures/zrev-v1/valid/tick.bin +0 -0
  85. package/fixtures/zrev-v1/valid/user.bin +0 -0
  86. package/package.json +31 -0
@@ -0,0 +1,167 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "cases": [
4
+ {
5
+ "name": "Down captures pressedId + focuses target; up on same target presses (docs/10)",
6
+ "enabledById": { "a": true },
7
+ "initialFocusedId": null,
8
+ "initialPressedId": null,
9
+ "steps": [
10
+ {
11
+ "event": {
12
+ "kind": "mouse",
13
+ "timeMs": 0,
14
+ "x": 1,
15
+ "y": 1,
16
+ "mouseKind": 3,
17
+ "mods": 0,
18
+ "buttons": 1,
19
+ "wheelX": 0,
20
+ "wheelY": 0
21
+ },
22
+ "hitTestTargetId": "a",
23
+ "expected": { "focusedId": "a", "pressedId": "a", "emittedKinds": ["engine"] }
24
+ },
25
+ {
26
+ "event": {
27
+ "kind": "mouse",
28
+ "timeMs": 1,
29
+ "x": 1,
30
+ "y": 1,
31
+ "mouseKind": 4,
32
+ "mods": 0,
33
+ "buttons": 0,
34
+ "wheelX": 0,
35
+ "wheelY": 0
36
+ },
37
+ "hitTestTargetId": "a",
38
+ "expected": {
39
+ "focusedId": "a",
40
+ "pressedId": null,
41
+ "emittedKinds": ["engine", "action"],
42
+ "action": { "id": "a", "action": "press" }
43
+ }
44
+ }
45
+ ]
46
+ },
47
+ {
48
+ "name": "Up on different target does not press; pressedId always clears on up (docs/10)",
49
+ "enabledById": { "a": true, "b": true },
50
+ "initialFocusedId": null,
51
+ "initialPressedId": null,
52
+ "steps": [
53
+ {
54
+ "event": {
55
+ "kind": "mouse",
56
+ "timeMs": 0,
57
+ "x": 1,
58
+ "y": 1,
59
+ "mouseKind": 3,
60
+ "mods": 0,
61
+ "buttons": 1,
62
+ "wheelX": 0,
63
+ "wheelY": 0
64
+ },
65
+ "hitTestTargetId": "a",
66
+ "expected": { "focusedId": "a", "pressedId": "a", "emittedKinds": ["engine"] }
67
+ },
68
+ {
69
+ "event": {
70
+ "kind": "mouse",
71
+ "timeMs": 1,
72
+ "x": 2,
73
+ "y": 1,
74
+ "mouseKind": 4,
75
+ "mods": 0,
76
+ "buttons": 0,
77
+ "wheelX": 0,
78
+ "wheelY": 0
79
+ },
80
+ "hitTestTargetId": "b",
81
+ "expected": { "focusedId": "a", "pressedId": null, "emittedKinds": ["engine"] }
82
+ }
83
+ ]
84
+ },
85
+ {
86
+ "name": "Disabled target does not focus and does not capture (docs/10)",
87
+ "enabledById": { "a": true, "b": false },
88
+ "initialFocusedId": "a",
89
+ "initialPressedId": null,
90
+ "steps": [
91
+ {
92
+ "event": {
93
+ "kind": "mouse",
94
+ "timeMs": 0,
95
+ "x": 1,
96
+ "y": 1,
97
+ "mouseKind": 3,
98
+ "mods": 0,
99
+ "buttons": 1,
100
+ "wheelX": 0,
101
+ "wheelY": 0
102
+ },
103
+ "hitTestTargetId": "b",
104
+ "expected": { "focusedId": "a", "pressedId": null, "emittedKinds": ["engine"] }
105
+ }
106
+ ]
107
+ },
108
+ {
109
+ "name": "Move/drag/wheel ignored and do not change pressedId (docs/10)",
110
+ "enabledById": { "a": true },
111
+ "initialFocusedId": null,
112
+ "initialPressedId": null,
113
+ "steps": [
114
+ {
115
+ "event": {
116
+ "kind": "mouse",
117
+ "timeMs": 0,
118
+ "x": 1,
119
+ "y": 1,
120
+ "mouseKind": 3,
121
+ "mods": 0,
122
+ "buttons": 1,
123
+ "wheelX": 0,
124
+ "wheelY": 0
125
+ },
126
+ "hitTestTargetId": "a",
127
+ "expected": { "focusedId": "a", "pressedId": "a", "emittedKinds": ["engine"] }
128
+ },
129
+ {
130
+ "event": {
131
+ "kind": "mouse",
132
+ "timeMs": 1,
133
+ "x": 2,
134
+ "y": 2,
135
+ "mouseKind": 1,
136
+ "mods": 0,
137
+ "buttons": 1,
138
+ "wheelX": 0,
139
+ "wheelY": 0
140
+ },
141
+ "hitTestTargetId": null,
142
+ "expected": { "focusedId": "a", "pressedId": "a", "emittedKinds": ["engine"] }
143
+ },
144
+ {
145
+ "event": {
146
+ "kind": "mouse",
147
+ "timeMs": 2,
148
+ "x": 2,
149
+ "y": 2,
150
+ "mouseKind": 4,
151
+ "mods": 0,
152
+ "buttons": 0,
153
+ "wheelX": 0,
154
+ "wheelY": 0
155
+ },
156
+ "hitTestTargetId": "a",
157
+ "expected": {
158
+ "focusedId": "a",
159
+ "pressedId": null,
160
+ "emittedKinds": ["engine", "action"],
161
+ "action": { "id": "a", "action": "press" }
162
+ }
163
+ }
164
+ ]
165
+ }
166
+ ]
167
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "cases": [
4
+ { "name": "ascii", "text": "A", "width": 1 },
5
+ { "name": "combining_sequence", "text": "a\u0301", "width": 1 },
6
+ { "name": "combining_mark_alone", "text": "\u0301", "width": 0 },
7
+ { "name": "zwj_alone", "text": "\u200d", "width": 0 },
8
+ { "name": "crlf_cluster", "text": "\r\n", "width": 0 },
9
+ { "name": "emoji_single", "text": "\ud83d\ude00", "width": 2 },
10
+ {
11
+ "name": "emoji_zwj_sequence_family",
12
+ "text": "\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66",
13
+ "width": 2
14
+ },
15
+ { "name": "regional_indicator_pair_flag", "text": "\ud83c\uddfa\ud83c\uddf8", "width": 2 },
16
+ { "name": "cjk_wide", "text": "\u754c", "width": 2 }
17
+ ]
18
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "cases": [
4
+ { "name": "unpaired_high_surrogate", "text": "\ud800", "width": 1 },
5
+ { "name": "unpaired_low_surrogate", "text": "\udc00", "width": 1 },
6
+ { "name": "unpaired_high_then_ascii", "text": "\ud800A", "width": 2 },
7
+ { "name": "ascii_then_unpaired_low_then_ascii", "text": "A\udc00B", "width": 3 },
8
+ { "name": "valid_surrogate_pair_emoji", "text": "\ud83d\ude00", "width": 2 },
9
+ { "name": "broken_pair_high_then_ascii_then_low", "text": "\ud83dA\ude00", "width": 3 },
10
+ { "name": "two_unpaired_high_surrogates", "text": "\ud800\ud800", "width": 2 }
11
+ ]
12
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "cases": [
4
+ { "name": "empty", "text": "", "width": 0 },
5
+ { "name": "ascii_word", "text": "hello", "width": 5 },
6
+ { "name": "tab_not_special", "text": "a\tb", "width": 2 },
7
+ { "name": "newline_not_special", "text": "a\nb", "width": 2 },
8
+ { "name": "crlf_not_special", "text": "a\r\nb", "width": 2 },
9
+ { "name": "cjk_and_ascii", "text": "\u754ca", "width": 3 },
10
+ { "name": "emoji_in_string", "text": "A\ud83d\ude00B", "width": 4 },
11
+ { "name": "combining_clusters", "text": "a\u0301b", "width": 2 },
12
+ { "name": "leading_combining_mark", "text": "\u0301a", "width": 1 },
13
+ { "name": "two_flags", "text": "\ud83c\uddfa\ud83c\uddf8\ud83c\udde8\ud83c\udde6", "width": 4 }
14
+ ]
15
+ }
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,78 @@
1
+ # ZRDL v1 Golden Fixtures
2
+
3
+ These fixtures are **byte-for-byte** golden buffers for the ZRDL v1 drawlist format.
4
+
5
+ Reference: [ZRDL drawlists](../../../../docs/protocol/zrdl.md)
6
+
7
+ They are generated deterministically by `@rezi-ui/core`’s ZRDL v1 builder and are
8
+ checked by unit tests (no auto-update behavior).
9
+
10
+ All integers are little-endian and all sections are 4-byte aligned. Any padding bytes
11
+ are `0x00`.
12
+
13
+ ## Files
14
+
15
+ ### `golden/clear_only.bin`
16
+
17
+ Command sequence:
18
+ 1. `clear()`
19
+
20
+ Header expectations:
21
+ - `cmd_count = 1`
22
+ - `cmd_bytes = 8`
23
+ - `strings_count = 0`, `strings_bytes_len = 0`
24
+ - `blobs_count = 0`, `blobs_bytes_len = 0`
25
+ - `total_size = 72`
26
+
27
+ ---
28
+
29
+ ### `golden/fill_rect.bin`
30
+
31
+ Command sequence:
32
+ 1. `fillRect(1, 2, 3, 4, { fg: { r: 0, g: 255, b: 0 }, bold: true, underline: true })`
33
+
34
+ Header expectations:
35
+ - `cmd_count = 1`
36
+ - `cmd_bytes = 40`
37
+ - `strings_count = 0`, `strings_bytes_len = 0`
38
+ - `blobs_count = 0`, `blobs_bytes_len = 0`
39
+ - `total_size = 104`
40
+
41
+ ---
42
+
43
+ ### `golden/draw_text_interned.bin`
44
+
45
+ Command sequence (tests deterministic string interning by first use):
46
+ 1. `drawText(0, 0, "hello", { fg: { r: 255, g: 255, b: 255 } })`
47
+ 2. `drawText(0, 1, "hello")` (same string; reuses `string_index=0`)
48
+ 3. `drawText(0, 2, "world", { bg: { r: 0, g: 0, b: 255 }, inverse: true })`
49
+
50
+ String table expectations:
51
+ - intern order: `"hello"` (index 0), then `"world"` (index 1)
52
+ - string spans: `[off=0,len=5]`, `[off=5,len=5]`
53
+ - `strings_bytes_len = 10` (`"helloworld"` in UTF-8)
54
+
55
+ Header expectations:
56
+ - `cmd_count = 3`
57
+ - `cmd_bytes = 144`
58
+ - `strings_count = 2`
59
+ - `blobs_count = 0`, `blobs_bytes_len = 0`
60
+ - `total_size = 236` (string bytes padded to 4-byte alignment)
61
+
62
+ ---
63
+
64
+ ### `golden/clip_nested.bin`
65
+
66
+ Command sequence:
67
+ 1. `pushClip(0, 0, 10, 10)`
68
+ 2. `pushClip(1, 1, 8, 8)`
69
+ 3. `fillRect(2, 2, 3, 4, { bg: { r: 255, g: 0, b: 0 }, inverse: true })`
70
+ 4. `popClip()`
71
+ 5. `popClip()`
72
+
73
+ Header expectations:
74
+ - `cmd_count = 5`
75
+ - `cmd_bytes = 104`
76
+ - `strings_count = 0`, `strings_bytes_len = 0`
77
+ - `blobs_count = 0`, `blobs_bytes_len = 0`
78
+ - `total_size = 168`
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,102 @@
1
+ # ZREV v1 Fixtures
2
+
3
+ All fixtures are ZREV v1 event batches as specified by:
4
+ - [Protocol overview](../../../../docs/protocol/index.md)
5
+ - [ZREV event batches](../../../../docs/protocol/zrev.md)
6
+
7
+ Paths are relative to `packages/testkit/fixtures/`.
8
+
9
+ ## Valid
10
+
11
+ Each valid fixture parses with:
12
+ - `ok === true`
13
+ - `value.flags === 0`
14
+ - exactly one decoded event in `value.events`
15
+
16
+ ### `zrev-v1/valid/key.bin`
17
+
18
+ Expected event:
19
+ ```ts
20
+ { kind: "key", timeMs: 1000, key: 23, mods: 3, action: "down" }
21
+ ```
22
+
23
+ ### `zrev-v1/valid/text.bin`
24
+
25
+ Expected event:
26
+ ```ts
27
+ { kind: "text", timeMs: 2000, codepoint: 0x41 }
28
+ ```
29
+
30
+ ### `zrev-v1/valid/paste.bin`
31
+
32
+ Expected event:
33
+ ```ts
34
+ { kind: "paste", timeMs: 3000, bytes: Uint8Array.of(0x68,0x65,0x6c,0x6c,0x6f) } // "hello"
35
+ ```
36
+
37
+ ### `zrev-v1/valid/mouse.bin`
38
+
39
+ Expected event:
40
+ ```ts
41
+ { kind: "mouse", timeMs: 4000, x: 10, y: 5, mouseKind: 1, mods: 0, buttons: 1, wheelX: 0, wheelY: -1 }
42
+ ```
43
+
44
+ ### `zrev-v1/valid/resize.bin`
45
+
46
+ Expected event:
47
+ ```ts
48
+ { kind: "resize", timeMs: 5000, cols: 80, rows: 24 }
49
+ ```
50
+
51
+ ### `zrev-v1/valid/tick.bin`
52
+
53
+ Expected event:
54
+ ```ts
55
+ { kind: "tick", timeMs: 6000, dtMs: 16 }
56
+ ```
57
+
58
+ ### `zrev-v1/valid/user.bin`
59
+
60
+ Expected event:
61
+ ```ts
62
+ { kind: "user", timeMs: 7000, tag: 42, payload: Uint8Array.of(1,2,3) }
63
+ ```
64
+
65
+ ## Invalid
66
+
67
+ Each invalid fixture parses with `ok === false` and the exact `error.code` and `error.offset` below.
68
+
69
+ ### `zrev-v1/invalid/truncated_header.bin`
70
+
71
+ - `error.code === "ZR_TRUNCATED"`
72
+ - `error.offset === 0`
73
+
74
+ ### `zrev-v1/invalid/truncated_record_header.bin`
75
+
76
+ - `error.code === "ZR_TRUNCATED"`
77
+ - `error.offset === 24`
78
+
79
+ ### `zrev-v1/invalid/truncated_payload.bin`
80
+
81
+ - `error.code === "ZR_INVALID_RECORD"`
82
+ - `error.offset === 24`
83
+
84
+ ### `zrev-v1/invalid/total_size_mismatch.bin`
85
+
86
+ - `error.code === "ZR_SIZE_MISMATCH"`
87
+ - `error.offset === 24`
88
+
89
+ ### `zrev-v1/invalid/misaligned_record_size.bin`
90
+
91
+ - `error.code === "ZR_MISALIGNED"`
92
+ - `error.offset === 24`
93
+
94
+ ### `zrev-v1/invalid/bad_magic.bin`
95
+
96
+ - `error.code === "ZR_BAD_MAGIC"`
97
+ - `error.offset === 0`
98
+
99
+ ### `zrev-v1/invalid/bad_version.bin`
100
+
101
+ - `error.code === "ZR_UNSUPPORTED_VERSION"`
102
+ - `error.offset === 4`
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@rezi-ui/testkit",
3
+ "version": "0.1.0-alpha.1",
4
+ "description": "Test utilities and fixtures for Rezi.",
5
+ "license": "Apache-2.0",
6
+ "homepage": "https://rtlzeromemory.github.io/Rezi/",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/RtlZeroMemory/Rezi.git",
10
+ "directory": "packages/testkit"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/RtlZeroMemory/Rezi/issues"
14
+ },
15
+ "type": "module",
16
+ "types": "./dist/index.d.ts",
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "default": "./dist/index.js"
21
+ }
22
+ },
23
+ "files": [
24
+ "dist/",
25
+ "fixtures/",
26
+ "README.md"
27
+ ],
28
+ "engines": {
29
+ "node": ">=18"
30
+ }
31
+ }