@pixel-point/toolcraft 0.0.17 → 0.0.18
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/package.json +1 -1
- package/src/generate-test-doc-assertions.mjs +58 -68
- package/src/generate-test-doc-assertions.test.mjs +43 -0
- package/src/generate-test-doc-policy-assertions.mjs +92 -0
- package/src/generate-test-file-assertions.mjs +26 -75
- package/src/generate-test-product-iteration.test.mjs +17 -0
- package/src/generate-test-runtime-boundary-assertions.mjs +158 -0
- package/src/generate-test-standalone-assertions.mjs +10 -0
- package/templates/runtime/contracts/component-contracts.choices.test.ts +47 -3
- package/templates/runtime/contracts/component-contracts.choices.ts +48 -3
- package/templates/runtime/contracts/component-contracts.inputs.test.ts +6 -6
- package/templates/runtime/contracts/component-contracts.inputs.ts +6 -6
- package/templates/runtime/contracts/component-contracts.media-custom.test.ts +8 -2
- package/templates/runtime/contracts/component-contracts.media-custom.ts +8 -2
- package/templates/runtime/contracts/component-contracts.runtime-acceptance.test.ts +4 -4
- package/templates/runtime/contracts/component-contracts.runtime-labels.test.ts +7 -1
- package/templates/runtime/contracts/component-contracts.runtime-panels.test.ts +3 -0
- package/templates/runtime/contracts/component-contracts.runtime-shell.test.ts +3 -0
- package/templates/runtime/contracts/component-contracts.runtime.ts +12 -8
- package/templates/runtime/contracts/component-contracts.test.ts +2 -0
- package/templates/runtime/contracts/decision-contracts.test.ts +18 -0
- package/templates/runtime/contracts/decision-contracts.ts +10 -10
- package/templates/runtime/export/export-background.ts +0 -19
- package/templates/runtime/export/export.test.ts +45 -42
- package/templates/runtime/export/index.ts +44 -16
- package/templates/runtime/index.ts +2 -0
- package/templates/runtime/model-import/model-import-limits.ts +15 -4
- package/templates/runtime/react/app-shell/runtime-public-api.test.tsx +11 -1
- package/templates/runtime/react/app-shell/toolcraft-app.scene-export.test.tsx +29 -0
- package/templates/runtime/react/app-shell/toolcraft-app.tsx +18 -8
- package/templates/runtime/react/canvas/canvas-shell-rendering.test.tsx +76 -0
- package/templates/runtime/react/canvas/canvas-shell-test-utils.tsx +13 -1
- package/templates/runtime/react/canvas/canvas-shell.tsx +16 -1
- package/templates/runtime/react/canvas/product-scene-surface.test.tsx +195 -0
- package/templates/runtime/react/canvas/product-scene-surface.tsx +155 -0
- package/templates/runtime/react/canvas/runtime-scene-export.ts +1 -1
- package/templates/runtime/react/controls-panel/__tests__/control-conditions.test.ts +61 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.collection-actions.test.tsx +89 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.control-visibility.test.tsx +40 -19
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.scene-export-actions.test.tsx +1 -1
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.source-collection.test.tsx +62 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.source-color-bank.test.tsx +67 -0
- package/templates/runtime/react/controls-panel/actions/controls-panel-actions.ts +2 -4
- package/templates/runtime/react/controls-panel/actions/export-action-runner.ts +10 -4
- package/templates/runtime/react/controls-panel/conditions/control-conditions.ts +32 -119
- package/templates/runtime/react/controls-panel/layout/controls-panel-control-group.tsx +5 -2
- package/templates/runtime/react/controls-panel/layout/controls-panel-layout.tsx +10 -8
- package/templates/runtime/react/controls-panel/layout/controls-panel-section.tsx +3 -3
- package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-item-fields.test.tsx +63 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-item-fields.tsx +138 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-items.tsx +104 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-renderer.tsx +115 -236
- package/templates/runtime/react/controls-panel/renderers/controls-panel-file-drop-item-controls.test.tsx +95 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-file-drop-item-controls.tsx +82 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-media-renderer.test.tsx +73 -1
- package/templates/runtime/react/controls-panel/renderers/controls-panel-media-renderer.tsx +50 -1
- package/templates/runtime/react/controls-panel/renderers/controls-panel-renderer-registry.test.ts +1 -1
- package/templates/runtime/react/controls-panel/renderers/controls-panel-renderer-registry.ts +2 -1
- package/templates/runtime/react/controls-panel/values/controls-panel-collection-values.ts +38 -6
- package/templates/runtime/react/controls-panel/values/controls-panel-value-labels.ts +1 -0
- package/templates/runtime/react/index.ts +4 -0
- package/templates/runtime/react/model-rendering/model-export.ts +1 -1
- package/templates/runtime/react/orientation-gizmo/orientation-gizmo-selection.ts +5 -5
- package/templates/runtime/react/orientation-gizmo/use-toolcraft-orientation-control-selection.ts +2 -2
- package/templates/runtime/scene/scene-bounds.test.ts +23 -0
- package/templates/runtime/scene/scene-bounds.ts +31 -17
- package/templates/runtime/schema/app-capabilities.test.ts +4 -0
- package/templates/runtime/schema/collection-item-controls.ts +29 -0
- package/templates/runtime/schema/control-applicability.test.ts +127 -0
- package/templates/runtime/schema/control-applicability.ts +433 -0
- package/templates/runtime/schema/control-schema-normalization.ts +177 -11
- package/templates/runtime/schema/controls-panel-actions.ts +2 -2
- package/templates/runtime/schema/controls-panel-section-layout.ts +14 -9
- package/templates/runtime/schema/controls-panel-section-roundtrip.test.ts +59 -0
- package/templates/runtime/schema/define-toolcraft.collection-actions-item-controls.test.ts +127 -0
- package/templates/runtime/schema/define-toolcraft.control-sections.test.ts +10 -4
- package/templates/runtime/schema/define-toolcraft.file-drop-item-controls.test.ts +98 -0
- package/templates/runtime/schema/define-toolcraft.file-drop-normalization.test.ts +27 -0
- package/templates/runtime/schema/define-toolcraft.segmented-control-fit.test.ts +20 -2
- package/templates/runtime/schema/define-toolcraft.setup-canvas.test.ts +16 -3
- package/templates/runtime/schema/define-toolcraft.source-collection.test.ts +79 -0
- package/templates/runtime/schema/runtime-setup-section.ts +24 -5
- package/templates/runtime/schema/types.ts +68 -13
- package/templates/starter/AGENTS.md +12 -10
- package/templates/starter/docs/toolcraft/acceptance-testing.md +17 -31
- package/templates/starter/docs/toolcraft/agent-worklog.md +15 -0
- package/templates/starter/docs/toolcraft/assembly-workflow.md +10 -3
- package/templates/starter/docs/toolcraft/component-rules.md +8 -6
- package/templates/starter/docs/toolcraft/core/control-selection.md +9 -3
- package/templates/starter/docs/toolcraft/core/layout.md +7 -7
- package/templates/starter/docs/toolcraft/core/media-upload.md +2 -0
- package/templates/starter/docs/toolcraft/core/runtime-boundary.md +13 -2
- package/templates/starter/docs/toolcraft/core/setup-export.md +33 -7
- package/templates/starter/docs/toolcraft/custom-controls.md +6 -4
- package/templates/starter/docs/toolcraft/decision-contract.md +3 -1
- package/templates/starter/docs/toolcraft/renderer-technique.md +4 -0
- package/templates/starter/docs/toolcraft/schema-reference.md +21 -19
- package/templates/starter/e2e/app-browser-control-applicability-requirements.spec.ts +163 -0
- package/templates/starter/e2e/app-browser-infinity-canvas-evidence.spec.ts +7 -2
- package/templates/starter/e2e/app-browser-orientation-evidence.spec.ts +174 -21
- package/templates/starter/e2e/app-browser-runtime-requirements.spec.ts +1 -33
- package/templates/starter/e2e/app-browser-semantic-evidence.spec.ts +61 -15
- package/templates/starter/e2e/{browser-conditional-output-evidence-helpers.ts → browser-background-output-evidence.ts} +0 -68
- package/templates/starter/e2e/browser-control-applicability-evidence.ts +114 -0
- package/templates/starter/e2e/browser-infinity-canvas-evidence.ts +20 -11
- package/templates/starter/e2e/browser-orientation-gizmo-evidence-helpers.ts +4 -0
- package/templates/starter/e2e/browser-orientation-gizmo-live-preconditions.ts +86 -0
- package/templates/starter/e2e/browser-runtime-applicability-requirements.ts +84 -0
- package/templates/starter/e2e/browser-runtime-evidence-reporter.ts +9 -2
- package/templates/starter/e2e/browser-runtime-evidence-requirements.ts +29 -26
- package/templates/starter/e2e/browser-semantic-evidence-test-helpers.ts +25 -0
- package/templates/starter/scripts/toolcraft-contract-manifest.json +1 -0
- package/templates/starter/scripts/toolcraft-product-boundary-ast.mjs +85 -115
- package/templates/starter/scripts/toolcraft-product-boundary-module-policy.mjs +101 -0
- package/templates/starter/scripts/toolcraft-product-boundary.test.mjs +0 -72
- package/templates/starter/scripts/toolcraft-product-control-bindings.mjs +182 -0
- package/templates/starter/scripts/toolcraft-product-control-boundary.mjs +146 -0
- package/templates/starter/scripts/toolcraft-product-control-boundary.test.mjs +186 -0
- package/templates/starter/scripts/toolcraft-product-export-boundary.mjs +6 -17
- package/templates/starter/scripts/toolcraft-product-export-boundary.test.mjs +196 -0
- package/templates/starter/scripts/toolcraft-typescript-source-evidence-structure.test.mjs +20 -0
- package/templates/starter/scripts/toolcraft-typescript-source-evidence.mjs +1 -0
- package/templates/starter/scripts/toolcraft-unavailable-resource-evidence-facade.test.mjs +2 -0
- package/templates/starter/src/app/acceptance/artifact-export-intent.ts +130 -0
- package/templates/starter/src/app/acceptance/conditions.ts +1 -1
- package/templates/starter/src/app/acceptance/control-acceptance-context.ts +2 -2
- package/templates/starter/src/app/acceptance/control-acceptance-coverage.ts +6 -20
- package/templates/starter/src/app/acceptance/control-acceptance-kind-rules.ts +24 -5
- package/templates/starter/src/app/acceptance/control-acceptance-policy.ts +2 -13
- package/templates/starter/src/app/acceptance/control-applicability-cases.test.ts +321 -0
- package/templates/starter/src/app/acceptance/control-applicability-cases.ts +290 -0
- package/templates/starter/src/app/acceptance/control-applicability.ts +332 -0
- package/templates/starter/src/app/acceptance/control-layout-dependency-rules.ts +20 -9
- package/templates/starter/src/app/acceptance/control-layout-entity-rules.ts +4 -6
- package/templates/starter/src/app/acceptance/control-layout-model.ts +4 -4
- package/templates/starter/src/app/acceptance/control-layout-section-rules.ts +3 -10
- package/templates/starter/src/app/acceptance/control-parts.ts +8 -0
- package/templates/starter/src/app/acceptance/control-section-entity-cohesion.test.ts +215 -0
- package/templates/starter/src/app/acceptance/control-section-entity-cohesion.ts +132 -0
- package/templates/starter/src/app/acceptance/control-section-inventory.test.ts +87 -0
- package/templates/starter/src/app/acceptance/control-section-inventory.ts +74 -44
- package/templates/starter/src/app/acceptance/custom-controls.ts +11 -3
- package/templates/starter/src/app/acceptance/inline-layout.ts +64 -9
- package/templates/starter/src/app/acceptance/media-upload.ts +5 -1
- package/templates/starter/src/app/acceptance/orientation-gizmo.ts +18 -11
- package/templates/starter/src/app/acceptance/output-background-rules.ts +2 -2
- package/templates/starter/src/app/acceptance/output-export-layout-rules.ts +18 -10
- package/templates/starter/src/app/acceptance/output-export-model.ts +54 -11
- package/templates/starter/src/app/acceptance/output-export.ts +22 -10
- package/templates/starter/src/app/acceptance/output-video-export-rules.ts +99 -0
- package/templates/starter/src/app/acceptance/types.ts +23 -8
- package/templates/starter/src/app/acceptance/validate-coverage.ts +19 -2
- package/templates/starter/src/app/starter-acceptance.artifact-export-intent.test.ts +239 -0
- package/templates/starter/src/app/starter-acceptance.background-export.test.ts +33 -0
- package/templates/starter/src/app/starter-acceptance.canvas-sizing.test.ts +16 -1
- package/templates/starter/src/app/starter-acceptance.compound-part-coverage.test.ts +65 -0
- package/templates/starter/src/app/starter-acceptance.contract-fixtures.test.ts +41 -0
- package/templates/starter/src/app/starter-acceptance.contract-fixtures.ts +112 -16
- package/templates/starter/src/app/starter-acceptance.control-applicability.test.ts +224 -0
- package/templates/starter/src/app/starter-acceptance.control-order.test.ts +58 -3
- package/templates/starter/src/app/starter-acceptance.control-state.test.ts +0 -111
- package/templates/starter/src/app/starter-acceptance.custom-control-collections.test.ts +3 -1
- package/templates/starter/src/app/starter-acceptance.custom-control-valid.test.ts +1 -1
- package/templates/starter/src/app/starter-acceptance.export-test-utils.ts +22 -0
- package/templates/starter/src/app/{starter-acceptance.image-video-export-settings.test.ts → starter-acceptance.image-export-settings.test.ts} +37 -9
- package/templates/starter/src/app/starter-acceptance.interaction-ownership.test.ts +12 -0
- package/templates/starter/src/app/starter-acceptance.media-upload.fixtures.ts +11 -1
- package/templates/starter/src/app/starter-acceptance.media-upload.test.ts +28 -0
- package/templates/starter/src/app/starter-acceptance.output-export-intent.test.ts +384 -0
- package/templates/starter/src/app/starter-acceptance.output-export-rules.test.ts +4 -0
- package/templates/starter/src/app/starter-acceptance.product-output-export.test.ts +112 -105
- package/templates/starter/src/app/starter-acceptance.product-readiness.test.ts +12 -0
- package/templates/starter/src/app/starter-acceptance.section-cohesion.test.ts +1 -1
- package/templates/starter/src/app/starter-acceptance.section-dependencies.test.ts +35 -24
- package/templates/starter/src/app/starter-acceptance.section-size.test.ts +72 -0
- package/templates/starter/src/app/starter-acceptance.ts +11 -2
- package/templates/starter/src/app/starter-acceptance.video-export-settings.test.ts +336 -0
- package/templates/starter/src/app/starter-acceptance.view-interaction.test.ts +8 -0
- package/templates/starter/src/app/test-evidence/browser-runtime-contract.ts +2 -2
- package/templates/starter/src/routes/index.tsx +1 -0
- package/templates/ui/components/composites/tabs.tsx +2 -2
- package/templates/ui/components/controls/collection-actions/collection-item-groups.test.tsx +38 -0
- package/templates/ui/components/controls/collection-actions/collection-item-groups.tsx +36 -0
- package/templates/ui/components/controls/collection-actions/index.ts +2 -0
- package/templates/ui/components/controls/file-drop/file-drop-collection-control.tsx +137 -0
- package/templates/ui/components/controls/file-drop/file-drop-control.test.tsx +189 -0
- package/templates/ui/components/controls/file-drop/file-drop-control.tsx +81 -88
- package/templates/ui/components/controls/file-drop/file-drop-presentation.tsx +131 -9
- package/templates/ui/components/controls/file-drop/file-drop-types.ts +36 -22
- package/templates/ui/components/controls/file-drop/index.ts +1 -0
- package/templates/ui/components/controls/index.ts +3 -0
- package/templates/ui/components/controls/range-slider/range-slider-control.tsx +1 -1
- package/templates/ui/components/controls/range-slider/range-slider-value.test.ts +14 -0
- package/templates/ui/components/controls/range-slider/range-slider-value.ts +3 -2
- package/templates/starter/src/app/acceptance/condition-exclusivity.test.ts +0 -60
- package/templates/starter/src/app/acceptance/condition-exclusivity.ts +0 -221
|
@@ -5,11 +5,13 @@ import {
|
|
|
5
5
|
getToolcraftAnimationModeChoiceErrors,
|
|
6
6
|
} from "./animation-intent";
|
|
7
7
|
import { getToolcraftControlAcceptanceErrors } from "./control-acceptance";
|
|
8
|
+
import { getToolcraftControlApplicabilityErrors } from "./control-applicability";
|
|
8
9
|
import {
|
|
9
10
|
getToolcraftControlSectionHeuristicErrors,
|
|
10
11
|
getToolcraftControlSectionInvariantErrors,
|
|
11
12
|
} from "./control-layout";
|
|
12
13
|
import { getToolcraftControlOrderErrors } from "./control-order";
|
|
14
|
+
import { getToolcraftControlSectionEntityCohesionErrors } from "./control-section-entity-cohesion";
|
|
13
15
|
import { getToolcraftControlSectionInventoryErrors } from "./control-section-inventory";
|
|
14
16
|
import { isToolcraftVisibleAcceptanceControl } from "./controls";
|
|
15
17
|
import { getToolcraftInlineLayoutErrors } from "./inline-layout";
|
|
@@ -146,12 +148,27 @@ const toolcraftAcceptanceValidators: readonly ToolcraftAcceptanceValidator[] = [
|
|
|
146
148
|
ruleId: "controls-product-coverage",
|
|
147
149
|
validate: ({ schema }) => getToolcraftOrientationGizmoErrors(schema),
|
|
148
150
|
},
|
|
151
|
+
{
|
|
152
|
+
path: "schema.panels.controls.sections[].controls[].applicability",
|
|
153
|
+
ruleId: "controls-product-coverage",
|
|
154
|
+
validate: ({ controls, productReadiness }) =>
|
|
155
|
+
getToolcraftControlApplicabilityErrors({
|
|
156
|
+
controls,
|
|
157
|
+
productReadiness,
|
|
158
|
+
}),
|
|
159
|
+
},
|
|
149
160
|
{
|
|
150
161
|
path: "starterControlSectionInventory",
|
|
151
162
|
ruleId: "controls-section-inventory-required",
|
|
152
163
|
validate: ({ schema, sectionInventory }) =>
|
|
153
164
|
getToolcraftControlSectionInventoryErrors(schema, sectionInventory),
|
|
154
165
|
},
|
|
166
|
+
{
|
|
167
|
+
path: "starterControlSectionInventory",
|
|
168
|
+
ruleId: "controls-section-inventory-required",
|
|
169
|
+
validate: ({ sectionInventory }) =>
|
|
170
|
+
getToolcraftControlSectionEntityCohesionErrors(sectionInventory),
|
|
171
|
+
},
|
|
155
172
|
{
|
|
156
173
|
path: "schema.panels.controls.sections[].layoutGroups",
|
|
157
174
|
ruleId: "controls-component-layout-invariants",
|
|
@@ -160,11 +177,11 @@ const toolcraftAcceptanceValidators: readonly ToolcraftAcceptanceValidator[] = [
|
|
|
160
177
|
{
|
|
161
178
|
path: "schema.export",
|
|
162
179
|
ruleId: "output-export-required",
|
|
163
|
-
validate: ({ acceptance, controls,
|
|
180
|
+
validate: ({ acceptance, controls, productReadiness, schema }) =>
|
|
164
181
|
getToolcraftOutputExportErrors({
|
|
165
182
|
acceptance,
|
|
166
183
|
controls,
|
|
167
|
-
|
|
184
|
+
productReadiness,
|
|
168
185
|
schema,
|
|
169
186
|
}),
|
|
170
187
|
},
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
getToolcraftArtifactExportIntentEvidenceErrors,
|
|
5
|
+
resolveToolcraftArtifactExportIntent,
|
|
6
|
+
validateToolcraftArtifactExportIntentCorrespondence,
|
|
7
|
+
} from "./acceptance/artifact-export-intent";
|
|
8
|
+
import type { ToolcraftArtifactExportIntent } from "./acceptance/types";
|
|
9
|
+
|
|
10
|
+
const deliveryCases: readonly Readonly<{
|
|
11
|
+
expected: Readonly<{
|
|
12
|
+
imageEnabled: boolean;
|
|
13
|
+
videoEnabled: boolean;
|
|
14
|
+
}>;
|
|
15
|
+
intent: ToolcraftArtifactExportIntent;
|
|
16
|
+
name: string;
|
|
17
|
+
}>[] = [
|
|
18
|
+
{
|
|
19
|
+
expected: { imageEnabled: true, videoEnabled: false },
|
|
20
|
+
intent: {
|
|
21
|
+
image: { mode: "toolcraft-default" },
|
|
22
|
+
video: { mode: "not-requested" },
|
|
23
|
+
},
|
|
24
|
+
name: "enables default image export without unrequested video export",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
expected: { imageEnabled: true, videoEnabled: false },
|
|
28
|
+
intent: {
|
|
29
|
+
image: {
|
|
30
|
+
evidence: "The user explicitly requested PNG delivery.",
|
|
31
|
+
mode: "user-requested",
|
|
32
|
+
},
|
|
33
|
+
video: { mode: "not-requested" },
|
|
34
|
+
},
|
|
35
|
+
name: "enables explicitly requested image export",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
expected: { imageEnabled: false, videoEnabled: false },
|
|
39
|
+
intent: {
|
|
40
|
+
image: {
|
|
41
|
+
evidence: "The user explicitly requested no image export.",
|
|
42
|
+
mode: "user-removed",
|
|
43
|
+
},
|
|
44
|
+
video: { mode: "not-requested" },
|
|
45
|
+
},
|
|
46
|
+
name: "disables explicitly removed image export",
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
expected: { imageEnabled: true, videoEnabled: true },
|
|
50
|
+
intent: {
|
|
51
|
+
image: { mode: "toolcraft-default" },
|
|
52
|
+
video: {
|
|
53
|
+
evidence: "The user explicitly requested MP4 delivery.",
|
|
54
|
+
mode: "user-requested",
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
name: "enables explicitly requested video export",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
expected: { imageEnabled: true, videoEnabled: true },
|
|
61
|
+
intent: {
|
|
62
|
+
image: {
|
|
63
|
+
evidence: "The user explicitly requested PNG delivery.",
|
|
64
|
+
mode: "user-requested",
|
|
65
|
+
},
|
|
66
|
+
video: {
|
|
67
|
+
evidence: "The user explicitly requested MP4 delivery.",
|
|
68
|
+
mode: "user-requested",
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
name: "enables explicitly requested image and video export",
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
expected: { imageEnabled: false, videoEnabled: true },
|
|
75
|
+
intent: {
|
|
76
|
+
image: {
|
|
77
|
+
evidence: "The user explicitly requested no image export.",
|
|
78
|
+
mode: "user-removed",
|
|
79
|
+
},
|
|
80
|
+
video: {
|
|
81
|
+
evidence: "The user explicitly requested MP4 delivery.",
|
|
82
|
+
mode: "user-requested",
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
name: "keeps requested video export when image export is removed",
|
|
86
|
+
},
|
|
87
|
+
];
|
|
88
|
+
|
|
89
|
+
const evidenceCases: readonly Readonly<{
|
|
90
|
+
expected: readonly string[];
|
|
91
|
+
intent: ToolcraftArtifactExportIntent;
|
|
92
|
+
name: string;
|
|
93
|
+
}>[] = [
|
|
94
|
+
{
|
|
95
|
+
expected: [],
|
|
96
|
+
intent: {
|
|
97
|
+
image: { mode: "toolcraft-default" },
|
|
98
|
+
video: { mode: "not-requested" },
|
|
99
|
+
},
|
|
100
|
+
name: "accepts default image and not-requested video modes",
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
expected: [],
|
|
104
|
+
intent: {
|
|
105
|
+
image: {
|
|
106
|
+
evidence: "The user explicitly requested PNG delivery.",
|
|
107
|
+
mode: "user-requested",
|
|
108
|
+
},
|
|
109
|
+
video: { mode: "not-requested" },
|
|
110
|
+
},
|
|
111
|
+
name: "accepts nonblank requested image evidence",
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
expected: [],
|
|
115
|
+
intent: {
|
|
116
|
+
image: {
|
|
117
|
+
evidence: "The user explicitly requested no image export.",
|
|
118
|
+
mode: "user-removed",
|
|
119
|
+
},
|
|
120
|
+
video: { mode: "not-requested" },
|
|
121
|
+
},
|
|
122
|
+
name: "accepts nonblank image removal evidence",
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
expected: [],
|
|
126
|
+
intent: {
|
|
127
|
+
image: { mode: "toolcraft-default" },
|
|
128
|
+
video: {
|
|
129
|
+
evidence: "The user explicitly requested MP4 delivery.",
|
|
130
|
+
mode: "user-requested",
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
name: "accepts nonblank requested video evidence",
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
expected: [
|
|
137
|
+
"Image export user-removed intent requires non-empty evidence.",
|
|
138
|
+
],
|
|
139
|
+
intent: {
|
|
140
|
+
image: { evidence: " \n\t ", mode: "user-removed" },
|
|
141
|
+
video: { mode: "not-requested" },
|
|
142
|
+
},
|
|
143
|
+
name: "rejects blank image removal evidence",
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
expected: [
|
|
147
|
+
"Image export user-requested intent requires non-empty evidence.",
|
|
148
|
+
],
|
|
149
|
+
intent: {
|
|
150
|
+
image: { evidence: " ", mode: "user-requested" },
|
|
151
|
+
video: { mode: "not-requested" },
|
|
152
|
+
},
|
|
153
|
+
name: "rejects blank requested image evidence",
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
expected: [
|
|
157
|
+
"Video export user-requested intent requires non-empty evidence.",
|
|
158
|
+
],
|
|
159
|
+
intent: {
|
|
160
|
+
image: { mode: "toolcraft-default" },
|
|
161
|
+
video: { evidence: "\t", mode: "user-requested" },
|
|
162
|
+
},
|
|
163
|
+
name: "rejects blank requested video evidence",
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
expected: [
|
|
167
|
+
"Image export user-removed intent requires non-empty evidence.",
|
|
168
|
+
"Video export user-requested intent requires non-empty evidence.",
|
|
169
|
+
],
|
|
170
|
+
intent: {
|
|
171
|
+
image: { evidence: " ", mode: "user-removed" },
|
|
172
|
+
video: { evidence: "\n", mode: "user-requested" },
|
|
173
|
+
},
|
|
174
|
+
name: "aggregates blank image and video evidence errors",
|
|
175
|
+
},
|
|
176
|
+
];
|
|
177
|
+
|
|
178
|
+
describe("Toolcraft artifact export intent", () => {
|
|
179
|
+
it.each(deliveryCases)("$name", ({ expected, intent }) => {
|
|
180
|
+
const delivery = resolveToolcraftArtifactExportIntent(intent);
|
|
181
|
+
|
|
182
|
+
expect(delivery).toEqual(expected);
|
|
183
|
+
expect(Object.isFrozen(delivery)).toBe(true);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it.each(evidenceCases)("$name", ({ expected, intent }) => {
|
|
187
|
+
expect(getToolcraftArtifactExportIntentEvidenceErrors(intent)).toEqual(
|
|
188
|
+
expected,
|
|
189
|
+
);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it("validates enabled and disabled delivery against typed schema facts", () => {
|
|
193
|
+
expect(
|
|
194
|
+
validateToolcraftArtifactExportIntentCorrespondence({
|
|
195
|
+
hasImageExportAction: false,
|
|
196
|
+
hasImageExportSection: false,
|
|
197
|
+
hasVideoExportAction: true,
|
|
198
|
+
hasVideoExportSection: true,
|
|
199
|
+
intent: {
|
|
200
|
+
image: { mode: "toolcraft-default" },
|
|
201
|
+
video: { mode: "not-requested" },
|
|
202
|
+
},
|
|
203
|
+
}),
|
|
204
|
+
).toEqual({
|
|
205
|
+
delivery: { imageEnabled: true, videoEnabled: false },
|
|
206
|
+
errors: [
|
|
207
|
+
'Image export intent "toolcraft-default" requires an export-image panel action.',
|
|
208
|
+
'Image export intent "toolcraft-default" requires an "Image Export" section.',
|
|
209
|
+
'Video export intent "not-requested" must not have an export-video panel action.',
|
|
210
|
+
'Video export intent "not-requested" must not have a "Video Export" section.',
|
|
211
|
+
],
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it("aggregates evidence and correspondence errors without prose inference", () => {
|
|
216
|
+
expect(
|
|
217
|
+
validateToolcraftArtifactExportIntentCorrespondence({
|
|
218
|
+
hasImageExportAction: true,
|
|
219
|
+
hasImageExportSection: true,
|
|
220
|
+
hasVideoExportAction: false,
|
|
221
|
+
hasVideoExportSection: false,
|
|
222
|
+
intent: {
|
|
223
|
+
image: { evidence: " ", mode: "user-removed" },
|
|
224
|
+
video: { evidence: "\t", mode: "user-requested" },
|
|
225
|
+
},
|
|
226
|
+
}),
|
|
227
|
+
).toEqual({
|
|
228
|
+
delivery: { imageEnabled: false, videoEnabled: true },
|
|
229
|
+
errors: [
|
|
230
|
+
"Image export user-removed intent requires non-empty evidence.",
|
|
231
|
+
"Video export user-requested intent requires non-empty evidence.",
|
|
232
|
+
'Image export intent "user-removed" must not have an export-image panel action.',
|
|
233
|
+
'Image export intent "user-removed" must not have an "Image Export" section.',
|
|
234
|
+
'Video export intent "user-requested" requires an export-video panel action.',
|
|
235
|
+
'Video export intent "user-requested" requires a "Video Export" section.',
|
|
236
|
+
],
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
2
|
|
|
3
|
+
import type { ToolcraftProductReadiness } from "./acceptance/types";
|
|
3
4
|
import { defineContractSchemaFixture, validateContractAcceptance } from "./starter-acceptance.contract-fixtures";
|
|
4
5
|
import {
|
|
5
6
|
makeBackgroundSection,
|
|
@@ -7,6 +8,33 @@ import {
|
|
|
7
8
|
} from "./starter-acceptance.export-test-utils";
|
|
8
9
|
import { makeControlAcceptance } from "./starter-acceptance.test-utils";
|
|
9
10
|
|
|
11
|
+
const imageExportProductReadiness: ToolcraftProductReadiness = {
|
|
12
|
+
exportIntent: {
|
|
13
|
+
image: { mode: "toolcraft-default" },
|
|
14
|
+
video: { mode: "not-requested" },
|
|
15
|
+
},
|
|
16
|
+
interactionOwnership: [],
|
|
17
|
+
mode: "product",
|
|
18
|
+
productName: "Background image export fixture",
|
|
19
|
+
productSummary: "A static image fixture for background export validation.",
|
|
20
|
+
requestedBehavior: "Export the image with configurable background output.",
|
|
21
|
+
viewInteraction: {
|
|
22
|
+
mode: "non-spatial",
|
|
23
|
+
reason: "The fixture renders a static two-dimensional image.",
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const videoExportProductReadiness: ToolcraftProductReadiness = {
|
|
28
|
+
...imageExportProductReadiness,
|
|
29
|
+
exportIntent: {
|
|
30
|
+
image: { mode: "toolcraft-default" },
|
|
31
|
+
video: {
|
|
32
|
+
evidence: "The background fixture explicitly exercises video background export.",
|
|
33
|
+
mode: "user-requested",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
10
38
|
describe("Toolcraft background export acceptance contract", () => {
|
|
11
39
|
it("requires png export apps to expose background color and png background toggle controls", () => {
|
|
12
40
|
const schemaWithoutBackgroundControls = defineContractSchemaFixture({
|
|
@@ -43,6 +71,7 @@ describe("Toolcraft background export acceptance contract", () => {
|
|
|
43
71
|
expect(
|
|
44
72
|
validateContractAcceptance({
|
|
45
73
|
schema: schemaWithoutBackgroundControls,
|
|
74
|
+
productReadiness: imageExportProductReadiness,
|
|
46
75
|
acceptance: [
|
|
47
76
|
{
|
|
48
77
|
actionCoverage: ["export.png"],
|
|
@@ -118,6 +147,7 @@ describe("Toolcraft background export acceptance contract", () => {
|
|
|
118
147
|
expect(
|
|
119
148
|
validateContractAcceptance({
|
|
120
149
|
schema: schemaWithLegacyBackgroundControls,
|
|
150
|
+
productReadiness: imageExportProductReadiness,
|
|
121
151
|
acceptance: [
|
|
122
152
|
makeControlAcceptance("appearance.background", "color"),
|
|
123
153
|
makeControlAcceptance("export.includeBackground", "switch"),
|
|
@@ -185,6 +215,7 @@ describe("Toolcraft background export acceptance contract", () => {
|
|
|
185
215
|
});
|
|
186
216
|
const errors = validateContractAcceptance({
|
|
187
217
|
schema: schemaWithBackgroundControls,
|
|
218
|
+
productReadiness: imageExportProductReadiness,
|
|
188
219
|
acceptance: [
|
|
189
220
|
makeControlAcceptance("appearance.background", "color"),
|
|
190
221
|
{
|
|
@@ -262,6 +293,7 @@ describe("Toolcraft background export acceptance contract", () => {
|
|
|
262
293
|
expect(
|
|
263
294
|
validateContractAcceptance({
|
|
264
295
|
schema: schemaWithBackgroundControls,
|
|
296
|
+
productReadiness: imageExportProductReadiness,
|
|
265
297
|
acceptance: [
|
|
266
298
|
makeControlAcceptance("appearance.background", "color"),
|
|
267
299
|
makeControlAcceptance("export.includeBackground", "switch"),
|
|
@@ -332,6 +364,7 @@ describe("Toolcraft background export acceptance contract", () => {
|
|
|
332
364
|
expect(
|
|
333
365
|
validateContractAcceptance({
|
|
334
366
|
schema: schemaWithVideoExport,
|
|
367
|
+
productReadiness: videoExportProductReadiness,
|
|
335
368
|
acceptance: [
|
|
336
369
|
makeControlAcceptance("appearance.background", "color"),
|
|
337
370
|
{
|
|
@@ -9,6 +9,10 @@ import { makeControlAcceptance } from "./starter-acceptance.test-utils";
|
|
|
9
9
|
import type { ToolcraftProductReadiness } from "./acceptance/types";
|
|
10
10
|
|
|
11
11
|
const infinityProductReadiness: ToolcraftProductReadiness = {
|
|
12
|
+
exportIntent: {
|
|
13
|
+
image: { mode: "toolcraft-default" },
|
|
14
|
+
video: { mode: "not-requested" },
|
|
15
|
+
},
|
|
12
16
|
interactionOwnership: [],
|
|
13
17
|
mode: "product",
|
|
14
18
|
productName: "Infinity contract fixture",
|
|
@@ -20,6 +24,17 @@ const infinityProductReadiness: ToolcraftProductReadiness = {
|
|
|
20
24
|
},
|
|
21
25
|
};
|
|
22
26
|
|
|
27
|
+
const infinityVideoProductReadiness: ToolcraftProductReadiness = {
|
|
28
|
+
...infinityProductReadiness,
|
|
29
|
+
exportIntent: {
|
|
30
|
+
image: { mode: "toolcraft-default" },
|
|
31
|
+
video: {
|
|
32
|
+
evidence: "The Infinity canvas fixture explicitly exercises video export bounds.",
|
|
33
|
+
mode: "user-requested",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
23
38
|
function createFixedOutputSchema({
|
|
24
39
|
height = 1080,
|
|
25
40
|
width = 1920,
|
|
@@ -167,7 +182,7 @@ describe("Toolcraft canvas sizing acceptance coverage", () => {
|
|
|
167
182
|
validateContractAcceptance({
|
|
168
183
|
schema: createEditableOutputSchema("export-video"),
|
|
169
184
|
acceptance: [makeInfinityCanvasAcceptance("mode-and-restoration")],
|
|
170
|
-
productReadiness:
|
|
185
|
+
productReadiness: infinityVideoProductReadiness,
|
|
171
186
|
}),
|
|
172
187
|
).toEqual(
|
|
173
188
|
expect.arrayContaining([
|
|
@@ -7,6 +7,71 @@ import {
|
|
|
7
7
|
import { makeControlAcceptance } from "./starter-acceptance.test-utils";
|
|
8
8
|
|
|
9
9
|
describe("starter acceptance compound control part coverage contract", () => {
|
|
10
|
+
it("distinguishes user-owned and source-owned collection parts", () => {
|
|
11
|
+
const collectionSchema = defineContractSchemaFixture({
|
|
12
|
+
canvas: { enabled: true },
|
|
13
|
+
panels: {
|
|
14
|
+
controls: {
|
|
15
|
+
sections: [
|
|
16
|
+
{
|
|
17
|
+
controls: {
|
|
18
|
+
editableColors: {
|
|
19
|
+
defaultValue: [{ hex: "#DFFF1A" }],
|
|
20
|
+
itemControl: { label: false, type: "color" },
|
|
21
|
+
target: "colors.editable",
|
|
22
|
+
type: "collectionActions",
|
|
23
|
+
},
|
|
24
|
+
editableLayers: {
|
|
25
|
+
defaultValue: [{ enabled: true, strength: 0.5 }],
|
|
26
|
+
itemControls: {
|
|
27
|
+
enabled: {
|
|
28
|
+
defaultValue: true,
|
|
29
|
+
label: "Enabled",
|
|
30
|
+
type: "switch",
|
|
31
|
+
},
|
|
32
|
+
strength: {
|
|
33
|
+
defaultValue: 0.5,
|
|
34
|
+
label: "Strength",
|
|
35
|
+
max: 1,
|
|
36
|
+
min: 0,
|
|
37
|
+
type: "slider",
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
itemLabel: "Layer",
|
|
41
|
+
target: "layers.editable",
|
|
42
|
+
type: "collectionActions",
|
|
43
|
+
},
|
|
44
|
+
sourceColors: {
|
|
45
|
+
defaultValue: [{ hex: "#8CFF3A" }],
|
|
46
|
+
itemControl: { label: false, type: "color" },
|
|
47
|
+
target: "colors.source",
|
|
48
|
+
type: "sourceCollection",
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
title: "Fill Sections",
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
title: "Controls",
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
const acceptance = [
|
|
59
|
+
makeControlAcceptance("colors.editable", "collectionActions"),
|
|
60
|
+
makeControlAcceptance("layers.editable", "collectionActions"),
|
|
61
|
+
makeControlAcceptance("colors.source", "sourceCollection"),
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
expect(
|
|
65
|
+
validateContractAcceptance({ schema: collectionSchema, acceptance }),
|
|
66
|
+
).toEqual(
|
|
67
|
+
expect.arrayContaining([
|
|
68
|
+
"Fill Sections / editableColors (colors.editable) must declare controlPartCoverage for every semantic value part: collectionActions.add, collectionActions.remove, collectionActions.items.",
|
|
69
|
+
"Fill Sections / editableLayers (layers.editable) must declare controlPartCoverage for every semantic value part: collectionActions.add, collectionActions.remove, collectionActions.items.",
|
|
70
|
+
"Fill Sections / sourceColors (colors.source) must declare controlPartCoverage for every semantic value part: sourceCollection.items.",
|
|
71
|
+
]),
|
|
72
|
+
);
|
|
73
|
+
});
|
|
74
|
+
|
|
10
75
|
it("requires compound controls to cover every semantic value part", () => {
|
|
11
76
|
const compoundSchema = defineContractSchemaFixture({
|
|
12
77
|
canvas: { enabled: true },
|
|
@@ -20,6 +20,47 @@ const schema = {
|
|
|
20
20
|
} satisfies ToolcraftAppSchema;
|
|
21
21
|
|
|
22
22
|
describe("Toolcraft acceptance contract schema fixtures", () => {
|
|
23
|
+
it("authors neutral fixture controls explicitly without masking legacy input", () => {
|
|
24
|
+
const fixture = defineContractSchemaFixture({
|
|
25
|
+
canvas: { enabled: true },
|
|
26
|
+
panels: {
|
|
27
|
+
controls: {
|
|
28
|
+
sections: [
|
|
29
|
+
{
|
|
30
|
+
controls: {
|
|
31
|
+
legacy: {
|
|
32
|
+
target: "shape.legacy",
|
|
33
|
+
type: "slider",
|
|
34
|
+
visibleWhen: { equals: true, target: "shape.enabled" },
|
|
35
|
+
},
|
|
36
|
+
neutral: {
|
|
37
|
+
target: "shape.enabled",
|
|
38
|
+
type: "switch",
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
id: "shape",
|
|
42
|
+
title: "Shape",
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
title: "Controls",
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
const controls = fixture.panels.controls?.sections.find(
|
|
50
|
+
(section) => section.id === "shape",
|
|
51
|
+
)?.controls;
|
|
52
|
+
|
|
53
|
+
expect(controls?.neutral?.applicability).toEqual({
|
|
54
|
+
mode: "always",
|
|
55
|
+
origin: "explicit",
|
|
56
|
+
});
|
|
57
|
+
expect(controls?.legacy?.applicability).toEqual({
|
|
58
|
+
all: [{ equals: true, target: "shape.enabled" }],
|
|
59
|
+
mode: "conditional",
|
|
60
|
+
origin: "legacy",
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
23
64
|
it("opts unrelated unit fixtures out without changing the production default", () => {
|
|
24
65
|
const productionDefault = defineToolcraft(schema);
|
|
25
66
|
const contractFixture = defineContractSchemaFixture(schema);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
defineToolcraft,
|
|
3
|
+
resolveToolcraftControlApplicability,
|
|
4
|
+
type ResolvedToolcraftAppSchema,
|
|
3
5
|
type ToolcraftAppSchema,
|
|
4
6
|
} from "@repo/toolcraft-runtime";
|
|
5
7
|
|
|
@@ -16,8 +18,32 @@ import {
|
|
|
16
18
|
} from "./acceptance/validate-coverage";
|
|
17
19
|
|
|
18
20
|
export function defineContractSchemaFixture(schema: ToolcraftAppSchema) {
|
|
21
|
+
const controls = schema.panels.controls
|
|
22
|
+
? {
|
|
23
|
+
...schema.panels.controls,
|
|
24
|
+
sections: schema.panels.controls.sections.map((section) => ({
|
|
25
|
+
...section,
|
|
26
|
+
controls: Object.fromEntries(
|
|
27
|
+
Object.entries(section.controls).map(([controlId, control]) => [
|
|
28
|
+
controlId,
|
|
29
|
+
control.applicability || control.visibleWhen
|
|
30
|
+
? control
|
|
31
|
+
: {
|
|
32
|
+
...control,
|
|
33
|
+
applicability: { mode: "always" as const },
|
|
34
|
+
},
|
|
35
|
+
]),
|
|
36
|
+
),
|
|
37
|
+
})),
|
|
38
|
+
}
|
|
39
|
+
: undefined;
|
|
40
|
+
|
|
19
41
|
return defineToolcraft({
|
|
20
42
|
...schema,
|
|
43
|
+
panels: {
|
|
44
|
+
...schema.panels,
|
|
45
|
+
...(controls ? { controls } : {}),
|
|
46
|
+
},
|
|
21
47
|
persistence: { storage: "none" },
|
|
22
48
|
});
|
|
23
49
|
}
|
|
@@ -54,28 +80,98 @@ export const contractProductReadinessFixture: ToolcraftProductReadiness = {
|
|
|
54
80
|
reason: "Neutral contract fixture without a product-owned spatial scene.",
|
|
55
81
|
};
|
|
56
82
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
83
|
+
type ContractAcceptanceOverrides = Omit<
|
|
84
|
+
Partial<ToolcraftAcceptanceValidationInput>,
|
|
85
|
+
"schema"
|
|
86
|
+
> & {
|
|
87
|
+
schema?: ContractValidationSchemaFixture;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
type ContractValidationSchemaFixture = Omit<
|
|
91
|
+
ResolvedToolcraftAppSchema,
|
|
92
|
+
"panels"
|
|
93
|
+
> & {
|
|
94
|
+
panels: Omit<ResolvedToolcraftAppSchema["panels"], "controls"> & {
|
|
95
|
+
controls?: ToolcraftAppSchema["panels"]["controls"];
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
function resolveContractValidationSchemaFixture(
|
|
100
|
+
schema: ContractValidationSchemaFixture,
|
|
101
|
+
): ResolvedToolcraftAppSchema {
|
|
102
|
+
const {
|
|
103
|
+
controls: _fixtureControls,
|
|
104
|
+
...panelsWithoutFixtureControls
|
|
105
|
+
} = schema.panels;
|
|
106
|
+
const controls = schema.panels.controls
|
|
107
|
+
? {
|
|
108
|
+
...schema.panels.controls,
|
|
109
|
+
sections: schema.panels.controls.sections.map((section) => ({
|
|
110
|
+
...section,
|
|
111
|
+
controls: Object.fromEntries(
|
|
112
|
+
Object.entries(section.controls).map(([controlId, control]) => {
|
|
113
|
+
const {
|
|
114
|
+
applicability: authoredApplicability,
|
|
115
|
+
visibleWhen,
|
|
116
|
+
...controlWithoutApplicability
|
|
117
|
+
} = control;
|
|
118
|
+
|
|
119
|
+
return [
|
|
120
|
+
controlId,
|
|
121
|
+
{
|
|
122
|
+
...controlWithoutApplicability,
|
|
123
|
+
applicability: resolveToolcraftControlApplicability({
|
|
124
|
+
applicability:
|
|
125
|
+
authoredApplicability ??
|
|
126
|
+
(visibleWhen ? undefined : { mode: "always" }),
|
|
127
|
+
visibleWhen,
|
|
128
|
+
}),
|
|
129
|
+
},
|
|
130
|
+
];
|
|
131
|
+
}),
|
|
132
|
+
),
|
|
133
|
+
})),
|
|
134
|
+
}
|
|
135
|
+
: undefined;
|
|
136
|
+
|
|
137
|
+
// Contract tests deliberately preserve malformed post-normalization fields so
|
|
138
|
+
// the matching acceptance validator, rather than defineToolcraft, reports them.
|
|
139
|
+
return {
|
|
140
|
+
...schema,
|
|
141
|
+
panels: {
|
|
142
|
+
...panelsWithoutFixtureControls,
|
|
143
|
+
...(controls ? { controls } : {}),
|
|
144
|
+
},
|
|
145
|
+
} as ResolvedToolcraftAppSchema;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function resolveContractAcceptanceInput(
|
|
149
|
+
overrides: ContractAcceptanceOverrides,
|
|
150
|
+
): ToolcraftAcceptanceValidationInput {
|
|
151
|
+
const { schema = contractSchemaFixture, ...remainingOverrides } = overrides;
|
|
152
|
+
|
|
153
|
+
return {
|
|
61
154
|
acceptance: contractAcceptanceFixture,
|
|
62
155
|
productReadiness: contractProductReadinessFixture,
|
|
63
|
-
schema:
|
|
156
|
+
schema: resolveContractValidationSchemaFixture(schema),
|
|
64
157
|
sectionInventory: contractSectionInventoryFixture,
|
|
65
158
|
transferMode: contractTransferModeFixture,
|
|
66
|
-
...
|
|
67
|
-
}
|
|
159
|
+
...remainingOverrides,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function validateContractAcceptance(
|
|
164
|
+
overrides: ContractAcceptanceOverrides = {},
|
|
165
|
+
): string[] {
|
|
166
|
+
return validateToolcraftAcceptanceCoverage(
|
|
167
|
+
resolveContractAcceptanceInput(overrides),
|
|
168
|
+
);
|
|
68
169
|
}
|
|
69
170
|
|
|
70
171
|
export function validateContractAcceptanceDiagnostics(
|
|
71
|
-
overrides:
|
|
172
|
+
overrides: ContractAcceptanceOverrides = {},
|
|
72
173
|
) {
|
|
73
|
-
return validateToolcraftAcceptanceDiagnostics(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
schema: contractSchemaFixture,
|
|
77
|
-
sectionInventory: contractSectionInventoryFixture,
|
|
78
|
-
transferMode: contractTransferModeFixture,
|
|
79
|
-
...overrides,
|
|
80
|
-
});
|
|
174
|
+
return validateToolcraftAcceptanceDiagnostics(
|
|
175
|
+
resolveContractAcceptanceInput(overrides),
|
|
176
|
+
);
|
|
81
177
|
}
|