@metamesh/testkit 0.17.0 → 0.18.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.
Files changed (87) hide show
  1. package/CHANGELOG.md +159 -0
  2. package/README.md +120 -112
  3. package/dist/assertions.d.ts +8 -15
  4. package/dist/assertions.d.ts.map +1 -1
  5. package/dist/assertions.js +24 -70
  6. package/dist/assertions.js.map +1 -1
  7. package/dist/content-assertions.d.ts +28 -0
  8. package/dist/content-assertions.d.ts.map +1 -0
  9. package/dist/content-assertions.js +75 -0
  10. package/dist/content-assertions.js.map +1 -0
  11. package/dist/content-matchers.d.ts +12 -0
  12. package/dist/content-matchers.d.ts.map +1 -0
  13. package/dist/content-matchers.js +22 -0
  14. package/dist/content-matchers.js.map +1 -0
  15. package/dist/docs/guides/package.md +120 -112
  16. package/dist/docs/manifest.json +157 -45
  17. package/dist/docs/reference/font-fixtures/LoadedFontFixtures.md +1 -1
  18. package/dist/docs/reference/font-fixtures/loadFontFixtureServices.md +1 -1
  19. package/dist/docs/reference/font-fixtures/loadFontFixtures.md +1 -1
  20. package/dist/docs/reference/fonts/FontTestFixture.md +1 -1
  21. package/dist/docs/reference/fonts/prepareFontTestServices.md +1 -1
  22. package/dist/docs/reference/index/BufferContent.md +13 -0
  23. package/dist/docs/reference/index/ContentMismatchError.md +12 -0
  24. package/dist/docs/reference/index/GeneratorModelTestInput.md +13 -0
  25. package/dist/docs/reference/index/GeneratorModelTestOptions.md +10 -0
  26. package/dist/docs/reference/index/GeneratorTestResult.md +18 -0
  27. package/dist/docs/reference/index/GeneratorTestRunner.md +9 -11
  28. package/dist/docs/reference/index/GeneratorTestRunnerOptions.md +2 -3
  29. package/dist/docs/reference/index/MeshContent.md +13 -0
  30. package/dist/docs/reference/index/MeshMeasurementExpectation.md +3 -3
  31. package/dist/docs/reference/index/MeshMeasurementTolerances.md +1 -1
  32. package/dist/docs/reference/index/RunModelOptions.md +13 -0
  33. package/dist/docs/reference/index/assertEqualBuffer.md +15 -0
  34. package/dist/docs/reference/index/assertEqualMesh.md +14 -0
  35. package/dist/docs/reference/index/{expectMeshMeasurements.md → assertMeshMeasurements.md} +3 -3
  36. package/dist/docs/reference/index/{expectValidDefaults.md → assertValidDefaults.md} +3 -3
  37. package/dist/docs/reference/index/assertValidDefinition.md +10 -0
  38. package/dist/docs/reference/index/assertValidParts.md +12 -0
  39. package/dist/docs/reference/index/{expectValidPresets.md → assertValidPresets.md} +3 -3
  40. package/dist/docs/reference/index/contentMatchers.md +12 -0
  41. package/dist/docs/reference/index/createGeneratorTestRunner.md +2 -4
  42. package/dist/docs/reference/index/getTestEngine.md +1 -1
  43. package/dist/docs/reference/index/runModel.md +13 -0
  44. package/dist/generator-execution.d.ts +6 -0
  45. package/dist/generator-execution.d.ts.map +1 -0
  46. package/dist/generator-execution.js +20 -0
  47. package/dist/generator-execution.js.map +1 -0
  48. package/dist/generator-test-runner.d.ts +32 -0
  49. package/dist/generator-test-runner.d.ts.map +1 -0
  50. package/dist/generator-test-runner.js +109 -0
  51. package/dist/generator-test-runner.js.map +1 -0
  52. package/dist/index.d.ts +10 -7
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +7 -5
  55. package/dist/index.js.map +1 -1
  56. package/dist/measurements.d.ts +4 -4
  57. package/dist/measurements.d.ts.map +1 -1
  58. package/dist/measurements.js +10 -9
  59. package/dist/measurements.js.map +1 -1
  60. package/dist/run-model.d.ts +21 -0
  61. package/dist/run-model.d.ts.map +1 -0
  62. package/dist/run-model.js +39 -0
  63. package/dist/run-model.js.map +1 -0
  64. package/dist/{engine.d.ts → test-engine.d.ts} +1 -1
  65. package/dist/test-engine.d.ts.map +1 -0
  66. package/dist/{engine.js → test-engine.js} +1 -1
  67. package/dist/test-engine.js.map +1 -0
  68. package/package.json +8 -5
  69. package/dist/docs/reference/index/GeneratorTestExecution.md +0 -19
  70. package/dist/docs/reference/index/ModelTestOptions.md +0 -13
  71. package/dist/docs/reference/index/expectSerializableDefinition.md +0 -10
  72. package/dist/docs/reference/index/expectValidParts.md +0 -19
  73. package/dist/docs/reference/index/withModel.md +0 -17
  74. package/dist/engine.d.ts.map +0 -1
  75. package/dist/engine.js.map +0 -1
  76. package/dist/model.d.ts +0 -17
  77. package/dist/model.d.ts.map +0 -1
  78. package/dist/model.js +0 -22
  79. package/dist/model.js.map +0 -1
  80. package/dist/runner.d.ts +0 -38
  81. package/dist/runner.d.ts.map +0 -1
  82. package/dist/runner.js +0 -130
  83. package/dist/runner.js.map +0 -1
  84. package/dist/snapshot-scope.d.ts +0 -4
  85. package/dist/snapshot-scope.d.ts.map +0 -1
  86. package/dist/snapshot-scope.js +0 -10
  87. package/dist/snapshot-scope.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,164 @@
