@orkestrel/test 0.0.11 → 0.0.13
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 +58 -39
- package/dist/src/browser/index.d.ts +516 -268
- package/dist/src/browser/index.js +363 -89
- package/dist/src/browser/index.js.map +1 -1
- package/dist/src/core/index.cjs +191 -23
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +272 -23
- package/dist/src/core/index.d.ts +272 -23
- package/dist/src/core/index.js +185 -24
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +69 -50
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +74 -36
- package/dist/src/server/index.d.ts +74 -36
- package/dist/src/server/index.js +68 -52
- package/dist/src/server/index.js.map +1 -1
- package/package.json +14 -11
package/README.md
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
The test helpers the `@orkestrel` fleet kept rewriting, published once. A call recorder that is a
|
|
4
4
|
real callback rather than a spy. A real host delay. A throw-to-value converter and a presence
|
|
5
|
-
narrower, so `!` and `as` stay banned in tests.
|
|
6
|
-
hostile-value corpus for proving guards are total. A cleanup list that gives
|
|
7
|
-
back, newest first. A scratch directory the test owns and destroys, a loopback
|
|
8
|
-
test built, and a symlink-refusing source-file walker. And the browser journey
|
|
9
|
-
a real interface by role and accessible name through the installed Vitest
|
|
10
|
-
here only when enough packages had already written their own; the guide's
|
|
5
|
+
narrower, so `!` and `as` stay banned in tests. An async-iterable collector, a stream collector, and
|
|
6
|
+
a JSON copier. A frozen hostile-value corpus for proving guards are total. A cleanup list that gives
|
|
7
|
+
every owned resource back, newest first. A scratch directory the test owns and destroys, a loopback
|
|
8
|
+
port for a server the test built, and a symlink-refusing source-file walker. And the browser journey
|
|
9
|
+
layer, which drives a real interface by role and accessible name through the installed Vitest
|
|
10
|
+
provider. A helper ships here only when enough packages had already written their own; the guide's
|
|
11
11
|
[Limits](guides/test.md#limits) section states that rule, what it excluded, and the one door the
|
|
12
|
-
journey layer came through instead. Add it as a devDependency; nothing here runs in production
|
|
13
|
-
|
|
12
|
+
journey layer came through instead. Add it as a devDependency; nothing here runs in production code.
|
|
13
|
+
Part of the `@orkestrel` line.
|
|
14
14
|
|
|
15
15
|
It has **zero runtime dependencies**, and no exported signature names an `@orkestrel/*` type. Both
|
|
16
16
|
rules exist for one reason: a test helper hands its types straight into the consumer's assertions,
|
|
@@ -73,18 +73,27 @@ once, in its own setup, because registering it here would take a runtime depende
|
|
|
73
73
|
runner. A handler that throws does not stop the run: one failure is rethrown by identity, so the
|
|
74
74
|
test can assert on the value it threw, and several arrive as an `AggregateError` in run order.
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
(
|
|
80
|
-
|
|
76
|
+
Core also carries the wait family (`waitForCondition`, `retryUntil`, `waitForEvent`, `waitForAbort`,
|
|
77
|
+
and the leaves they share), the recorder map and the abort-signal instrument, the unchecked
|
|
78
|
+
boundary, the header flattener, and the JSON Lines decoder — the guide's
|
|
79
|
+
[Surface](guides/test.md#surface) section carries every export. Among them are `collect` (drains an
|
|
80
|
+
async iterable), `collectStream` (drains a `ReadableStream`), `roundTripJSON` (copies any value
|
|
81
|
+
`JSONSafe` accepts, including an interface-typed one, and throws rather than turning a non-finite
|
|
82
|
+
number into `null`), `resolveRoot` (the directory above the calling module, from `import.meta`), and
|
|
83
|
+
`createHostileValues` (a frozen array of fresh values that each make a naive read throw or violate a
|
|
84
|
+
naive structural assumption). Beside them sits the statechart contract the fleet repeats:
|
|
85
|
+
`StateTransition` and `StateScenario` for one row of a transition table, `executeScenario` and
|
|
86
|
+
`executeScenarios` to walk it, and `STATECHART_ATTRIBUTES` and `STATECHART_STATUSES` for the harness
|
|
87
|
+
a browser workspace renders that table in.
|
|
81
88
|
|
|
82
89
|
The server face adds `readInventory`, which reads a checkout into a map of root-relative path to
|
|
83
90
|
file text that a parity suite can assert against, and `createLoopback`, which binds a server the
|
|
84
|
-
test built to an ephemeral loopback port. Behind
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
91
|
+
test built to an ephemeral loopback port. Behind them sit the pure leaves the server face also
|
|
92
|
+
exports on its own: `readInventory` refuses an escape with `resolveContained` and prunes with
|
|
93
|
+
`isExcluded`, while `createScratch` refuses one with `requireContained`, the throwing form, and
|
|
94
|
+
reads and compares its allocation with `readIdentity` and `matchesIdentity` before `destroy()`
|
|
95
|
+
removes anything. `createLink` and `removeTree` do the writing under it, and both decide on the
|
|
96
|
+
errno `readErrorCode` reads off an unknown throw.
|
|
88
97
|
|
|
89
98
|
```ts
|
|
90
99
|
import { resolveRoot } from '@orkestrel/test'
|
|
@@ -97,44 +106,51 @@ const root = resolveRoot(import.meta)
|
|
|
97
106
|
const sources = readInventory(root, ['src/core', 'src/server'], { extensions: ['.ts'] })
|
|
98
107
|
|
|
99
108
|
Object.keys(sources)
|
|
100
|
-
// ['src/core/
|
|
109
|
+
// ['src/core/constants.ts', 'src/core/factories.ts', 'src/core/helpers.ts', 'src/core/index.ts',
|
|
110
|
+
// 'src/core/types.ts', 'src/core/validators.ts', 'src/server/constants.ts',
|
|
101
111
|
// 'src/server/factories.ts', 'src/server/helpers.ts', 'src/server/index.ts', 'src/server/types.ts']
|
|
102
112
|
|
|
103
113
|
// The keys are paths; the values are the file contents.
|
|
104
114
|
sources['src/core/index.ts']
|
|
105
|
-
// "export * from './types.js'\nexport * from './
|
|
115
|
+
// "export * from './types.js'\nexport * from './constants.js'\nexport * from './validators.js'\n
|
|
116
|
+
// export * from './helpers.js'\nexport * from './factories.js'\n"
|
|
106
117
|
|
|
107
118
|
// A target is a file or a directory. A named file is read whatever the extension filter says.
|
|
108
119
|
Object.keys(readInventory(root, ['package.json', 'src/core'], { extensions: ['.ts'] }))
|
|
109
|
-
// ['package.json', 'src/core/
|
|
110
|
-
// 'src/core/types.ts']
|
|
120
|
+
// ['package.json', 'src/core/constants.ts', 'src/core/factories.ts', 'src/core/helpers.ts',
|
|
121
|
+
// 'src/core/index.ts', 'src/core/types.ts', 'src/core/validators.ts']
|
|
111
122
|
|
|
112
123
|
// An `exclude` entry matches whole key segments. A file key drops that file.
|
|
113
124
|
Object.keys(
|
|
114
125
|
readInventory(root, ['src/core'], { extensions: ['.ts'], exclude: ['src/core/index.ts'] }),
|
|
115
126
|
)
|
|
116
|
-
// ['src/core/factories.ts', 'src/core/helpers.ts', 'src/core/types.ts'
|
|
127
|
+
// ['src/core/constants.ts', 'src/core/factories.ts', 'src/core/helpers.ts', 'src/core/types.ts',
|
|
128
|
+
// 'src/core/validators.ts']
|
|
117
129
|
|
|
118
130
|
// A directory key prunes its whole subtree.
|
|
119
131
|
Object.keys(readInventory(root, ['src'], { extensions: ['.ts'], exclude: ['src/server'] }))
|
|
120
|
-
// ['src/
|
|
132
|
+
// ['src/browser/constants.ts', 'src/browser/factories.ts', 'src/browser/helpers.ts',
|
|
133
|
+
// 'src/browser/index.ts', 'src/browser/types.ts', 'src/core/constants.ts',
|
|
134
|
+
// 'src/core/factories.ts', 'src/core/helpers.ts', 'src/core/index.ts', 'src/core/types.ts',
|
|
135
|
+
// 'src/core/validators.ts']
|
|
121
136
|
```
|
|
122
137
|
|
|
123
|
-
Keys are root-relative and `/`-separated whatever the host separator is
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
key that is not integer-like.
|
|
138
|
+
Keys are root-relative and `/`-separated whatever the host separator is. The suite gates that proof
|
|
139
|
+
on a runtime reading of `node:path` rather than on a platform name, so it runs only where the host
|
|
140
|
+
separator differs from `/`. Keys are inserted in sorted order, and a plain object reads that order
|
|
141
|
+
back for every key that is not integer-like.
|
|
127
142
|
|
|
128
|
-
|
|
129
|
-
|
|
143
|
+
`createScratch` and `readInventory` promise different things, and each boundary is worth stating up
|
|
144
|
+
front. `createScratch` allocates its own directory at POSIX mode `0700` — under the host temporary
|
|
130
145
|
directory, or under a `parent` you name — and refuses a path that lexically escapes it. The suite
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
146
|
+
gates that assertion on `supportsMode`, the shipped probe that reads whether permission bits
|
|
147
|
+
round-trip on this host, so it runs only where they do and claims nothing about a host that emulates
|
|
148
|
+
them. The mode keeps another uid out, and neither a sibling test worker nor the code under test is
|
|
149
|
+
another uid. It does not walk segments for symbolic links. A link inside its own allocation was
|
|
150
|
+
created by the test process, by the code the test drives, or by this package's own `link` — handing
|
|
151
|
+
that code `scratch.path` is the ordinary use of this helper — and a contained path reaches outside
|
|
152
|
+
the allocation through one. The guide's [traversal](guides/test.md#traversal) section states what
|
|
153
|
+
each member does with a link it meets. Naming a `parent` inside a package tree costs one more thing:
|
|
138
154
|
while the allocation exists, everything that walks that tree sees it. `destroy()` is unaffected by
|
|
139
155
|
where the allocation sits, because it matches the allocation's identity rather than its path. One
|
|
140
156
|
field of that identity is the host's to supply: where a host reports no real creation time, libuv
|
|
@@ -150,7 +166,10 @@ region and disclosure targeting, input and traversal verbs, perception readers,
|
|
|
150
166
|
instrument that composites translucent layers, and the capture portfolio. Every acting verb
|
|
151
167
|
resolves its own target from a role and an accessible name — none takes an element, a component
|
|
152
168
|
instance, or a selector — and the whole environment imports `vitest/browser` and DOM globals and
|
|
153
|
-
nothing else, with `vitest` declared as a peer dependency.
|
|
169
|
+
nothing else, with `vitest` declared as a peer dependency. Beside the journey verbs are the
|
|
170
|
+
readers a markup conformance check needs: `readClasses` for the classes the markup carries,
|
|
171
|
+
differenced against `readCascade` for the classes the cascade declares, and `extractStyles` for
|
|
172
|
+
the inline `style` attributes and `<style>` elements that go round the cascade entirely. The guide's
|
|
154
173
|
[Browser](guides/test.md#browser) section carries every export and every voice.
|
|
155
174
|
|
|
156
175
|
`createLoopback` binds a server the test built. The caller constructs it and keeps every route,
|
|
@@ -191,8 +210,8 @@ rule deciding what ships and what stays in the package that owns it — see
|
|
|
191
210
|
|
|
192
211
|
## Package
|
|
193
212
|
|
|
194
|
-
Published as
|
|
195
|
-
|
|
213
|
+
Published as typed entry points per the `exports` field in `package.json`: `@orkestrel/test` for the
|
|
214
|
+
host-independent core, `@orkestrel/test/browser` for the journey layer, and
|
|
196
215
|
`@orkestrel/test/server` for the Node helpers. Core and server ship ESM and CommonJS; the browser
|
|
197
216
|
face ships ESM only, because `vitest/browser` is an ES-only module.
|
|
198
217
|
|