@metamesh/testkit 0.0.0-stage → 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/LICENSE +200 -0
- package/README.md +112 -2
- 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 +55 -3
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/LICENSE
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice.
|
|
187
|
+
|
|
188
|
+
Copyright 2026 MetaMesh
|
|
189
|
+
|
|
190
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
191
|
+
you may not use this file except in compliance with the License.
|
|
192
|
+
You may obtain a copy of the License at
|
|
193
|
+
|
|
194
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
195
|
+
|
|
196
|
+
Unless required by applicable law or agreed to in writing, software
|
|
197
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
198
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
199
|
+
See the License for the specific language governing permissions and
|
|
200
|
+
limitations under the License.
|
package/README.md
CHANGED
|
@@ -1,3 +1,113 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `@metamesh/testkit`
|
|
2
2
|
|
|
3
|
-
|
|
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
|