1
1
  # @metamesh/testkit
2
2
 
3
+ ## 0.18.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 2eea694: Consolidate model authoring, execution, and testing around fluent shapes and durable immutable
8
+ results. Upgrade all four packages together; these Preview API changes have no compatibility
9
+ aliases. Rebuild compiled Generators for module format 5 and Modeling runtime major 11. Older
10
+ module formats and incompatible runtime versions are rejected before execution.
11
+
12
+ ### Modeling imports and operations
13
+
14
+ | Previous API | 0.18 API |
15
+ | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
16
+ | `body.subtract([cutter])` for a single operand | `body.subtract(cutter)`; fluent `union`, `intersect`, and `subtract` accept one shape or a readonly array |
17
+ | `compose(shapes)` | `union(shapes)` |
18
+ | Free shape inspection, emptiness, component, and anchor queries | `shape.inspect()`, `shape.isEmpty()`, `shape.components()`, and `shape.anchor(name)` |
19
+ | Free Solid distance/segment queries and splitting functions | `solid.distance(other)`, `solid.castSegment(...)`, `solid.split(cutter)`, and `solid.splitByPlane(plane)` |
20
+ | `solid.toTriangleMesh()` | `solid.toMesh()` |
21
+ | Named `mesh` import from `/geometry`, or standalone triangle-mesh functions | `import * as mesh from "@metamesh/modeling/geometry/mesh"` |
22
+ | Standalone `immutableMesh(...)` | `mesh.immutable(...)` |
23
+ | `helicalThreadRidgeMesh`, `helicalThreadSolidMesh`, and `preflightHelicalThreadSolidMesh` | `mesh.threadRidge`, `mesh.threadSolid`, and `mesh.preflightThreadSolid` |
24
+ | `HelicalThreadRidgeMeshOptions`, `HelicalThreadSolidMeshOptions`, and `HelicalThreadSolidMeshPreflight` | `ThreadRidgeOptions`, `ThreadSolidOptions`, and `ThreadSolidPreflight`, exported from the mesh module |
25
+ | Mesh `connectedComponentCount` | `shellCount`; native inspection `componentCount` still counts material components |
26
+ | Inspection extrema on the inspection result | Immutable `inspection.bounds.min` and `inspection.bounds.max` |
27
+ | `starContour(outerRadius, points, innerRadius, limits)` | `starContour({ outerRadius, innerRadius, points, limits })` |
28
+
29
+ Free `union(shapes)` and `intersect(shapes)` remain for collections of peers and reject empty
30
+ collections. Fluent Boolean methods with an empty array return the receiver.
31
+
32
+ Use `section.extrude(options)` in fluent modeling, `extrude(profile, options)` for generic
33
+ `Section | CorrespondingProfile` inputs, and `mesh.extrude(contour, options)` for pure triangle
34
+ buffers. The same fluent/generic distinction applies to revolution and sweeping. Pure extrusion
35
+ uses `ExtrudeMeshOptions` and rejects `ends`; use Section extrusion for native end treatments.
36
+ Construction, transforms, and splitting remain deferred recipes; observations and `toMesh()`
37
+ require active model execution.
38
+
39
+ Point-loop and arbitrary Section lofts default to direct correspondence when the method is
40
+ omitted; known primitive landmarks remain preserved. Dimension inputs accept fluent vectors.
41
+ Tube sizing accepts complete inner/outer radius or diameter pairs. Both star factories require
42
+ an explicit inner radius and support degree rotation; use `innerRadius: outerRadius / 2` to retain
43
+ the contour helper's former default.
44
+
45
+ Rod and internal-cutter `bevelBottom`, `bevelTop`, and `bevelSize` become `bevel`. The shared
46
+ `Bevel` contract accepts a nonnegative size, `"auto"`, or a readonly `[bottom, top]` pair; zero
47
+ disables an end and omission preserves factory defaults. Complete-thread mesh builders use the
48
+ same contract, with thread termination under `ends`. Nuts replace bevel selection, `chamferSize`,
49
+ and `flushBuildPlateBottom` with independent `innerBevel` and `outerBevel`. For a flat outside
50
+ bottom that retains its inner opening bevel, use `outerBevel: [0, "auto"]`. Nut preflight exposes
51
+ resolved inner/outer pairs and checks face walls pairwise; each end's reservation and automatic
52
+ sizing are resolved independently, including internal-cutter axial extension.
53
+
54
+ Primitive contours and their points are immutable and can be explicit `computed` dependencies.
55
+ Copy the outer array and any points before editing. Geometry errors are available from the
56
+ Modeling root; operation option/result types are exported beside their owning operations.
57
+ Topology analysis with `includeTopology: true`, finalized parts, and local geometry resources
58
+ include required `shellCount` and `edgeCount`. Bounds construction options describe inputs only;
59
+ existing fluent bounds remain accepted.
60
+
61
+ ### Part placement and result ownership
62
+
63
+ Replace `part(id, { geometry, position, rotation })` with
64
+ `part(id, { geometry, transform })`. The optional transform accepts a fluent `transform3()` value,
65
+ a row-major 16-number matrix, or a computed reader; omission means identity. Pattern and
66
+ attachment matrices pass directly to `part()`. Only rigid placement is supported: scale, shear,
67
+ reflection, perspective, and non-finite values are rejected. Geometry-only and geometry-or-options
68
+ union inputs remain accepted without casts.
69
+
70
+ Use `PartDeclaration` for authored parts. Replace `ModelSnapshot` / `FinalizedModel` with
71
+ `ModelResult`, and `SnapshotPart` / `FinalizedPart` with `ModelPart`. `engine.run()`, `session.run()`,
72
+ and Testkit's `runModel()` return durable immutable results. Dispose sessions and runners to release their
73
+ caches; completed results remain valid and need no disposal. `model.part(id)` returns a required
74
+ semantic part or throws with available IDs; `model.parts` preserves output order.
75
+
76
+ Finalized buffers expose stable, iterable `ImmutableBuffer` values. Use `.copy()` for mutable
77
+ storage. A `ModelPart`'s top-level positions and indices are already in world space; apply its
78
+ immutable `transform` only to the reusable local buffers under `geometry`. Worker deliveries also
79
+ nest local resources under `geometry`. Host integrations use `ModelDeliveryEncoder`,
80
+ `PartDeliveryDecoder`, and `toWorldMeshes` for owned transfer and manufacturing output.
81
+ Replace `engine.export3mf(...)` with standalone `export3mf(parts, options)` from `/engine`, which
82
+ accepts completed meshes with explicit resource limits, independently of engine initialization.
83
+
84
+ Statistics rename `volumeMm3` → `signedVolume`, `finalizationMs` → `finalizeMs`, and
85
+ `generationMs` → `generateMs`; `buildMs` measures declarations.
86
+ `ModelResult.stats.byteCount` means bytes occupied by finalized world-space position and index buffers,
87
+ counting shared buffers once. Worker statistics preserve engine `generateMs`; host elapsed time
88
+ is `timings.totalMs`, with `paramsMs` for parameter work. Other host timing stages are optional:
89
+ an omitted stage is unmeasured.
90
+
91
+ Model parameter roots must be object maps. Captured parameters and computed results expose
92
+ deeply readonly `ImmutableValue<T>` views; supported mutable caller input is still accepted and
93
+ recaptured on every revision, including mutable children inside frozen objects. Deeply immutable
94
+ data retains identity reuse. Assertions and warnings accept bounded immutable nested `path`
95
+ metadata. Replace `validateModel` with `checkModel` and session/runner `.validate()` with `.check()`.
96
+ These check declarations and reached assertions without finalizing geometry; unexpected execution
97
+ failures still throw.
98
+
99
+ ### Generator SDK and Testkit
100
+
101
+ | Previous API | 0.18 API |
102
+ | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
103
+ | Nested compiled Generator module | Flat format-5 model program; bind an existing program with `defineGeneratorModule({ definition, program })` |
104
+ | `isGeneratorModule(value)` | `parseGeneratorModule(value, definition)` |
105
+ | `executeGenerator({ ..., parsedParameters })` | `executeGenerator({ ..., parameters })`; current-definition validation always runs |
106
+ | Callback-scoped `withModel`, `ModelTestOptions`, or `runner.withModel` | `await runModel(programOrCallback, ...)` for one-off results; explicit sessions or Generator runners for repeated edits |
107
+ | Generator test `runner.execute(...)` | `runner.run(...)`, returning `GeneratorTestResult` |
108
+ | `expectSerializableDefinition` | `assertValidDefinition` |
109
+ | `expectValidDefaults`, `expectValidPresets`, and `expectValidParts` | `assertValidDefaults`, `assertValidPresets`, and `assertValidParts` |
110
+ | `expectMeshMeasurements` | `assertMeshMeasurements` |
111
+ | `canonicalizeParameters(definition, parameters)` from `/parameters` | `canonicalizeParameters(parameters)` from `/runtime` |
112
+ | `GeneratedPartsDecoder`, `parseGeneratedParts`, and `GeneratedPartsLimits` | `PartDeliveryDecoder`, `parseModelParts`, and `PartDeliveryLimits` |
113
+ | `GeneratedPart` and `GeneratedModel` | `ModelPartData` and `ModelData` |
114
+ | `GeneratedPartDelivery` and `GeneratedModelDelivery` | `PartDelivery` and `ModelDelivery` |
115
+
116
+ Testkit `runModel` accepts existing `ModelProgram` values and synchronous inline callbacks;
117
+ typed callbacks use `runModel<Parameters, Services>`. Its definition-bound Generator overload
118
+ validates inputs and prepares services. The SDK Modeling adapter adds definition-inferred
119
+ `GeneratorModel` and `parseGeneratorModel`. Ordinary model tests preserve definition-inferred
120
+ input types. Reusable Generator runners accept physical generation policy plus `cache` and
121
+ `verifyCache` for edit sequences; dispose the runner after use.
122
+
123
+ Generator execution and ordinary tests strictly require complete canonical parameter maps.
124
+ Use the parameter codec for strict input and `normalizeParameters` for forgiving recovery;
125
+ replace `prepareParameters`, `validateParameters`, and `PreparedParameters` with
126
+ `createParamCodec(definition).parse(...)` or `.safeParse(...)`. Schema adapters remain private.
127
+ Codec failures provide structured issues without a substitute parameter map. For deliberate
128
+ malformed-input assertion probes, replace `runner.validate(parameters, { normalize: false })`
129
+ with `runner.check(parameters, { validateInput: false })`.
130
+ Defaults are selected only by omission or `undefined` where supported; a `null` parameter map is
131
+ rejected. Parameterless model calls can omit the empty map. Definition and preset helpers catch
132
+ nested key typos and validate immediately while retaining literal inference.
133
+
134
+ `assertValidParts` checks the supplied world-space buffers, closed topology, and exact agreement
135
+ with local geometry under `transform`; it no longer hides corrupted output by reconstructing it.
136
+ Always await `assertValidParts(parts, engine)` (or omit the engine): failures reject, and supplying
137
+ an engine changes resource reuse only.
138
+ `assertValidDefinition` also checks the canonical JSON round trip. New `assertEqualBuffer` and
139
+ `assertEqualMesh` compare exact ordered contents without copying; equivalent shapes with different
140
+ triangulations can differ. `ContentMismatchError` identifies the first differing element or
141
+ length, while malformed input and reader failures retain their errors. Optional `contentMatchers`
142
+ support `expect.extend`, including negation, without a test-framework dependency.
143
+
144
+ ### CLI and package requirements
145
+
146
+ Rename the type-only CLI command `metamesh check` to `metamesh typecheck`; no alias is retained.
147
+ Node authoring APIs and Modeling/Testkit declaration-check methods retain their names. Generator
148
+ runs use `overrides` / `--overrides`, merged with defaults before strict parsing; standalone models
149
+ use `params` / `--params`. Supplying the other entry kind's input option is rejected.
150
+
151
+ Captured runs use format 2 with transform-only placement. The bundled capture renderer resolves
152
+ from the installed CLI package so published installations can render captures.
153
+ Public packages require Node.js 24 or newer, ESM imports, and TypeScript 6.0 or newer with strict
154
+ checking for TypeScript consumers.
155
+
156
+ ### Patch Changes
157
+
158
+ - Updated dependencies [2eea694]
159
+ - @metamesh/modeling@0.18.0
160
+ - @metamesh/generator-sdk@0.18.0
161
+
3
162
  ## 0.17.0
