@metamesh/testkit 0.0.0-bootstrap.0 → 0.13.0
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 +225 -0
- package/README.md +112 -5
- package/dist/assertions.d.ts +20 -0
- package/dist/assertions.d.ts.map +1 -0
- package/dist/assertions.js +103 -0
- package/dist/assertions.js.map +1 -0
- package/dist/docs/guides/package.md +113 -0
- package/dist/docs/manifest.json +259 -0
- package/dist/docs/reference/font-fixtures/LoadedFontFixtures.md +12 -0
- package/dist/docs/reference/font-fixtures/loadFontFixtureServices.md +10 -0
- package/dist/docs/reference/font-fixtures/loadFontFixtures.md +10 -0
- package/dist/docs/reference/fonts/FontTestFixture.md +17 -0
- package/dist/docs/reference/fonts/prepareFontTestServices.md +10 -0
- package/dist/docs/reference/index/GeneratorTestExecution.md +18 -0
- package/dist/docs/reference/index/GeneratorTestRunner.md +18 -0
- package/dist/docs/reference/index/GeneratorTestRunnerOptions.md +14 -0
- package/dist/docs/reference/index/MeshMeasurementExpectation.md +19 -0
- package/dist/docs/reference/index/MeshMeasurementTolerances.md +17 -0
- package/dist/docs/reference/index/createGeneratorTestRunner.md +12 -0
- package/dist/docs/reference/index/expectMeshMeasurements.md +14 -0
- package/dist/docs/reference/index/expectSerializableDefinition.md +10 -0
- package/dist/docs/reference/index/expectValidDefaults.md +10 -0
- package/dist/docs/reference/index/expectValidParts.md +19 -0
- package/dist/docs/reference/index/expectValidPresets.md +10 -0
- package/dist/docs/reference/index/getTestEngine.md +13 -0
- package/dist/engine.d.ts +7 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +11 -0
- package/dist/engine.js.map +1 -0
- package/dist/font-fixtures.d.ts +10 -0
- package/dist/font-fixtures.d.ts.map +1 -0
- package/dist/font-fixtures.js +75 -0
- package/dist/font-fixtures.js.map +1 -0
- package/dist/fonts.d.ts +13 -0
- package/dist/fonts.d.ts.map +1 -0
- package/dist/fonts.js +34 -0
- package/dist/fonts.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/measurements.d.ts +28 -0
- package/dist/measurements.d.ts.map +1 -0
- package/dist/measurements.js +66 -0
- package/dist/measurements.js.map +1 -0
- package/dist/runner.d.ts +34 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +118 -0
- package/dist/runner.js.map +1 -0
- package/package.json +43 -6
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# @metamesh/testkit
|
|
2
|
+
|
|
3
|
+
## 0.13.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 2ebe03f: Ship exact-version offline documentation and a development-only authoring CLI for semantic
|
|
8
|
+
checking, generation, captured geometry inspection, and explicit Chromium previews. Use exact
|
|
9
|
+
package versions in documentation metadata and reject unsupported authoring artifact formats.
|
|
10
|
+
Provide generated command help and strict per-command argument validation, and enforce semantic
|
|
11
|
+
checking even when the consumer's TypeScript configuration disables it.
|
|
12
|
+
|
|
13
|
+
Publish lightweight model and Generator testing helpers as `@metamesh/testkit`. Move the
|
|
14
|
+
`metamesh` executable and Node authoring API into `@metamesh/cli`, which owns compiler, bundler,
|
|
15
|
+
renderer, and browser dependencies. Remove the former package name and authoring entry from
|
|
16
|
+
Testkit without compatibility aliases.
|
|
17
|
+
|
|
18
|
+
- 7e1b75d: Simplify modeling authoring with `polygon` construction, shared bounds and vector text fitting,
|
|
19
|
+
Section patterns, pure pattern transforms, and explicit profile closure and part layout helpers.
|
|
20
|
+
Zero-sized round, chamfer, and smooth treatments preserve untreated geometry.
|
|
21
|
+
|
|
22
|
+
Replace the public geometry vocabulary with `Vector2`, `Vector3`, `Contour`, `Polygon`, and
|
|
23
|
+
`Region`, and use canonical `Bounds2` and `Bounds3` throughout. Remove retired constructor and
|
|
24
|
+
type names. Bundles require runtime major 5 and the generation realm uses protocol 5; older
|
|
25
|
+
runtime packages reject before execution. The package envelope remains format 4.
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- Updated dependencies [2ebe03f]
|
|
30
|
+
- Updated dependencies [7e1b75d]
|
|
31
|
+
- Updated dependencies [3139981]
|
|
32
|
+
- @metamesh/modeling@0.13.0
|
|
33
|
+
- @metamesh/generator-sdk@0.13.0
|
|
34
|
+
|
|
35
|
+
## 0.12.0
|
|
36
|
+
|
|
37
|
+
### Patch Changes
|
|
38
|
+
|
|
39
|
+
- Updated dependencies [45d2617]
|
|
40
|
+
- @metamesh/modeling@0.12.0
|
|
41
|
+
- @metamesh/generator-sdk@0.12.0
|
|
42
|
+
|
|
43
|
+
## 0.11.0
|
|
44
|
+
|
|
45
|
+
### Minor Changes
|
|
46
|
+
|
|
47
|
+
- b5da778: Replace prepare/build with typed generation programs, optional computed values and authoritative
|
|
48
|
+
part placement. Add isolated session caches and deferred geometry with explicit snapshot ownership.
|
|
49
|
+
Expose immutable fluent Solid and Section methods for transforms, subtraction, finishing, and
|
|
50
|
+
Section-to-Solid construction, replacing the corresponding standalone operations and public
|
|
51
|
+
context facade. Generator packages require format 4 and runtime 4; previous executable contracts are unsupported.
|
|
52
|
+
|
|
53
|
+
### Patch Changes
|
|
54
|
+
|
|
55
|
+
- 88f5336: Correct immutable cache comparisons, recapture mutable mesh inputs on every run, and preserve
|
|
56
|
+
session ownership during concurrent Testkit operations. Reject unsupported hidden data fields
|
|
57
|
+
instead of silently dropping them, and reuse native operation contexts during recipe evaluation.
|
|
58
|
+
- Updated dependencies [88f5336]
|
|
59
|
+
- Updated dependencies [6c90e9d]
|
|
60
|
+
- Updated dependencies [b5da778]
|
|
61
|
+
- Updated dependencies [60c458f]
|
|
62
|
+
- Updated dependencies [d69836c]
|
|
63
|
+
- Updated dependencies [bfb7a63]
|
|
64
|
+
- Updated dependencies [a1f5aba]
|
|
65
|
+
- Updated dependencies [d4ffce7]
|
|
66
|
+
- @metamesh/modeling@0.11.0
|
|
67
|
+
- @metamesh/generator-sdk@0.11.0
|
|
68
|
+
|
|
69
|
+
## 0.10.0
|
|
70
|
+
|
|
71
|
+
### Minor Changes
|
|
72
|
+
|
|
73
|
+
- 9d7052c: Separate parameter values from local UI metadata, add strict parameter-document diagnostics and a generated JSON Schema, and rename the side-profile and contour APIs. Generator packages and modules now require format 3 and runtime 3.0.0.
|
|
74
|
+
|
|
75
|
+
### Patch Changes
|
|
76
|
+
|
|
77
|
+
- Updated dependencies [0eea1b4]
|
|
78
|
+
- Updated dependencies [9d7052c]
|
|
79
|
+
- Updated dependencies [cf597bd]
|
|
80
|
+
- @metamesh/generator-sdk@0.10.0
|
|
81
|
+
- @metamesh/modeling@0.10.0
|
|
82
|
+
|
|
83
|
+
## 0.9.0
|
|
84
|
+
|
|
85
|
+
### Patch Changes
|
|
86
|
+
|
|
87
|
+
- Updated dependencies [e405876]
|
|
88
|
+
- Updated dependencies [e405876]
|
|
89
|
+
- @metamesh/generator-sdk@0.9.0
|
|
90
|
+
- @metamesh/modeling@0.9.0
|
|
91
|
+
|
|
92
|
+
## 0.8.0
|
|
93
|
+
|
|
94
|
+
### Minor Changes
|
|
95
|
+
|
|
96
|
+
- bf1abe4: Add circular baselines to prepared vector text and Generator text services. Shaped glyphs and attached marks rotate rigidly around a millimetre radius, preserving kerning, ligatures, exact curve bounds and logical advances. Circular text is limited to one line, baseline vertical alignment, less than one revolution, and outlines that stay clear of the circle's center axis.
|
|
97
|
+
- bf1abe4: Complete solid splitting, plane clipping, Section hull/component/simplification operations, minimum-distance
|
|
98
|
+
queries and inspection facts. Add optional bounded geometric solid
|
|
99
|
+
validation at build/export boundaries and a pure uniform-density volume centroid helper.
|
|
100
|
+
Reuse immutable native inspection facts within a build and fresh owned topology analysis during
|
|
101
|
+
solid validation; share checks for identical buffer ranges without trusting mutable external facts.
|
|
102
|
+
|
|
103
|
+
Unify SVG default/preset limits and strict preset metadata checks. Preserve structured validation
|
|
104
|
+
codes and nested paths, add physical mesh assertions, and require runtime 2.1 for the current host
|
|
105
|
+
surface and issue metadata.
|
|
106
|
+
|
|
107
|
+
### Patch Changes
|
|
108
|
+
|
|
109
|
+
- Updated dependencies [bf1abe4]
|
|
110
|
+
- Updated dependencies [bf1abe4]
|
|
111
|
+
- Updated dependencies [bf1abe4]
|
|
112
|
+
- Updated dependencies [bf1abe4]
|
|
113
|
+
- Updated dependencies [bf1abe4]
|
|
114
|
+
- @metamesh/modeling@0.8.0
|
|
115
|
+
- @metamesh/generator-sdk@0.8.0
|
|
116
|
+
|
|
117
|
+
## 0.7.0
|
|
118
|
+
|
|
119
|
+
### Patch Changes
|
|
120
|
+
|
|
121
|
+
- Updated dependencies [b1b97b9]
|
|
122
|
+
- Updated dependencies [b1b97b9]
|
|
123
|
+
- @metamesh/modeling@0.7.0
|
|
124
|
+
- @metamesh/generator-sdk@0.7.0
|
|
125
|
+
|
|
126
|
+
## 0.6.0
|
|
127
|
+
|
|
128
|
+
### Minor Changes
|
|
129
|
+
|
|
130
|
+
- Run prepare/build through the shared Modeling engine. Remove direct native-kernel and generate bypass APIs; add direct preparation probes, finalized-model execution, and synchronous mesh assertions for an explicit engine.
|
|
131
|
+
|
|
132
|
+
## 0.5.2
|
|
133
|
+
|
|
134
|
+
### Patch Changes
|
|
135
|
+
|
|
136
|
+
- Updated dependencies [02a1692]
|
|
137
|
+
- @metamesh/generator-sdk@0.5.2
|
|
138
|
+
- @metamesh/geometry@0.5.2
|
|
139
|
+
|
|
140
|
+
## 0.5.1
|
|
141
|
+
|
|
142
|
+
### Patch Changes
|
|
143
|
+
|
|
144
|
+
- Updated dependencies
|
|
145
|
+
- @metamesh/generator-sdk@0.5.1
|
|
146
|
+
- @metamesh/geometry@0.5.1
|
|
147
|
+
|
|
148
|
+
## 0.5.0
|
|
149
|
+
|
|
150
|
+
### Minor Changes
|
|
151
|
+
|
|
152
|
+
- 0dc29c2: Add the portable numeric `curve-resolution` parameter role for model-owned physical curve
|
|
153
|
+
tolerance, with strict millimetre units, positive bounds, and one role per definition. Require
|
|
154
|
+
runtime 1.3.0 or later for packages declaring the role. Geometry and
|
|
155
|
+
Testkit follow the coordinated fixed Preview package release.
|
|
156
|
+
|
|
157
|
+
### Patch Changes
|
|
158
|
+
|
|
159
|
+
- Updated dependencies [0dc29c2]
|
|
160
|
+
- Updated dependencies [0dc29c2]
|
|
161
|
+
- @metamesh/generator-sdk@0.5.0
|
|
162
|
+
- @metamesh/geometry@0.5.0
|
|
163
|
+
|
|
164
|
+
## 0.4.0
|
|
165
|
+
|
|
166
|
+
### Minor Changes
|
|
167
|
+
|
|
168
|
+
- ad3bb49: Strengthen generator geometry with correct concave sweep caps, bounded region aggregation,
|
|
169
|
+
consistent finite input checks, protected copied-mesh scope exits, and shared primitive/extrusion
|
|
170
|
+
sampling. Add scoped hull, Minkowski sum, projection, slicing, and region revolution.
|
|
171
|
+
|
|
172
|
+
Compiled `MeshPart` now exposes `{ id, positions, indices, color? }`, directly compatible with SDK
|
|
173
|
+
`GeneratedPart`. Pass explicit `{ degrees }` or `{ radians }` to `rotationTransform3`, and rounded
|
|
174
|
+
rectangle sampling options as `{ segmentsPerCorner }` or `{ resolution }`.
|
|
175
|
+
|
|
176
|
+
Add `definePreparedGeneratorModule` for bounded, one-use validation/generation preparation while
|
|
177
|
+
preserving the five format-1 module exports. Authored `/v1` keeps its existing signatures and shares
|
|
178
|
+
the pure validation and sampling implementation with compiled modeling.
|
|
179
|
+
|
|
180
|
+
### Patch Changes
|
|
181
|
+
|
|
182
|
+
- Updated dependencies [ad3bb49]
|
|
183
|
+
- @metamesh/geometry@0.4.0
|
|
184
|
+
- @metamesh/generator-sdk@0.4.0
|
|
185
|
+
|
|
186
|
+
## 0.3.0
|
|
187
|
+
|
|
188
|
+
### Minor Changes
|
|
189
|
+
|
|
190
|
+
- e87357e: Add direct catalog-font text geometry and matching metrics through prepared synchronous font
|
|
191
|
+
scopes. Share vector layout with SVG outlining, use natural font line spacing by default, and
|
|
192
|
+
make whitespace measurable. Nonzero tracking disables optional ligatures to match browser text.
|
|
193
|
+
Compiled Generators can receive font services during validation as well as generation; packages
|
|
194
|
+
declaring font parameters require runtime 1.2.0. Text geometry requires an exact font selection;
|
|
195
|
+
host text services expose shared vector layout. Browser editing uses prepared vector measurements.
|
|
196
|
+
Compiled module calls require explicit execution services for validation and generation.
|
|
197
|
+
|
|
198
|
+
Use the shared transform functions for both 2D sections and 3D solids. Reuse core-validated immutable
|
|
199
|
+
loops, polygons, and regions when winding and tolerance policies match, avoiding repeated topology
|
|
200
|
+
validation without changing tessellation or accepting unvalidated caller geometry.
|
|
201
|
+
|
|
202
|
+
### Patch Changes
|
|
203
|
+
|
|
204
|
+
- Updated dependencies [e87357e]
|
|
205
|
+
- @metamesh/geometry@0.3.0
|
|
206
|
+
- @metamesh/generator-sdk@0.3.0
|
|
207
|
+
|
|
208
|
+
## 0.2.0
|
|
209
|
+
|
|
210
|
+
### Minor Changes
|
|
211
|
+
|
|
212
|
+
- 8b4e918: Add immutable font selections, font parameters and prepared text services, the optional Geometry
|
|
213
|
+
text engine, and reproducible font test services.
|
|
214
|
+
|
|
215
|
+
### Patch Changes
|
|
216
|
+
|
|
217
|
+
- Updated dependencies [8b4e918]
|
|
218
|
+
- @metamesh/generator-sdk@0.2.0
|
|
219
|
+
- @metamesh/geometry@0.2.0
|
|
220
|
+
|
|
221
|
+
## 0.1.0
|
|
222
|
+
|
|
223
|
+
### Minor Changes
|
|
224
|
+
|
|
225
|
+
- Initial public Preview release of the Generator contract assertions.
|
package/README.md
CHANGED
|
@@ -1,6 +1,113 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `@metamesh/testkit`
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
Test MetaMesh models and Generators with the same generation engine used by their hosts. Check definitions,
|
|
4
|
+
presets, mesh validity, and physical measurements with any test runner.
|
|
5
|
+
|
|
6
|
+
> **Preview:** `0.x` minor releases may break compatibility. Patches remain compatible within the
|
|
7
|
+
> same minor line.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
Install matching SDK, Modeling, and Testkit releases. Testkit is a development dependency:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm add @metamesh/generator-sdk @metamesh/modeling
|
|
15
|
+
pnpm add -D @metamesh/testkit
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Execute models in tests
|
|
19
|
+
|
|
20
|
+
Given a Generator module exporting its `definition` and default runtime, such as the
|
|
21
|
+
[SDK example](https://github.com/JasonKoolman/metamesh/blob/main/packages/generator-sdk/README.md#define-controls):
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { getDefaultParameters } from "@metamesh/generator-sdk/parameters";
|
|
25
|
+
import { createGeneratorTestRunner, expectValidParts } from "@metamesh/testkit";
|
|
26
|
+
|
|
27
|
+
import runtime, { definition } from "./generator.js";
|
|
28
|
+
|
|
29
|
+
const runner = createGeneratorTestRunner(definition, runtime);
|
|
30
|
+
try {
|
|
31
|
+
const result = await runner.execute(getDefaultParameters(definition));
|
|
32
|
+
if (result.type !== "generated") throw new Error("Expected valid Generator output.");
|
|
33
|
+
try {
|
|
34
|
+
await expectValidParts(result.model.parts);
|
|
35
|
+
} finally {
|
|
36
|
+
result.model.dispose();
|
|
37
|
+
}
|
|
38
|
+
} finally {
|
|
39
|
+
runner.dispose();
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`execute` normalizes values, prepares services, and runs a persistent session. Schema and assertion
|
|
44
|
+
errors return `invalid`; unexpected execution or malformed-output errors reject. Dispose returned
|
|
45
|
+
snapshots separately from the runner; captured snapshots remain valid after runner disposal.
|
|
46
|
+
|
|
47
|
+
Use `runner.validate(parameters, { normalize: false })` to probe deliberately invalid typed values
|
|
48
|
+
without finalizing parts. It checks declarations and reached assertions; observing geometry can
|
|
49
|
+
still initialize the engine. Creating a runner alone loads no engine or assets. Pass `options.engine`
|
|
50
|
+
to reuse a test-owned engine and `options.limits` to lower host ceilings.
|
|
51
|
+
|
|
52
|
+
## Assertions
|
|
53
|
+
|
|
54
|
+
Helpers throw on failure without depending on your test framework:
|
|
55
|
+
|
|
56
|
+
| Helper | Checks |
|
|
57
|
+
| ------------------------------ | ------------------------------------------------------------------ |
|
|
58
|
+
| `expectSerializableDefinition` | Strict parsing and a canonical JSON round trip |
|
|
59
|
+
| `expectValidDefaults` | Strict parameter decoding and agreement with definition defaults |
|
|
60
|
+
| `expectValidPresets` | Serializable preset metadata; use the runner for domain assertions |
|
|
61
|
+
| `expectValidParts` | Strict part metadata, closed topology, and native reconstruction |
|
|
62
|
+
| `expectMeshMeasurements` | Bounds, area, signed volume, and connected-component count |
|
|
63
|
+
|
|
64
|
+
`expectValidParts(parts, engine)` is synchronous and uses that engine's limits. Without an engine,
|
|
65
|
+
it returns a promise using the shared test engine and default limits. It also accepts finalized
|
|
66
|
+
parts, stripping measurement facts before strict validation; other unknown fields reject.
|
|
67
|
+
|
|
68
|
+
Compare physical measurements with explicit tolerances. For a 30 × 20 × 4 mm box mesh:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { expectMeshMeasurements } from "@metamesh/testkit";
|
|
72
|
+
|
|
73
|
+
expectMeshMeasurements(
|
|
74
|
+
mesh,
|
|
75
|
+
{ signedVolume: 30 * 20 * 4, connectedComponentCount: 1 },
|
|
76
|
+
{ signedVolume: 0.05 }
|
|
77
|
+
);
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Bounds use mm, area mm², and volume mm³. Tolerances are absolute and default to zero; component
|
|
81
|
+
counts are exact. Measurements check closed oriented topology without a native engine. Matching
|
|
82
|
+
measurements alone do not establish geometric equivalence or exclude self-intersections; use
|
|
83
|
+
`expectValidParts` for native reconstruction.
|
|
84
|
+
|
|
85
|
+
## Font fixtures
|
|
86
|
+
|
|
87
|
+
Supply `prepareServices` in runner options for models with fonts. It receives the definition and
|
|
88
|
+
current parameters, and can return services synchronously or asynchronously. Missing fixtures or
|
|
89
|
+
service failures reject before generation.
|
|
90
|
+
|
|
91
|
+
`prepareFontTestServices` from `/fonts` checks immutable font revisions and prepares services from
|
|
92
|
+
checked-in bytes. Install Modeling's optional `fontkit` peer, plus `woff2-encoder` for WOFF2 fixtures.
|
|
93
|
+
Tests need no font downloads or browser cache; retain the fixtures' licenses.
|
|
94
|
+
|
|
95
|
+
## Documentation
|
|
96
|
+
|
|
97
|
+
Resolve `@metamesh/testkit/docs/manifest.json` for this installed version's Markdown
|
|
98
|
+
reference and testing guidance. Testkit has no compiler, bundler, renderer, or browser dependencies.
|
|
99
|
+
It shares the Modeling engine and Generator SDK contracts rather than duplicating runtime rules.
|
|
100
|
+
|
|
101
|
+
For source checking, captured runs, documentation lookup, and images, install
|
|
102
|
+
[`@metamesh/cli`](https://github.com/JasonKoolman/metamesh/blob/main/packages/cli/README.md).
|
|
103
|
+
Its executable is `metamesh`; reusable Node authoring functions live in `@metamesh/cli/authoring`.
|
|
104
|
+
|
|
105
|
+
- [Generator SDK](https://github.com/JasonKoolman/metamesh/blob/main/packages/generator-sdk/README.md) — definitions, parameter values, and module authoring.
|
|
106
|
+
- [Modeling](https://github.com/JasonKoolman/metamesh/blob/main/packages/modeling/README.md) — geometry, sessions, and snapshots.
|
|
107
|
+
- [API source](https://github.com/JasonKoolman/metamesh/blob/main/packages/testkit/src/index.ts) — runner and assertion exports; [font helpers](https://github.com/JasonKoolman/metamesh/blob/main/packages/testkit/src/fonts.ts) live in `/fonts`.
|
|
108
|
+
|
|
109
|
+
For package development, see [Contributing](https://github.com/JasonKoolman/metamesh/blob/main/CONTRIBUTING.md).
|
|
110
|
+
|
|
111
|
+
## License
|
|
112
|
+
|
|
113
|
+
[Apache-2.0](https://github.com/JasonKoolman/metamesh/blob/main/packages/testkit/LICENSE).
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { GeneratorDefinition, GeneratorParams, GeneratorPreset } from "@metamesh/generator-sdk";
|
|
2
|
+
import { type GeneratedPart } from "@metamesh/generator-sdk/runtime";
|
|
3
|
+
import { type FinalizedPart } from "@metamesh/modeling";
|
|
4
|
+
import type { ModelEngine } from "@metamesh/modeling/engine";
|
|
5
|
+
/** Throws unless a definition already has the canonical package-serializable representation. */
|
|
6
|
+
export declare function expectSerializableDefinition(definition: GeneratorDefinition): void;
|
|
7
|
+
/** Throws unless defaults strictly decode and equal the defaults derived from the definition. */
|
|
8
|
+
export declare function expectValidDefaults<const D extends GeneratorDefinition>(definition: D, defaults: GeneratorParams<D>): void;
|
|
9
|
+
/** Checks preset metadata. Validate domain assertions through the generation test runner. */
|
|
10
|
+
export declare function expectValidPresets<const D extends GeneratorDefinition>(definition: D, presets: readonly GeneratorPreset<D>[]): void;
|
|
11
|
+
/**
|
|
12
|
+
* Checks finalized engine parts after omitting measurement facts from their strict wire DTOs.
|
|
13
|
+
* Runs mesh reconstruction/finalization synchronously using the supplied engine.
|
|
14
|
+
*/
|
|
15
|
+
export declare function expectValidParts(value: readonly FinalizedPart[], engine: ModelEngine): readonly GeneratedPart[];
|
|
16
|
+
/** Strictly checks unknown wire data and reconstructs its meshes using the supplied engine. */
|
|
17
|
+
export declare function expectValidParts(value: unknown, engine: ModelEngine): readonly GeneratedPart[];
|
|
18
|
+
/** Initializes the shared test engine lazily, then applies the same wire and mesh checks. */
|
|
19
|
+
export declare function expectValidParts(value: unknown): Promise<readonly GeneratedPart[]>;
|
|
20
|
+
//# sourceMappingURL=assertions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assertions.d.ts","sourceRoot":"","sources":["../src/assertions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,eAAe,EACf,eAAe,EAChB,MAAM,yBAAyB,CAAC;AAMjC,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAC1F,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AA4B7D,gGAAgG;AAChG,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,mBAAmB,GAAG,IAAI,CAUlF;AAED,iGAAiG;AACjG,wBAAgB,mBAAmB,CAAC,KAAK,CAAC,CAAC,SAAS,mBAAmB,EACrE,UAAU,EAAE,CAAC,EACb,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC,GAC3B,IAAI,CAQN;AAED,6FAA6F;AAC7F,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,CAAC,SAAS,mBAAmB,EACpE,UAAU,EAAE,CAAC,EACb,OAAO,EAAE,SAAS,eAAe,CAAC,CAAC,CAAC,EAAE,GACrC,IAAI,CAEN;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,aAAa,EAAE,EAC/B,MAAM,EAAE,WAAW,GAClB,SAAS,aAAa,EAAE,CAAC;AAE5B,+FAA+F;AAC/F,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,GAAG,SAAS,aAAa,EAAE,CAAC;AAEhG,6FAA6F;AAC7F,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,aAAa,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { parseGeneratorDefinition, validateGeneratorPresets, } from "@metamesh/generator-sdk/packages";
|
|
2
|
+
import { createParamCodec, getDefaultParameters } from "@metamesh/generator-sdk/parameters";
|
|
3
|
+
import { parseGeneratedParts } from "@metamesh/generator-sdk/runtime";
|
|
4
|
+
import { generate } from "@metamesh/modeling";
|
|
5
|
+
import { getTestEngine } from "./engine.js";
|
|
6
|
+
function stringify(value, label) {
|
|
7
|
+
try {
|
|
8
|
+
const serialized = JSON.stringify(value);
|
|
9
|
+
if (serialized === undefined)
|
|
10
|
+
throw new TypeError(`${label} is not JSON-serializable.`);
|
|
11
|
+
return serialized;
|
|
12
|
+
}
|
|
13
|
+
catch (cause) {
|
|
14
|
+
throw new TypeError(`${label} is not JSON-serializable.`, { cause });
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function sortJson(value) {
|
|
18
|
+
if (Array.isArray(value))
|
|
19
|
+
return value.map(sortJson);
|
|
20
|
+
if (typeof value !== "object" || value === null)
|
|
21
|
+
return value;
|
|
22
|
+
return Object.fromEntries(Object.entries(value)
|
|
23
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
24
|
+
.map(([key, entry]) => [key, sortJson(entry)]));
|
|
25
|
+
}
|
|
26
|
+
function stableStringify(value, label) {
|
|
27
|
+
return stringify(sortJson(value), label);
|
|
28
|
+
}
|
|
29
|
+
/** Throws unless a definition already has the canonical package-serializable representation. */
|
|
30
|
+
export function expectSerializableDefinition(definition) {
|
|
31
|
+
parseGeneratorDefinition(definition);
|
|
32
|
+
const decoded = JSON.parse(stringify(definition, "Generator definition"));
|
|
33
|
+
const parsed = parseGeneratorDefinition(decoded);
|
|
34
|
+
if (stableStringify(parsed, "Parsed Generator definition") !==
|
|
35
|
+
stableStringify(decoded, "Generator definition")) {
|
|
36
|
+
throw new TypeError("Generator definition must already use its canonical serialized form.");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** Throws unless defaults strictly decode and equal the defaults derived from the definition. */
|
|
40
|
+
export function expectValidDefaults(definition, defaults) {
|
|
41
|
+
const parsed = createParamCodec(definition).parse(defaults);
|
|
42
|
+
if (stableStringify(parsed, "Generator defaults") !==
|
|
43
|
+
stableStringify(getDefaultParameters(definition), "Derived Generator defaults")) {
|
|
44
|
+
throw new TypeError("Generator defaults do not match their definition.");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** Checks preset metadata. Validate domain assertions through the generation test runner. */
|
|
48
|
+
export function expectValidPresets(definition, presets) {
|
|
49
|
+
validateGeneratorPresets(definition, presets);
|
|
50
|
+
}
|
|
51
|
+
export function expectValidParts(value, engine) {
|
|
52
|
+
if (engine === undefined)
|
|
53
|
+
return getTestEngine().then((host) => expectValidParts(value, host));
|
|
54
|
+
const wireValue = Array.isArray(value)
|
|
55
|
+
? value.map((part, index) => {
|
|
56
|
+
if (typeof part !== "object" || part === null || !Object.hasOwn(part, "measurements"))
|
|
57
|
+
return part;
|
|
58
|
+
const prototype = Object.getPrototypeOf(part);
|
|
59
|
+
if (prototype !== null && prototype !== Object.prototype)
|
|
60
|
+
return part;
|
|
61
|
+
const descriptors = Object.getOwnPropertyDescriptors(part);
|
|
62
|
+
if (Object.keys(descriptors).some((key) => ![
|
|
63
|
+
"id",
|
|
64
|
+
"positions",
|
|
65
|
+
"indices",
|
|
66
|
+
"color",
|
|
67
|
+
"measurements",
|
|
68
|
+
"geometry",
|
|
69
|
+
"position",
|
|
70
|
+
"rotation",
|
|
71
|
+
].includes(key)))
|
|
72
|
+
return part;
|
|
73
|
+
// Captured engine snapshots expose owned buffer copies through accessors.
|
|
74
|
+
descriptors["positions"] = { value: part.positions, enumerable: true };
|
|
75
|
+
descriptors["indices"] = { value: part.indices, enumerable: true };
|
|
76
|
+
delete descriptors["position"];
|
|
77
|
+
delete descriptors["rotation"];
|
|
78
|
+
delete descriptors["measurements"];
|
|
79
|
+
delete descriptors["geometry"];
|
|
80
|
+
return Object.defineProperties({
|
|
81
|
+
geometryId: `assertion-${index}`,
|
|
82
|
+
geometryRevision: 0,
|
|
83
|
+
position: [0, 0, 0],
|
|
84
|
+
rotation: [0, 0, 0],
|
|
85
|
+
}, descriptors);
|
|
86
|
+
})
|
|
87
|
+
: value;
|
|
88
|
+
const parts = parseGeneratedParts(wireValue, engine.limits);
|
|
89
|
+
const session = engine.createSession(generate(({ part }) => parts.map((mesh) => part(mesh.id, {
|
|
90
|
+
geometry: mesh,
|
|
91
|
+
position: mesh.position,
|
|
92
|
+
rotation: mesh.rotation,
|
|
93
|
+
...(mesh.color === undefined ? {} : { color: mesh.color }),
|
|
94
|
+
}))));
|
|
95
|
+
try {
|
|
96
|
+
session.run({}).dispose();
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
session.dispose();
|
|
100
|
+
}
|
|
101
|
+
return parts;
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=assertions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assertions.js","sourceRoot":"","sources":["../src/assertions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# `@metamesh/testkit`
|
|
2
|
+
|
|
3
|
+
Test MetaMesh models and Generators with the same generation engine used by their hosts. Check definitions,
|
|
4
|
+
presets, mesh validity, and physical measurements with any test runner.
|
|
5
|
+
|
|
6
|
+
> **Preview:** `0.x` minor releases may break compatibility. Patches remain compatible within the
|
|
7
|
+
> same minor line.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
Install matching SDK, Modeling, and Testkit releases. Testkit is a development dependency:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm add @metamesh/generator-sdk @metamesh/modeling
|
|
15
|
+
pnpm add -D @metamesh/testkit
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Execute models in tests
|
|
19
|
+
|
|
20
|
+
Given a Generator module exporting its `definition` and default runtime, such as the
|
|
21
|
+
[SDK example](https://github.com/JasonKoolman/metamesh/blob/main/packages/generator-sdk/README.md#define-controls):
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { getDefaultParameters } from "@metamesh/generator-sdk/parameters";
|
|
25
|
+
import { createGeneratorTestRunner, expectValidParts } from "@metamesh/testkit";
|
|
26
|
+
|
|
27
|
+
import runtime, { definition } from "./generator.js";
|
|
28
|
+
|
|
29
|
+
const runner = createGeneratorTestRunner(definition, runtime);
|
|
30
|
+
try {
|
|
31
|
+
const result = await runner.execute(getDefaultParameters(definition));
|
|
32
|
+
if (result.type !== "generated") throw new Error("Expected valid Generator output.");
|
|
33
|
+
try {
|
|
34
|
+
await expectValidParts(result.model.parts);
|
|
35
|
+
} finally {
|
|
36
|
+
result.model.dispose();
|
|
37
|
+
}
|
|
38
|
+
} finally {
|
|
39
|
+
runner.dispose();
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`execute` normalizes values, prepares services, and runs a persistent session. Schema and assertion
|
|
44
|
+
errors return `invalid`; unexpected execution or malformed-output errors reject. Dispose returned
|
|
45
|
+
snapshots separately from the runner; captured snapshots remain valid after runner disposal.
|
|
46
|
+
|
|
47
|
+
Use `runner.validate(parameters, { normalize: false })` to probe deliberately invalid typed values
|
|
48
|
+
without finalizing parts. It checks declarations and reached assertions; observing geometry can
|
|
49
|
+
still initialize the engine. Creating a runner alone loads no engine or assets. Pass `options.engine`
|
|
50
|
+
to reuse a test-owned engine and `options.limits` to lower host ceilings.
|
|
51
|
+
|
|
52
|
+
## Assertions
|
|
53
|
+
|
|
54
|
+
Helpers throw on failure without depending on your test framework:
|
|
55
|
+
|
|
56
|
+
| Helper | Checks |
|
|
57
|
+
| ------------------------------ | ------------------------------------------------------------------ |
|
|
58
|
+
| `expectSerializableDefinition` | Strict parsing and a canonical JSON round trip |
|
|
59
|
+
| `expectValidDefaults` | Strict parameter decoding and agreement with definition defaults |
|
|
60
|
+
| `expectValidPresets` | Serializable preset metadata; use the runner for domain assertions |
|
|
61
|
+
| `expectValidParts` | Strict part metadata, closed topology, and native reconstruction |
|
|
62
|
+
| `expectMeshMeasurements` | Bounds, area, signed volume, and connected-component count |
|
|
63
|
+
|
|
64
|
+
`expectValidParts(parts, engine)` is synchronous and uses that engine's limits. Without an engine,
|
|
65
|
+
it returns a promise using the shared test engine and default limits. It also accepts finalized
|
|
66
|
+
parts, stripping measurement facts before strict validation; other unknown fields reject.
|
|
67
|
+
|
|
68
|
+
Compare physical measurements with explicit tolerances. For a 30 × 20 × 4 mm box mesh:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { expectMeshMeasurements } from "@metamesh/testkit";
|
|
72
|
+
|
|
73
|
+
expectMeshMeasurements(
|
|
74
|
+
mesh,
|
|
75
|
+
{ signedVolume: 30 * 20 * 4, connectedComponentCount: 1 },
|
|
76
|
+
{ signedVolume: 0.05 }
|
|
77
|
+
);
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Bounds use mm, area mm², and volume mm³. Tolerances are absolute and default to zero; component
|
|
81
|
+
counts are exact. Measurements check closed oriented topology without a native engine. Matching
|
|
82
|
+
measurements alone do not establish geometric equivalence or exclude self-intersections; use
|
|
83
|
+
`expectValidParts` for native reconstruction.
|
|
84
|
+
|
|
85
|
+
## Font fixtures
|
|
86
|
+
|
|
87
|
+
Supply `prepareServices` in runner options for models with fonts. It receives the definition and
|
|
88
|
+
current parameters, and can return services synchronously or asynchronously. Missing fixtures or
|
|
89
|
+
service failures reject before generation.
|
|
90
|
+
|
|
91
|
+
`prepareFontTestServices` from `/fonts` checks immutable font revisions and prepares services from
|
|
92
|
+
checked-in bytes. Install Modeling's optional `fontkit` peer, plus `woff2-encoder` for WOFF2 fixtures.
|
|
93
|
+
Tests need no font downloads or browser cache; retain the fixtures' licenses.
|
|
94
|
+
|
|
95
|
+
## Documentation
|
|
96
|
+
|
|
97
|
+
Resolve `@metamesh/testkit/docs/manifest.json` for this installed version's Markdown
|
|
98
|
+
reference and testing guidance. Testkit has no compiler, bundler, renderer, or browser dependencies.
|
|
99
|
+
It shares the Modeling engine and Generator SDK contracts rather than duplicating runtime rules.
|
|
100
|
+
|
|
101
|
+
For source checking, captured runs, documentation lookup, and images, install
|
|
102
|
+
[`@metamesh/cli`](https://github.com/JasonKoolman/metamesh/blob/main/packages/cli/README.md).
|
|
103
|
+
Its executable is `metamesh`; reusable Node authoring functions live in `@metamesh/cli/authoring`.
|
|
104
|
+
|
|
105
|
+
- [Generator SDK](https://github.com/JasonKoolman/metamesh/blob/main/packages/generator-sdk/README.md) — definitions, parameter values, and module authoring.
|
|
106
|
+
- [Modeling](https://github.com/JasonKoolman/metamesh/blob/main/packages/modeling/README.md) — geometry, sessions, and snapshots.
|
|
107
|
+
- [API source](https://github.com/JasonKoolman/metamesh/blob/main/packages/testkit/src/index.ts) — runner and assertion exports; [font helpers](https://github.com/JasonKoolman/metamesh/blob/main/packages/testkit/src/fonts.ts) live in `/fonts`.
|
|
108
|
+
|
|
109
|
+
For package development, see [Contributing](https://github.com/JasonKoolman/metamesh/blob/main/CONTRIBUTING.md).
|
|
110
|
+
|
|
111
|
+
## License
|
|
112
|
+
|
|
113
|
+
[Apache-2.0](https://github.com/JasonKoolman/metamesh/blob/main/packages/testkit/LICENSE).
|