4
163
 
5
164
  ### Minor Changes
package/README.md CHANGED
@@ -1,146 +1,154 @@
1
1
  # `@metamesh/testkit`
2
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.
3
+ Test MetaMesh models and Generators with their production engine. Check definitions, presets,
4
+ geometry, and physical measurements with any test runner.
5
5
 
6
6
  > **Preview:** `0.x` minor releases may break compatibility. Patches remain compatible within the
7
7
  > same minor line.
8
8
 
9
9
  ## Installation
10
10
 
11
- Install the same exact SDK, Modeling, and Testkit release. Testkit is a development dependency:
11
+ Install matching SDK, Modeling, and Testkit releases. Testkit is a development dependency:
12
12
 
13
13
  ```bash
14
14
  pnpm add @metamesh/generator-sdk @metamesh/modeling
15
15
  pnpm add -D @metamesh/testkit
16
16
  ```
17
17
 
18
- ## Execute models in tests
18
+ The package publishes ES modules only. Use Node.js 24 or newer. TypeScript consumers need
19
+ TypeScript 6.0 or newer, `strict` checking, and `NodeNext` or `Bundler` module resolution.
19
20
 
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):
21
+ Testkit has no test-framework, compiler, renderer, or browser dependency. For source checking,
22
+ captured runs, or images, use [CLI](https://github.com/JasonKoolman/metamesh/blob/main/packages/cli/README.md).
22
23
 
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
- await runner.withModel(getDefaultParameters(definition), async (model) => {
32
- await expectValidParts(model.parts);
33
- });
34
- } finally {
35
- runner.dispose();
36
- }
37
- ```
38
-
39
- `withModel` normalizes values, prepares services, and runs the persistent session. It awaits the
40
- callback, returns its result, and disposes the snapshot even when assertions throw or reject.
41
- Schema or generation assertion failures throw `GenerationError` with their structured diagnostics.
42
- Unexpected execution and malformed-output errors retain their original failures. The runner's
43
- session and caches remain reusable until `runner.dispose()`.
24
+ ## Test a model
44
25
 
45
- For a plain model program, import `withModel` from Testkit:
26
+ Build a plate, check its volume and shell count, then verify native reconstruction:
46
27
 
47
28
  ```ts
48
- import { box, generate } from "@metamesh/modeling";
49
- import { expectValidParts, withModel } from "@metamesh/testkit";
29
+ import { box } from "@metamesh/modeling";
30
+ import { assertMeshMeasurements, assertValidParts, runModel } from "@metamesh/testkit";
50
31
 
51
- const model = generate<{ width: number }>(({ params, part }) =>
52
- part("plate", box({ size: [params.width, 20, 4] }))
32
+ const model = await runModel<{ width: number }>(
33
+ ({ params, part }) => part("plate", box({ size: [params.width, 20, 4] })),
34
+ { width: 30 }
53
35
  );
54
- await withModel(model, { width: 30 }, async (snapshot) => {
55
- await expectValidParts(snapshot.parts);
56
- });
57
- ```
58
-
59
- The plain-model helper also disposes its temporary session. Its optional fourth argument accepts
60
- session policy, prepared `services`, and a test-owned `engine`; declared services are required.
61
- It passes model parameters directly without Generator normalization and never disposes the engine.
62
- Previously obtained parts remain usable after snapshot disposal; returning parts does not eagerly
63
- copy their buffers.
64
-
65
- Snapshot parts include session-specific geometry resource identities. Compare manufacturing
66
- fields such as world positions, indices, measurements, IDs and colors for equality across runs.
67
- Each positions or indices read copies its buffer; capture the buffer once before a dense loop.
68
-
69
- Use `runner.execute` for explicit snapshot ownership or invalid-result assertions. It returns
70
- `invalid` for schema or generation assertion errors. Dispose successful snapshots separately from
71
- the runner; captured snapshots remain valid after runner disposal.
72
-
73
- Use `runner.validate(parameters, { normalize: false })` to probe deliberately invalid typed values
74
- without finalizing parts. It checks declarations and reached assertions; observing geometry can
75
- still initialize the engine. Creating a runner alone loads no engine or assets. Pass `options.engine`
76
- to reuse a test-owned engine and `options.limits` to lower host ceilings.
77
-
78
- ## Assertions
79
-
80
- Helpers throw on failure without depending on your test framework:
81
36
 
82
- | Helper | Checks |
83
- | ------------------------------ | ------------------------------------------------------------------ |
84
- | `expectSerializableDefinition` | Strict parsing and a canonical JSON round trip |
85
- | `expectValidDefaults` | Strict parameter decoding and agreement with definition defaults |
86
- | `expectValidPresets` | Serializable preset metadata; use the runner for domain assertions |
87
- | `expectValidParts` | Strict part metadata, closed topology, and native reconstruction |
88
- | `expectMeshMeasurements` | Bounds, area, signed volume, and connected-component count |
89
-
90
- `expectValidParts(parts, engine)` is synchronous and uses that engine's limits. Without an engine,
91
- it returns a promise using the shared test engine and default limits. It also accepts finalized
92
- parts, stripping measurement facts before strict validation; other unknown fields reject.
93
- Snapshot inputs retain shared local mesh buffers and rigid placements in the returned parts.
94
-
95
- Compare physical measurements with explicit tolerances. For a 30 × 20 × 4 mm box mesh:
96
-
97
- ```ts
98
- import { expectMeshMeasurements } from "@metamesh/testkit";
99
-
100
- expectMeshMeasurements(
101
- mesh,
102
- { signedVolume: 30 * 20 * 4, connectedComponentCount: 1 },
37
+ assertMeshMeasurements(
38
+ model.part("plate"),
39
+ { signedVolume: 2400, shellCount: 1 },
103
40
  { signedVolume: 0.05 }
104
41
  );
42
+ await assertValidParts(model.parts);
105
43
  ```
106
44
 
107
- Bounds use mm, area mm², and volume mm³. Tolerances are absolute and default to zero; component
108
- counts are exact. Measurements check closed oriented topology without a native engine. Matching
109
- measurements alone do not establish geometric equivalence or exclude self-intersections; use
110
- `expectValidParts` for native reconstruction.
111
-
112
- ## Font fixtures
45
+ Helpers report failures without registering global assertions. `runModel` returns durable,
46
+ immutable parts, measurements, diagnostics, and dependencies; the result needs no cleanup.
47
+ Use `model.part(id)` for a required semantic part or `model.parts` for iteration and export.
48
+
49
+ Always await `assertValidParts(parts, engine)`: it resolves to the same parts or rejects on failure.
50
+ A supplied engine is reused; omission lazily initializes the shared test engine.
51
+ It checks the supplied world-space buffers for closed topology, then requires their positions and
52
+ indices to exactly match local geometry reconstructed with the declared rigid transform.
53
+ A valid local mesh cannot conceal corrupted or inconsistent world-space output.
54
+
55
+ Pass an existing Modeling program directly: `await runModel(program, parameters)` uses the same
56
+ program and parameter types as `engine.run`. A synchronous generation callback is also accepted;
57
+ without parameters, no type argument or wrapper is needed:
58
+ `await runModel(({ part }) => part("cube", box({ size: 2 })))`.
59
+ Parameters retain the program or callback's declared type; use
60
+ `GenerateCallback<Parameters, Services>` for a reusable callback or supply
61
+ `runModel<Parameters, Services>` inline. Options stay in the third argument; use `undefined` for
62
+ omitted parameters when supplying an engine, limits, or prepared services.
113
63
 
114
- Supply `prepareServices` in runner options for models with fonts. It receives the definition and
115
- current parameters, and can return services synchronously or asynchronously. Missing fixtures or
116
- service failures reject before generation. A different services object starts a fresh session;
117
- return the same immutable object when capabilities are unchanged to retain computation caches.
118
-
119
- `prepareFontTestServices` from `/fonts` checks immutable font revisions and prepares services from
120
- checked-in bytes. Install Modeling's optional `fontkit` peer, plus `woff2-encoder` for WOFF2 fixtures.
121
- Tests need no font downloads or browser cache; retain the fixtures' licenses.
64
+ ## Assertions
122
65
 
123
- For local JSON fixture descriptors, `loadFontFixtureServices` from
124
- `@metamesh/testkit/font-fixtures` returns the runner's `prepareServices` adapter. Descriptor paths
125
- resolve beside the JSON file, and every file's SHA-256 must match its declared selection revision.
126
- `loadFontFixtures` additionally returns the verified selections. These loaders are Node-only;
127
- use `/fonts` when the host already supplies the bytes.
66
+ | Helper | Checks |
67
+ | ------------------------ | -------------------------------------------------------------- |
68
+ | `assertValidDefinition` | Strict parsing and a canonical JSON round trip. |
69
+ | `assertValidDefaults` | Strict decoding and agreement with definition defaults. |
70
+ | `assertValidPresets` | Complete, normalized preset metadata. |
71
+ | `assertValidParts` | Part metadata, closed topology, and native reconstruction. |
72
+ | `assertMeshMeasurements` | Bounds, surface area, signed volume, and surface shell count. |
73
+ | `assertEqualBuffer` | Exact ordered numeric buffer contents without copying storage. |
74
+ | `assertEqualMesh` | Exact positions and indices, independently of mesh metadata. |
75
+
76
+ `assertValidDefinition` requires strict SDK parsing and a canonical JSON round trip; it does not
77
+ execute the Generator. Check model assertions and domain constraints through the Generator runner.
78
+
79
+ Measurement tolerances are absolute: millimetres for bounds, mm² for area, and mm³ for volume.
80
+ They default to zero; shell counts are exact. Matching measurements do not prove geometric
81
+ equivalence or rule out self-intersections. Use native reconstruction checks alongside them.
82
+
83
+ Use `assertEqualBuffer(actual, expected)` or `assertEqualMesh(actual, expected)` directly without a
84
+ test framework. They read `length` and `at(index)` without copying storage and throw
85
+ `ContentMismatchError` with the first differing index or length. Malformed representations throw
86
+ `TypeError`; reader failures propagate. Numeric equality uses `Object.is`: `NaN` equals `NaN` and
87
+ signed zero differs. Mesh comparisons ignore metadata and require identical position and index
88
+ contents. Geometrically equivalent meshes with different triangulation or ordering can fail.
89
+
90
+ Register the thin optional adapters with your runner's `expect.extend(contentMatchers)` to use
91
+ `toEqualBuffer` and `toEqualMesh`, including `.not`. Only `ContentMismatchError` becomes a failed
92
+ matcher result; invalid inputs and unexpected errors still throw. Follow your runner's
93
+ [matcher extension guidance](https://vitest.dev/guide/extending-matchers) for TypeScript declarations.
94
+
95
+ ## Test Generators and repeated edits
96
+
97
+ For a module exporting its definition and default runtime, pass
98
+ `runModel({ definition, runtime }, parameters)`. Omit parameters or pass `undefined` to use defaults;
99
+ all other supplied Generator inputs have the definition's inferred types and must form a complete
100
+ canonical map. Use `runner.run(record)` to test unknown keys, missing fields, or wrong value types.
101
+ For one changed value, spread
102
+ `getDefaultParameters(definition)` and then apply the override; the runner does not merge defaults. The overload strictly parses inputs and prepares
103
+ services. Use SDK `normalizeParameters` explicitly when recovering saved values. Plain model
104
+ parameters pass through directly.
105
+
106
+ Generator integration tests should import the actual entry point instead of repeating its input
107
+ resolution and builder wiring. Use a direct callback for isolated construction or mesh reconstruction.
108
+ For a deliberate schema bypass, `runModel(runtime, parameters, { services })` executes
109
+ the Generator's model behavior without claiming those values pass its parameter schema.
110
+ See the [SDK example](https://github.com/JasonKoolman/metamesh/blob/main/packages/generator-sdk/README.md#define-controls).
111
+
112
+ Use `createGeneratorTestRunner(definition, runtime)` for repeated parameter cases or cache tests.
113
+ Its `run` method returns a generated result or structured validation failure. `check` probes
114
+ declarations and reached assertions without finalizing parts; geometry observations can still
115
+ require the engine. Dispose the runner in `finally`; returned results remain usable.
116
+ Use `check(parameters, { validateInput: false })` only to probe model assertions with deliberately
117
+ invalid typed values, bypassing the parameter schema.
118
+
119
+ For models using `computed`, include repeated-edit tests with `{ verifyCache: true }` on the runner.
120
+ Change geometry inputs and placement inputs independently. Verification reruns cached calculations
121
+ and rejects changed results without tracked dependencies, including accidentally captured destructured
122
+ parameters. Read parameters inside the computation or list changing outer values in its dependency
123
+ array. Verification is a bounded development probe; unsupported captures or large results can
124
+ require comparison with `{ cache: false }` on a separate runner. It cannot prove arbitrary JavaScript.
125
+ Keep prepared service identity stable for unchanged assets; replacing services creates a new session
126
+ and prevents testing cache reuse. Isolated `runModel` calls do not verify repeated-edit correctness.
127
+
128
+ For plain models, use `engine.createSession(program, options)` for repeated edits or cache tests
129
+ and dispose the session in `finally`. Session results remain usable after later runs and disposal.
130
+ Both `runModel` and Generator runners can reuse a test-owned engine and lower its resource ceilings.
131
+ They accept the same physical `resolution`, `meshValidation`, and `meshTopologyMode` policy.
132
+
133
+ ## Fonts and entry points
134
+
135
+ | Import | Responsibility |
136
+ | --------------------------------- | ------------------------------------------------------------------------------ |
137
+ | `@metamesh/testkit` | Model execution, Generator runners, assertions, and optional content matchers. |
138
+ | `@metamesh/testkit/fonts` | Prepared font services from supplied fixture bytes. |
139
+ | `@metamesh/testkit/font-fixtures` | Node-only JSON fixture loading with SHA-256 verification. |
140
+
141
+ Font-dependent Generators receive a `prepareServices` callback before generation. Tests use
142
+ checked-in bytes without CDN access; retain their licenses. Font preparation needs Modeling's
143
+ optional `fontkit` peer, plus `woff2-encoder` for WOFF2 fixtures.
128
144
 
129
145
  ## Documentation
130
146
 
131
- Resolve `@metamesh/testkit/docs/manifest.json` for this installed version's Markdown
132
- reference and testing guidance. Testkit has no compiler, bundler, renderer, or browser dependencies.
133
- It shares the Modeling engine and Generator SDK contracts rather than duplicating runtime rules.
134
-
135
- For source checking, captured runs, documentation lookup, and images, install
136
- [`@metamesh/cli`](https://github.com/JasonKoolman/metamesh/blob/main/packages/cli/README.md).
137
- Its executable is `metamesh`; reusable Node authoring functions live in `@metamesh/cli/authoring`.
138
-
139
- - [Generator SDK](https://github.com/JasonKoolman/metamesh/blob/main/packages/generator-sdk/README.md) — definitions, parameter values, and module authoring.
140
- - [Modeling](https://github.com/JasonKoolman/metamesh/blob/main/packages/modeling/README.md) — geometry, sessions, and snapshots.
141
- - [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`.
142
-
143
- For package development, see [Contributing](https://github.com/JasonKoolman/metamesh/blob/main/CONTRIBUTING.md).
147
+ Resolve `@metamesh/testkit/docs/manifest.json` for exact-version Markdown guidance and annotated
148
+ API references. With CLI installed, read `pnpm exec metamesh docs show testkit/guide/testing`.
149
+ See [Modeling](https://github.com/JasonKoolman/metamesh/blob/main/packages/modeling/README.md)
150
+ for geometry and [Contributing](https://github.com/JasonKoolman/metamesh/blob/main/CONTRIBUTING.md)
151
+ for package development.
144
152
 
145
153
  ## License
146
154
 
@@ -1,20 +1,13 @@
1
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;
2
+ import type { ModelEngine, ModelPart } from "@metamesh/modeling/engine";
3
+ /** Strictly parses a definition and requires its JSON round trip to retain the canonical package representation. */
4
+ export declare function assertValidDefinition(definition: GeneratorDefinition): void;
7
5
  /** 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;
6
+ export declare function assertValidDefaults<const D extends GeneratorDefinition>(definition: D, defaults: GeneratorParams<D>): void;
9
7
  /** 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 parts without measurement facts, retaining shared snapshot resources and placement.
13
- * Runs mesh reconstruction/finalization synchronously using the supplied engine.
8
+ export declare function assertValidPresets<const D extends GeneratorDefinition>(definition: D, presets: readonly GeneratorPreset<D>[]): void;
9
+ /** Validates supplied world meshes and their exact agreement with reconstructed local geometry and placement.
10
+ * Resolves to the same parts or rejects on failure. A supplied engine is reused; otherwise the shared engine initializes lazily.
14
11
  */
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[]>;
12
+ export declare function assertValidParts(parts: readonly ModelPart[], engine?: ModelEngine): Promise<readonly ModelPart[]>;
20
13
  //# sourceMappingURL=assertions.d.ts.map
@@ -1 +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,EAAqB,MAAM,oBAAoB,CAAC;AACrF,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"}
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;AAOjC,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AA2BxE,oHAAoH;AACpH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,mBAAmB,GAAG,IAAI,CAU3E;AACD,iGAAiG;AACjG,wBAAgB,mBAAmB,CAAC,KAAK,CAAC,CAAC,SAAS,mBAAmB,EACrE,UAAU,EAAE,CAAC,EACb,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC,GAC3B,IAAI,CAQN;AACD,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;AACD;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,SAAS,SAAS,EAAE,EAC3B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,SAAS,SAAS,EAAE,CAAC,CA6B/B"}
@@ -1,8 +1,9 @@
1
1
  import { parseGeneratorDefinition, validateGeneratorPresets, } from "@metamesh/generator-sdk/packages";
2
2
  import { createParamCodec, getDefaultParameters } from "@metamesh/generator-sdk/parameters";
3
- import { parseGeneratedParts } from "@metamesh/generator-sdk/runtime";
4
3
  import { generate } from "@metamesh/modeling";
5
- import { getTestEngine } from "./engine.js";
4
+ import * as mesh from "@metamesh/modeling/geometry/mesh";
5
+ import { assertEqualMesh } from "./content-assertions.js";
6
+ import { getTestEngine } from "./test-engine.js";
6
7
  function stringify(value, label) {
7
8
  try {
8
9
  const serialized = JSON.stringify(value);
@@ -26,8 +27,8 @@ function sortJson(value) {
26
27
  function stableStringify(value, label) {
27
28
  return stringify(sortJson(value), label);
28
29
  }
29
- /** Throws unless a definition already has the canonical package-serializable representation. */
30
- export function expectSerializableDefinition(definition) {
30
+ /** Strictly parses a definition and requires its JSON round trip to retain the canonical package representation. */
31
+ export function assertValidDefinition(definition) {
31
32
  parseGeneratorDefinition(definition);
32
33
  const decoded = JSON.parse(stringify(definition, "Generator definition"));
33
34
  const parsed = parseGeneratorDefinition(decoded);
@@ -37,7 +38,7 @@ export function expectSerializableDefinition(definition) {
37
38
  }
38
39
  }
39
40
  /** Throws unless defaults strictly decode and equal the defaults derived from the definition. */
40
- export function expectValidDefaults(definition, defaults) {
41
+ export function assertValidDefaults(definition, defaults) {
41
42
  const parsed = createParamCodec(definition).parse(defaults);
42
43
  if (stableStringify(parsed, "Generator defaults") !==
43
44
  stableStringify(getDefaultParameters(definition), "Derived Generator defaults")) {
@@ -45,74 +46,27 @@ export function expectValidDefaults(definition, defaults) {
45
46
  }
46
47
  }
47
48
  /** Checks preset metadata. Validate domain assertions through the generation test runner. */
48
- export function expectValidPresets(definition, presets) {
49
+ export function assertValidPresets(definition, presets) {
49
50
  validateGeneratorPresets(definition, presets);
50
51
  }
51
- export function expectValidParts(value, engine) {
52
- if (engine === undefined)
53
- return getTestEngine().then((host) => expectValidParts(value, host));
54
- const meshes = new WeakMap();
55
- const wireValue = Array.isArray(value)
56
- ? value.map((part, index) => {
57
- if (typeof part !== "object" || part === null || !Object.hasOwn(part, "measurements"))
58
- return part;
59
- const prototype = Object.getPrototypeOf(part);
60
- if (prototype !== null && prototype !== Object.prototype)
61
- return part;
62
- const descriptors = Object.getOwnPropertyDescriptors(part);
63
- if (Object.keys(descriptors).some((key) => ![
64
- "id",
65
- "positions",
66
- "indices",
67
- "color",
68
- "measurements",
69
- "geometry",
70
- "position",
71
- "rotation",
72
- ].includes(key)))
73
- return part;
74
- const resource = descriptors["geometry"];
75
- if (resource !== undefined && !("value" in resource))
76
- return part;
77
- const geometry = resource?.value;
78
- const source = typeof geometry === "object" && geometry !== null
79
- ? geometry
80
- : part;
81
- // Snapshot getters return copies. Read each local resource once to retain shared storage.
82
- let mesh = meshes.get(source);
83
- if (mesh === undefined) {
84
- mesh = { positions: source.positions, indices: source.indices };
85
- meshes.set(source, mesh);
86
- }
87
- descriptors["positions"] = { value: mesh.positions, enumerable: true };
88
- descriptors["indices"] = { value: mesh.indices, enumerable: true };
89
- if (source === part) {
90
- delete descriptors["position"];
91
- delete descriptors["rotation"];
92
- }
93
- delete descriptors["measurements"];
94
- delete descriptors["geometry"];
95
- return Object.defineProperties({
96
- geometryId: `assertion-${index}`,
97
- geometryRevision: 0,
98
- position: [0, 0, 0],
99
- rotation: [0, 0, 0],
100
- }, descriptors);
101
- })
102
- : value;
103
- const parts = parseGeneratedParts(wireValue, engine.limits);
104
- const session = engine.createSession(generate(({ part }) => parts.map((mesh) => part(mesh.id, {
105
- geometry: mesh,
106
- position: mesh.position,
107
- rotation: mesh.rotation,
108
- ...(mesh.color === undefined ? {} : { color: mesh.color }),
109
- }))));
110
- try {
111
- session.run({}).dispose();
112
- }
113
- finally {
114
- session.dispose();
52
+ /** Validates supplied world meshes and their exact agreement with reconstructed local geometry and placement.
53
+ * Resolves to the same parts or rejects on failure. A supplied engine is reused; otherwise the shared engine initializes lazily.
54
+ */
55
+ export async function assertValidParts(parts, engine) {
56
+ const host = engine ?? (await getTestEngine());
57
+ for (const part of parts) {
58
+ const unknown = Reflect.ownKeys(part).find((key) => typeof key !== "string" ||
59
+ !["id", "positions", "indices", "color", "measurements", "geometry", "transform"].includes(key));
60
+ if (unknown !== undefined)
61
+ throw new TypeError('Model part contains unknown field "' + String(unknown) + '".');
62
+ mesh.validate(part, { requireClosed: true });
115
63
  }
64
+ const reconstructed = host.run(generate(({ part }) => parts.map((value) => part(value.id, {
65
+ geometry: value.geometry,
66
+ transform: value.transform,
67
+ ...(value.color === undefined ? {} : { color: value.color }),
68
+ }))), undefined, { meshTopologyMode: "original" });
69
+ parts.forEach((part, index) => assertEqualMesh(part, reconstructed.parts[index]));
116
70
  return parts;
117
71
  }
118
72
  //# sourceMappingURL=assertions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"assertions.js","sourceRoot":"","sources":["../src/assertions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"assertions.js","sourceRoot":"","sources":["../src/assertions.ts"],"names":[],"mappings":"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"}