@pixel-point/toolcraft 0.0.16 → 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-performance-iteration-execution.test.mjs +2 -2
- package/src/generate-test-demand-only-lifecycle.mjs +14 -3
- package/src/generate-test-dependency-sandbox.mjs +42 -5
- package/src/generate-test-doc-assertions.mjs +109 -69
- package/src/generate-test-doc-assertions.test.mjs +65 -0
- package/src/generate-test-doc-policy-assertions.mjs +92 -0
- package/src/generate-test-file-assertions.mjs +36 -118
- package/src/generate-test-output-assertions.mjs +95 -0
- package/src/generate-test-package-assertions.mjs +6 -0
- package/src/generate-test-performance-boundary-assertions.mjs +45 -0
- package/src/generate-test-product-fixture.mjs +1 -0
- package/src/generate-test-product-fixture.test.mjs +18 -0
- package/src/generate-test-product-iteration.mjs +1 -0
- package/src/generate-test-product-iteration.test.mjs +18 -0
- package/src/generate-test-runtime-boundary-assertions.mjs +158 -0
- package/src/generate-test-standalone-assertions.mjs +10 -0
- package/src/generate-test-standalone-delivery-stages.mjs +14 -6
- package/src/generate.test.mjs +14 -0
- package/templates/runtime/contracts/component-contracts.choices.test.ts +59 -12
- package/templates/runtime/contracts/component-contracts.choices.ts +58 -12
- 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 +21 -6
- package/templates/runtime/contracts/component-contracts.runtime-labels.test.ts +7 -1
- package/templates/runtime/contracts/component-contracts.runtime-panels.test.ts +4 -1
- package/templates/runtime/contracts/component-contracts.runtime-shell.test.ts +4 -1
- package/templates/runtime/contracts/component-contracts.runtime.ts +15 -10
- package/templates/runtime/contracts/component-contracts.test.ts +2 -0
- package/templates/runtime/contracts/decision-contracts.test.ts +43 -4
- package/templates/runtime/contracts/decision-contracts.ts +10 -10
- package/templates/runtime/contracts/performance-verification-policy.test.ts +59 -6
- package/templates/runtime/contracts/performance-verification-policy.ts +5 -2
- package/templates/runtime/export/artifact-download.test.ts +71 -0
- package/templates/runtime/export/artifact-download.ts +80 -0
- package/templates/runtime/export/artifact-export-request.ts +23 -0
- package/templates/runtime/export/artifact-export-settings.test.ts +75 -0
- package/templates/runtime/export/artifact-export-settings.ts +96 -0
- package/templates/runtime/export/artifact-frame-renderer.test.ts +107 -0
- package/templates/runtime/export/artifact-frame-renderer.ts +96 -0
- package/templates/runtime/export/artifact-frame-state.test.ts +54 -0
- package/templates/runtime/export/artifact-frame-state.ts +44 -0
- package/templates/runtime/export/artifact-scene-frame.test.ts +84 -0
- package/templates/runtime/export/artifact-scene-frame.ts +118 -0
- package/templates/runtime/export/export-background.ts +46 -0
- package/templates/runtime/export/export-error.ts +43 -0
- package/templates/runtime/export/export.test.ts +49 -226
- package/templates/runtime/export/image-artifact-export.test.ts +111 -0
- package/templates/runtime/export/image-artifact-export.ts +145 -0
- package/templates/runtime/export/index.ts +44 -3
- package/templates/runtime/export/product-export-renderer.test.ts +77 -0
- package/templates/runtime/export/product-export-renderer.ts +63 -0
- package/templates/runtime/export/video-artifact-export.test.ts +166 -0
- package/templates/runtime/export/video-artifact-export.ts +164 -0
- package/templates/runtime/export/video-encoding-backend.ts +124 -0
- package/templates/runtime/export/video-encoding-policy.test.ts +68 -0
- package/templates/runtime/export/video-encoding-policy.ts +86 -0
- package/templates/runtime/export/video-frame-schedule.test.ts +58 -0
- package/templates/runtime/export/video-frame-schedule.ts +42 -0
- package/templates/runtime/index.ts +3 -0
- package/templates/runtime/model-import/model-import-limits.ts +15 -4
- package/templates/runtime/react/app-shell/runtime-public-api-runtime.test.tsx +291 -0
- package/templates/runtime/react/app-shell/runtime-public-api-test-support.ts +21 -0
- package/templates/runtime/react/app-shell/runtime-public-api.test.tsx +15 -304
- package/templates/runtime/react/app-shell/toolcraft-app.scene-export.test.tsx +41 -27
- package/templates/runtime/react/app-shell/toolcraft-app.tsx +39 -11
- package/templates/runtime/react/app-shell/toolcraft-source-asset-context.test.tsx +16 -57
- package/templates/runtime/react/app-shell/toolcraft-source-asset-context.tsx +75 -434
- package/templates/runtime/react/app-shell/toolcraft-source-asset-owner.test.ts +194 -0
- package/templates/runtime/react/app-shell/toolcraft-source-asset-owner.ts +227 -0
- package/templates/runtime/react/app-shell/toolcraft-source-asset-provider-ownership.test.tsx +243 -0
- package/templates/runtime/react/app-shell/toolcraft-source-asset-test-support.ts +51 -0
- package/templates/runtime/react/app-shell/toolcraft-unavailable-resource-proof.test.ts +138 -0
- package/templates/runtime/react/app-shell/toolcraft-unavailable-resource-proof.ts +378 -0
- 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.footer-actions.test.tsx +7 -12
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.scene-export-actions.test.tsx +18 -84
- 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 +43 -87
- package/templates/runtime/react/controls-panel/actions/export-action-runner.ts +68 -0
- 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/react/panel-host/panel-host-runtime-placement.test.tsx +30 -0
- package/templates/runtime/react/panel-host/panel-host.tsx +4 -0
- package/templates/runtime/scene/scene-bounds.test.ts +23 -0
- package/templates/runtime/scene/scene-bounds.ts +32 -19
- package/templates/runtime/schema/app-capabilities.test.ts +4 -0
- package/templates/runtime/schema/canvas-render-scale.ts +62 -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-id.test.ts +1 -1
- package/templates/runtime/schema/controls-panel-section-layout.ts +14 -9
- package/templates/runtime/schema/controls-panel-section-roundtrip.test.ts +62 -3
- 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-background.test.ts +1 -1
- package/templates/runtime/schema/define-toolcraft.setup-canvas.test.ts +16 -3
- package/templates/runtime/schema/define-toolcraft.setup-render-scale-timeline.test.ts +71 -3
- package/templates/runtime/schema/define-toolcraft.source-collection.test.ts +79 -0
- package/templates/runtime/schema/define-toolcraft.ts +1 -1
- package/templates/runtime/schema/runtime-setup-section.ts +24 -5
- package/templates/runtime/schema/schema-resolvers.ts +0 -56
- package/templates/runtime/schema/types.ts +72 -17
- package/templates/runtime/state/canvas-background-state.ts +6 -0
- package/templates/runtime/testing/performance-render-plan-integration.test.ts +64 -0
- package/templates/runtime/testing/performance-renderer-pipeline-validation.ts +18 -1
- package/templates/starter/AGENTS.md +18 -15
- package/templates/starter/NOTICE.md +6 -0
- package/templates/starter/docs/toolcraft/README.md +2 -1
- package/templates/starter/docs/toolcraft/acceptance-testing.md +23 -35
- package/templates/starter/docs/toolcraft/agent-worklog.md +18 -3
- package/templates/starter/docs/toolcraft/assembly-workflow.md +13 -5
- 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 +4 -2
- package/templates/starter/docs/toolcraft/core/performance.md +14 -3
- package/templates/starter/docs/toolcraft/core/runtime-boundary.md +16 -3
- package/templates/starter/docs/toolcraft/core/setup-export.md +49 -19
- package/templates/starter/docs/toolcraft/core/timeline-animation.md +4 -4
- 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/performance.md +20 -6
- package/templates/starter/docs/toolcraft/renderer-technique.md +5 -1
- package/templates/starter/docs/toolcraft/schema-reference.md +23 -25
- package/templates/starter/docs/toolcraft/workflow.md +7 -2
- package/templates/starter/e2e/app-browser-control-applicability-requirements.spec.ts +163 -0
- package/templates/starter/e2e/app-browser-control-coverage.spec.ts +33 -0
- package/templates/starter/e2e/app-browser-infinity-canvas-evidence.spec.ts +50 -3
- package/templates/starter/e2e/app-browser-orientation-evidence.spec.ts +174 -21
- package/templates/starter/e2e/app-browser-render-scale-evidence.spec.ts +60 -6
- package/templates/starter/e2e/app-browser-render-scale-requirements.spec.ts +77 -1
- package/templates/starter/e2e/app-browser-runtime-provenance.spec.ts +8 -0
- package/templates/starter/e2e/app-browser-runtime-reporter.spec.ts +35 -0
- package/templates/starter/e2e/app-browser-runtime-requirements.spec.ts +5 -34
- package/templates/starter/e2e/app-browser-semantic-evidence.spec.ts +61 -16
- package/templates/starter/e2e/app-browser-shell.spec.ts +13 -5
- package/templates/starter/e2e/app-performance-path-adapters.ts +8 -1
- package/templates/starter/e2e/app-performance.spec.ts +16 -9
- 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 +29 -341
- package/templates/starter/e2e/browser-infinity-canvas-unavailable-image-evidence.ts +370 -0
- package/templates/starter/e2e/browser-media-export-evidence.spec.ts +77 -0
- package/templates/starter/e2e/browser-media-export-evidence.ts +208 -0
- 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-render-scale-evidence.ts +37 -29
- package/templates/starter/e2e/browser-runtime-applicability-requirements.ts +84 -0
- package/templates/starter/e2e/browser-runtime-evidence-reporter.ts +13 -3
- package/templates/starter/e2e/browser-runtime-evidence-requirements.ts +72 -35
- package/templates/starter/e2e/browser-semantic-evidence-test-helpers.ts +25 -0
- package/templates/starter/e2e/browser-standard-timeline-evidence.ts +106 -0
- package/templates/starter/e2e/decoded-pixel-observation.spec.ts +74 -0
- package/templates/starter/e2e/decoded-pixel-observation.ts +227 -0
- package/templates/starter/e2e/export-artifact-helpers.ts +206 -25
- package/templates/starter/e2e/image-artifact-inspection.spec.ts +41 -0
- package/templates/starter/e2e/image-artifact-inspection.ts +99 -0
- package/templates/starter/e2e/performance-canvas-helpers.ts +22 -21
- package/templates/starter/e2e/performance-canvas-quality-guard.spec.ts +312 -0
- package/templates/starter/e2e/performance-canvas-quality-guard.ts +196 -0
- package/templates/starter/e2e/performance-canvas-quality-observer.ts +351 -0
- package/templates/starter/e2e/performance-control-layout-helpers.ts +2 -2
- package/templates/starter/e2e/performance-path-adapter-contract.ts +4 -4
- package/templates/starter/e2e/performance-path-helpers.spec.ts +203 -70
- package/templates/starter/e2e/performance-path-helpers.ts +210 -91
- package/templates/starter/e2e/performance-pipeline-evidence-continuity.spec.ts +76 -0
- package/templates/starter/e2e/performance-pipeline-evidence-test-fixtures.ts +11 -2
- package/templates/starter/e2e/performance-pipeline-invariants.ts +47 -4
- package/templates/starter/e2e/performance-render-scale-runner.spec.ts +140 -38
- package/templates/starter/e2e/video-artifact-inspection.spec.ts +64 -0
- package/templates/starter/e2e/video-artifact-inspection.ts +281 -0
- package/templates/starter/gitignore +1 -0
- package/templates/starter/package.json +1 -0
- package/templates/starter/scripts/check-toolcraft-docs.mjs +17 -0
- package/templates/starter/scripts/toolcraft-contract-manifest.json +1 -0
- package/templates/starter/scripts/toolcraft-delivery-plan-authority.test.mjs +60 -0
- package/templates/starter/scripts/toolcraft-delivery-plan-errors.test.mjs +7 -2
- package/templates/starter/scripts/toolcraft-delivery-plan.mjs +7 -3
- package/templates/starter/scripts/toolcraft-product-boundary-ast.mjs +95 -103
- package/templates/starter/scripts/toolcraft-product-boundary-module-policy.mjs +101 -0
- package/templates/starter/scripts/toolcraft-product-boundary.mjs +12 -0
- package/templates/starter/scripts/toolcraft-product-boundary.test.mjs +0 -26
- 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-evidence-boundary.test.mjs +85 -20
- package/templates/starter/scripts/toolcraft-product-evidence-import-policy.mjs +43 -0
- package/templates/starter/scripts/toolcraft-product-export-boundary.mjs +157 -0
- package/templates/starter/scripts/toolcraft-product-export-boundary.test.mjs +196 -0
- package/templates/starter/scripts/toolcraft-typescript-analysis.d.mts +73 -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-helpers.mjs +318 -0
- package/templates/starter/scripts/toolcraft-unavailable-resource-evidence-facade.test.mjs +157 -206
- package/templates/starter/scripts/toolcraft-verification-inventory.mjs +1 -0
- package/templates/starter/scripts/toolcraft-verification-receipt.test.mjs +51 -0
- package/templates/starter/scripts/toolcraft-vite-env-activation.test.mjs +128 -59
- 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/export-artifact-coverage.ts +113 -0
- 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 +35 -12
- package/templates/starter/src/app/acceptance/output-video-export-rules.ts +99 -0
- package/templates/starter/src/app/acceptance/types.ts +30 -8
- package/templates/starter/src/app/acceptance/validate-coverage.ts +20 -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-artifact.test.ts +131 -0
- 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.keyframes.test.ts +14 -4
- 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 +46 -1
- 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 +13 -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/starter-performance-test-utils.ts +103 -0
- package/templates/starter/src/app/starter-performance.gates.test.ts +231 -278
- package/templates/starter/src/app/starter-performance.lifecycle.test.ts +261 -0
- package/templates/starter/src/app/test-evidence/browser-runtime-contract.ts +4 -2
- package/templates/starter/src/routes/index.tsx +2 -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/runtime/export/export.ts +0 -166
- package/templates/starter/src/app/acceptance/condition-exclusivity.test.ts +0 -60
- package/templates/starter/src/app/acceptance/condition-exclusivity.ts +0 -221
|
@@ -14,6 +14,81 @@ import {
|
|
|
14
14
|
setProofState,
|
|
15
15
|
} from "./browser-semantic-evidence-test-helpers";
|
|
16
16
|
|
|
17
|
+
const orientationBaseline: ToolcraftOrientationBrowserObservation = {
|
|
18
|
+
outputSignature: "model-front",
|
|
19
|
+
pixelSignature: "pixels-front",
|
|
20
|
+
pose: { position: [0, 0, 5], up: [0, 1, 0] },
|
|
21
|
+
poseTarget: "view.orbit",
|
|
22
|
+
presentationCacheKey: "appearance:document-model:v2",
|
|
23
|
+
presentationDocumentId: "document-model",
|
|
24
|
+
viewportOffsetX: 0,
|
|
25
|
+
viewportOffsetY: 0,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const orientationDragged: ToolcraftOrientationBrowserObservation = {
|
|
29
|
+
...orientationBaseline,
|
|
30
|
+
outputSignature: "model-dragged",
|
|
31
|
+
pixelSignature: "pixels-dragged",
|
|
32
|
+
pose: { position: [1, 1, 4.8], up: [0, 1, 0] },
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const orientationOptions = {
|
|
36
|
+
requirementId: "model.orientation",
|
|
37
|
+
stabilityIntervalMs: 0,
|
|
38
|
+
target: "view.orbit",
|
|
39
|
+
} as const;
|
|
40
|
+
|
|
41
|
+
type OrientationProofUiState = Readonly<{
|
|
42
|
+
playbackActions?: readonly ("pause" | "play")[];
|
|
43
|
+
renderScales?: readonly Readonly<{
|
|
44
|
+
maximum: string;
|
|
45
|
+
value: string;
|
|
46
|
+
}>[];
|
|
47
|
+
}>;
|
|
48
|
+
|
|
49
|
+
async function installOrientationProofUiState(
|
|
50
|
+
page: Page,
|
|
51
|
+
state: OrientationProofUiState,
|
|
52
|
+
): Promise<void> {
|
|
53
|
+
await page.locator('[data-slot="toolcraft-runtime-app"]').evaluate(
|
|
54
|
+
(root, proofState) => {
|
|
55
|
+
root.querySelector('[data-orientation-proof-state]')?.remove();
|
|
56
|
+
const fixture = document.createElement("div");
|
|
57
|
+
fixture.dataset.orientationProofState = "";
|
|
58
|
+
|
|
59
|
+
for (const action of proofState.playbackActions ?? []) {
|
|
60
|
+
const button = document.createElement("button");
|
|
61
|
+
const label = action === "play" ? "Play playback" : "Pause playback";
|
|
62
|
+
button.type = "button";
|
|
63
|
+
button.textContent = label;
|
|
64
|
+
button.setAttribute("aria-label", label);
|
|
65
|
+
fixture.append(button);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
for (const [index, renderScale] of (
|
|
69
|
+
proofState.renderScales ?? []
|
|
70
|
+
).entries()) {
|
|
71
|
+
const field = document.createElement("div");
|
|
72
|
+
field.dataset.toolcraftControlTarget = "canvas.renderScale";
|
|
73
|
+
field.dataset.orientationProofRenderScale = String(index);
|
|
74
|
+
const slider = document.createElement("div");
|
|
75
|
+
slider.dataset.slot = "slider";
|
|
76
|
+
slider.setAttribute("aria-valuemax", renderScale.maximum);
|
|
77
|
+
slider.setAttribute("aria-valuemin", "1");
|
|
78
|
+
slider.setAttribute("aria-valuenow", renderScale.value);
|
|
79
|
+
slider.setAttribute("role", "slider");
|
|
80
|
+
Object.assign(slider.style, { height: "20px", width: "120px" });
|
|
81
|
+
slider.textContent = "Render scale";
|
|
82
|
+
field.append(slider);
|
|
83
|
+
fixture.append(field);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
root.append(fixture);
|
|
87
|
+
},
|
|
88
|
+
state,
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
17
92
|
async function installOrientationGizmoPointerProbe(
|
|
18
93
|
page: Page,
|
|
19
94
|
initial: ToolcraftOrientationBrowserObservation,
|
|
@@ -123,33 +198,107 @@ async function installModelOrbitPointerProbe(
|
|
|
123
198
|
);
|
|
124
199
|
}
|
|
125
200
|
|
|
201
|
+
test("orientation axis drag validates paused maximum-quality proof state", async ({
|
|
202
|
+
page,
|
|
203
|
+
}, testInfo) => {
|
|
204
|
+
await page.goto("/");
|
|
205
|
+
const session = await createToolcraftBrowserProofSession(page);
|
|
206
|
+
const attachmentCount = testInfo.attachments.length;
|
|
207
|
+
const observation = session.observe((root) =>
|
|
208
|
+
JSON.parse(root.getAttribute("data-proof-orientation") ?? "null"),
|
|
209
|
+
);
|
|
210
|
+
const invalidStateCases: readonly Readonly<{
|
|
211
|
+
expectedError: RegExp;
|
|
212
|
+
state: OrientationProofUiState;
|
|
213
|
+
}>[] = [
|
|
214
|
+
{
|
|
215
|
+
expectedError: /must be paused.*Play playback/iu,
|
|
216
|
+
state: {
|
|
217
|
+
playbackActions: ["pause"],
|
|
218
|
+
renderScales: [{ maximum: "2", value: "2" }],
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
expectedError: /exactly one standard playback action/iu,
|
|
223
|
+
state: { playbackActions: ["play", "pause"] },
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
expectedError: /canvas\.renderScale.*maximum/iu,
|
|
227
|
+
state: {
|
|
228
|
+
playbackActions: ["play"],
|
|
229
|
+
renderScales: [{ maximum: "2", value: "1" }],
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
expectedError: /exactly one canvas\.renderScale owner/iu,
|
|
234
|
+
state: {
|
|
235
|
+
playbackActions: ["play"],
|
|
236
|
+
renderScales: [
|
|
237
|
+
{ maximum: "2", value: "2" },
|
|
238
|
+
{ maximum: "2", value: "2" },
|
|
239
|
+
],
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
expectedError: /finite aria-valuenow/iu,
|
|
244
|
+
state: {
|
|
245
|
+
playbackActions: ["play"],
|
|
246
|
+
renderScales: [{ maximum: "2", value: "" }],
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
expectedError: /finite aria-valuemax/iu,
|
|
251
|
+
state: {
|
|
252
|
+
playbackActions: ["play"],
|
|
253
|
+
renderScales: [{ maximum: "invalid", value: "2" }],
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
];
|
|
257
|
+
|
|
258
|
+
for (const { expectedError, state } of invalidStateCases) {
|
|
259
|
+
await setProofState(page, "orientation", orientationBaseline);
|
|
260
|
+
await installOrientationGizmoPointerProbe(page, orientationBaseline, {
|
|
261
|
+
outcomes: { drag: orientationDragged },
|
|
262
|
+
});
|
|
263
|
+
await installOrientationProofUiState(page, state);
|
|
264
|
+
await expect(
|
|
265
|
+
expectToolcraftOrientationAxisDrag(observation, session, {
|
|
266
|
+
...orientationOptions,
|
|
267
|
+
dragDelta: { x: 18, y: 12 },
|
|
268
|
+
}),
|
|
269
|
+
).rejects.toThrow(expectedError);
|
|
270
|
+
expect(testInfo.attachments).toHaveLength(attachmentCount);
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
test("orientation axis drag retains proof for products without optional playback or render scale", async ({
|
|
275
|
+
page,
|
|
276
|
+
}) => {
|
|
277
|
+
await page.goto("/");
|
|
278
|
+
const session = await createToolcraftBrowserProofSession(page);
|
|
279
|
+
await setProofState(page, "orientation", orientationBaseline);
|
|
280
|
+
const observation = session.observe((root) =>
|
|
281
|
+
JSON.parse(root.getAttribute("data-proof-orientation") ?? "null"),
|
|
282
|
+
);
|
|
283
|
+
await installOrientationGizmoPointerProbe(page, orientationBaseline, {
|
|
284
|
+
outcomes: { drag: orientationDragged },
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
await expectToolcraftOrientationAxisDrag(observation, session, {
|
|
288
|
+
...orientationOptions,
|
|
289
|
+
dragDelta: { x: 18, y: 12 },
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
|
|
126
293
|
test("orientation recipes require shared pose/output changes and correct canvas ownership", async ({
|
|
127
294
|
page,
|
|
128
295
|
}, testInfo) => {
|
|
129
296
|
await page.goto("/");
|
|
130
297
|
const session = await createToolcraftBrowserProofSession(page);
|
|
131
298
|
const attachmentCount = testInfo.attachments.length;
|
|
132
|
-
const baseline
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
pose: { position: [0, 0, 5], up: [0, 1, 0] },
|
|
136
|
-
poseTarget: "view.orbit",
|
|
137
|
-
presentationCacheKey: "appearance:document-model:v2",
|
|
138
|
-
presentationDocumentId: "document-model",
|
|
139
|
-
viewportOffsetX: 0,
|
|
140
|
-
viewportOffsetY: 0,
|
|
141
|
-
};
|
|
142
|
-
const dragged: ToolcraftOrientationBrowserObservation = {
|
|
143
|
-
...baseline,
|
|
144
|
-
outputSignature: "model-dragged",
|
|
145
|
-
pixelSignature: "pixels-dragged",
|
|
146
|
-
pose: { position: [1, 1, 4.8], up: [0, 1, 0] },
|
|
147
|
-
};
|
|
148
|
-
const options = {
|
|
149
|
-
requirementId: "model.orientation",
|
|
150
|
-
stabilityIntervalMs: 0,
|
|
151
|
-
target: "view.orbit",
|
|
152
|
-
} as const;
|
|
299
|
+
const baseline = orientationBaseline;
|
|
300
|
+
const dragged = orientationDragged;
|
|
301
|
+
const options = orientationOptions;
|
|
153
302
|
|
|
154
303
|
await setProofState(page, "orientation", baseline);
|
|
155
304
|
const observation = session.observe((root) =>
|
|
@@ -175,6 +324,10 @@ test("orientation recipes require shared pose/output changes and correct canvas
|
|
|
175
324
|
expect(testInfo.attachments).toHaveLength(attachmentCount);
|
|
176
325
|
|
|
177
326
|
await setProofState(page, "orientation", baseline);
|
|
327
|
+
await installOrientationProofUiState(page, {
|
|
328
|
+
playbackActions: ["play"],
|
|
329
|
+
renderScales: [{ maximum: "2", value: "2" }],
|
|
330
|
+
});
|
|
178
331
|
await installOrientationGizmoPointerProbe(page, baseline, {
|
|
179
332
|
dragCommit: "pointerup",
|
|
180
333
|
outcomes: { drag: dragged },
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { expect, test, type Page, type TestInfo } from "@playwright/test";
|
|
2
2
|
|
|
3
|
+
import {
|
|
4
|
+
parseToolcraftBrowserRuntimeEvidence,
|
|
5
|
+
} from "../src/app/test-evidence/browser-runtime-contract";
|
|
3
6
|
import { attachedEvidenceTypes } from "./browser-semantic-evidence-test-helpers";
|
|
4
7
|
import {
|
|
5
8
|
expectToolcraftCanvasRenderScaleEvidence,
|
|
@@ -89,6 +92,24 @@ test("selected 2x rejects a 1x backing store and attaches no evidence", async ({
|
|
|
89
92
|
expect(testInfo.attachments).toHaveLength(attachmentCount);
|
|
90
93
|
});
|
|
91
94
|
|
|
95
|
+
test("selected 2x rejects a 3x backing store and attaches no evidence", async ({
|
|
96
|
+
page,
|
|
97
|
+
}, testInfo: TestInfo) => {
|
|
98
|
+
await installCanvas(page, 3);
|
|
99
|
+
const attachmentCount = testInfo.attachments.length;
|
|
100
|
+
|
|
101
|
+
await expect(
|
|
102
|
+
expectToolcraftCanvasRenderScaleEvidence(page, {
|
|
103
|
+
canvasSelector,
|
|
104
|
+
requirementId: "canvas.render-scale",
|
|
105
|
+
selectedScale: 2,
|
|
106
|
+
stateTransitions: [transition("steady", () => setBackingScale(page, 3))],
|
|
107
|
+
target: "canvas.renderScale",
|
|
108
|
+
}),
|
|
109
|
+
).rejects.toThrow(/backing width.*one physical pixel/iu);
|
|
110
|
+
expect(testInfo.attachments).toHaveLength(attachmentCount);
|
|
111
|
+
});
|
|
112
|
+
|
|
92
113
|
test("a backing clamp introduced by a state transition fails the whole recipe", async ({
|
|
93
114
|
page,
|
|
94
115
|
}, testInfo: TestInfo) => {
|
|
@@ -164,15 +185,23 @@ test("performance render-scale evidence attaches only after real backing proof",
|
|
|
164
185
|
const attachmentCount = testInfo.attachments.length;
|
|
165
186
|
|
|
166
187
|
await expectToolcraftPerformanceRenderScaleBackingEvidence(page, {
|
|
188
|
+
baselineCssSize: { height: 80, width: 120 },
|
|
167
189
|
canvasSelector,
|
|
190
|
+
cssSizePolicy: "fixed",
|
|
168
191
|
pathId: "performance-path:render-scale",
|
|
169
|
-
|
|
192
|
+
phase: "cold",
|
|
170
193
|
target: "canvas.renderScale",
|
|
171
194
|
});
|
|
172
195
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
196
|
+
const [qualityEvidence] = testInfo.attachments
|
|
197
|
+
.slice(attachmentCount)
|
|
198
|
+
.map(parseToolcraftBrowserRuntimeEvidence)
|
|
199
|
+
.filter(
|
|
200
|
+
(evidence) => evidence?.evidenceType === "performance-render-scale",
|
|
201
|
+
);
|
|
202
|
+
expect(qualityEvidence?.requirementId).toBe(
|
|
203
|
+
"performance-path:render-scale#cold",
|
|
204
|
+
);
|
|
176
205
|
});
|
|
177
206
|
|
|
178
207
|
test("performance render-scale evidence rejects a quality clamp without attaching", async ({
|
|
@@ -183,11 +212,36 @@ test("performance render-scale evidence rejects a quality clamp without attachin
|
|
|
183
212
|
|
|
184
213
|
await expect(
|
|
185
214
|
expectToolcraftPerformanceRenderScaleBackingEvidence(page, {
|
|
215
|
+
baselineCssSize: { height: 80, width: 120 },
|
|
186
216
|
canvasSelector,
|
|
217
|
+
cssSizePolicy: "fixed",
|
|
187
218
|
pathId: "performance-path:render-scale",
|
|
188
|
-
|
|
219
|
+
phase: "warm",
|
|
189
220
|
target: "canvas.renderScale",
|
|
190
221
|
}),
|
|
191
|
-
).rejects.toThrow(/backing width
|
|
222
|
+
).rejects.toThrow(/warm.*backing width/iu);
|
|
223
|
+
expect(testInfo.attachments).toHaveLength(attachmentCount);
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
test("performance render-scale evidence rejects a changed CSS baseline", async ({
|
|
227
|
+
page,
|
|
228
|
+
}, testInfo: TestInfo) => {
|
|
229
|
+
await installCanvas(page, 2);
|
|
230
|
+
const attachmentCount = testInfo.attachments.length;
|
|
231
|
+
await page.locator(canvasSelector).evaluate((canvas) => {
|
|
232
|
+
canvas.setAttribute("style", "display:block;width:60px;height:40px");
|
|
233
|
+
});
|
|
234
|
+
await setBackingScale(page, 2);
|
|
235
|
+
|
|
236
|
+
await expect(
|
|
237
|
+
expectToolcraftPerformanceRenderScaleBackingEvidence(page, {
|
|
238
|
+
baselineCssSize: { height: 80, width: 120 },
|
|
239
|
+
canvasSelector,
|
|
240
|
+
cssSizePolicy: "fixed",
|
|
241
|
+
pathId: "performance-path:render-scale",
|
|
242
|
+
phase: "sustained",
|
|
243
|
+
target: "canvas.renderScale",
|
|
244
|
+
}),
|
|
245
|
+
).rejects.toThrow(/sustained.*preserve.*CSS width/iu);
|
|
192
246
|
expect(testInfo.attachments).toHaveLength(attachmentCount);
|
|
193
247
|
});
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { expect, test } from "@playwright/test";
|
|
2
|
+
import {
|
|
3
|
+
defineToolcraft,
|
|
4
|
+
type ToolcraftPerformancePath,
|
|
5
|
+
} from "@repo/toolcraft-runtime";
|
|
2
6
|
|
|
3
7
|
import type { ToolcraftComponentAcceptance } from "../src/app/starter-acceptance";
|
|
4
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
deriveToolcraftBrowserRuntimeRequirements,
|
|
10
|
+
deriveToolcraftPerformancePathRuntimeRequirements,
|
|
11
|
+
} from "./browser-runtime-evidence-requirements";
|
|
5
12
|
|
|
6
13
|
function renderScaleAcceptance(
|
|
7
14
|
states: readonly ("interaction" | "playback" | "steady")[],
|
|
@@ -57,6 +64,20 @@ test("render-scale coverage derives one exact functional requirement per state",
|
|
|
57
64
|
]);
|
|
58
65
|
});
|
|
59
66
|
|
|
67
|
+
test("render-scale backing replaces generic visual-change evidence", () => {
|
|
68
|
+
const requirements = deriveToolcraftBrowserRuntimeRequirements([
|
|
69
|
+
renderScaleAcceptance(["interaction", "steady"]),
|
|
70
|
+
]);
|
|
71
|
+
|
|
72
|
+
expect(requirements.map(({ evidenceType }) => evidenceType)).not.toContain(
|
|
73
|
+
"product-observable-change",
|
|
74
|
+
);
|
|
75
|
+
expect(requirements.map(({ evidenceType }) => evidenceType)).toEqual([
|
|
76
|
+
"canvas-render-scale-backing",
|
|
77
|
+
"canvas-render-scale-backing",
|
|
78
|
+
]);
|
|
79
|
+
});
|
|
80
|
+
|
|
60
81
|
test("render-scale functional requirements remain separate from performance evidence", () => {
|
|
61
82
|
const requirements = deriveToolcraftBrowserRuntimeRequirements([
|
|
62
83
|
renderScaleAcceptance(["interaction", "steady"]),
|
|
@@ -69,3 +90,58 @@ test("render-scale functional requirements remain separate from performance evid
|
|
|
69
90
|
"performance-render-scale",
|
|
70
91
|
);
|
|
71
92
|
});
|
|
93
|
+
|
|
94
|
+
const unrelatedPerformancePaths = [
|
|
95
|
+
{
|
|
96
|
+
id: "performance-path:color",
|
|
97
|
+
interaction: "control-drag",
|
|
98
|
+
invalidates: ["composite"],
|
|
99
|
+
profile: "live-interaction",
|
|
100
|
+
runsOn: ["main"],
|
|
101
|
+
targets: ["appearance.color"],
|
|
102
|
+
workloadDimensions: [],
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
id: "performance-path:viewport",
|
|
106
|
+
interaction: "viewport-drag",
|
|
107
|
+
invalidates: ["composite"],
|
|
108
|
+
profile: "frame-budget",
|
|
109
|
+
runsOn: ["main"],
|
|
110
|
+
targets: [],
|
|
111
|
+
workloadDimensions: [],
|
|
112
|
+
},
|
|
113
|
+
] as const satisfies readonly ToolcraftPerformancePath[];
|
|
114
|
+
|
|
115
|
+
test("every raster performance path derives cold, warm, and sustained 2x requirements", () => {
|
|
116
|
+
const requirements = deriveToolcraftPerformancePathRuntimeRequirements(
|
|
117
|
+
unrelatedPerformancePaths,
|
|
118
|
+
defineToolcraft({
|
|
119
|
+
canvas: { enabled: true, renderScale: true },
|
|
120
|
+
panels: {},
|
|
121
|
+
}),
|
|
122
|
+
).filter(({ evidenceType }) => evidenceType === "performance-render-scale");
|
|
123
|
+
|
|
124
|
+
expect(requirements).toEqual([
|
|
125
|
+
expect.objectContaining({ requirementId: "performance-path:color#cold" }),
|
|
126
|
+
expect.objectContaining({ requirementId: "performance-path:color#warm" }),
|
|
127
|
+
expect.objectContaining({
|
|
128
|
+
requirementId: "performance-path:color#sustained",
|
|
129
|
+
}),
|
|
130
|
+
expect.objectContaining({ requirementId: "performance-path:viewport#cold" }),
|
|
131
|
+
expect.objectContaining({ requirementId: "performance-path:viewport#warm" }),
|
|
132
|
+
expect.objectContaining({
|
|
133
|
+
requirementId: "performance-path:viewport#sustained",
|
|
134
|
+
}),
|
|
135
|
+
]);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
test("vector performance paths derive no raster quality requirements", () => {
|
|
139
|
+
const requirements = deriveToolcraftPerformancePathRuntimeRequirements(
|
|
140
|
+
unrelatedPerformancePaths,
|
|
141
|
+
defineToolcraft({ canvas: { enabled: true }, panels: {} }),
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
expect(requirements.map(({ evidenceType }) => evidenceType)).not.toContain(
|
|
145
|
+
"performance-render-scale",
|
|
146
|
+
);
|
|
147
|
+
});
|
|
@@ -23,6 +23,13 @@ test("protected observable evidence is attached only after its assertion succeed
|
|
|
23
23
|
const output = document.createElement("div");
|
|
24
24
|
output.dataset.toolcraftProductOutput = "";
|
|
25
25
|
output.dataset.toolcraftProofProductOutput = "";
|
|
26
|
+
output.style.backgroundColor = "#000000";
|
|
27
|
+
output.style.height = "24px";
|
|
28
|
+
output.style.left = "0";
|
|
29
|
+
output.style.position = "fixed";
|
|
30
|
+
output.style.top = "0";
|
|
31
|
+
output.style.width = "24px";
|
|
32
|
+
output.style.zIndex = "100";
|
|
26
33
|
output.textContent = "Before";
|
|
27
34
|
const button = document.createElement("button");
|
|
28
35
|
button.id = "change-output";
|
|
@@ -46,6 +53,7 @@ test("protected observable evidence is attached only after its assertion succeed
|
|
|
46
53
|
button.dataset.activated = "true";
|
|
47
54
|
});
|
|
48
55
|
await currentPage.locator('[data-toolcraft-proof-product-output]').evaluate((output) => {
|
|
56
|
+
(output as HTMLElement).style.backgroundColor = "#FFFFFF";
|
|
49
57
|
output.textContent = "After";
|
|
50
58
|
});
|
|
51
59
|
}),
|
|
@@ -135,6 +135,41 @@ test("performance marker requires every derived scenario evidence type", () => {
|
|
|
135
135
|
expect(errors).toContainEqual(expect.stringContaining("performance-budget"));
|
|
136
136
|
});
|
|
137
137
|
|
|
138
|
+
test("performance reporter rejects missing warm and sustained raster quality evidence", () => {
|
|
139
|
+
const testName = "browser perf: toolcraft path performance-path:color";
|
|
140
|
+
const requirements: ToolcraftBrowserRuntimeRequirement[] = [
|
|
141
|
+
"cold",
|
|
142
|
+
"warm",
|
|
143
|
+
"sustained",
|
|
144
|
+
].map((phase) => ({
|
|
145
|
+
evidenceType: "performance-render-scale",
|
|
146
|
+
requirementId: `performance-path:color#${phase}`,
|
|
147
|
+
target: "appearance.color",
|
|
148
|
+
testName,
|
|
149
|
+
}));
|
|
150
|
+
const marker = fakeTestCase({
|
|
151
|
+
file: "/product/e2e/app-browser-runtime-evidence.spec.ts",
|
|
152
|
+
title: TOOLCRAFT_BROWSER_PERFORMANCE_MARKER_TEST_NAME,
|
|
153
|
+
});
|
|
154
|
+
const scenarioTest = fakeTestCase({
|
|
155
|
+
results: [passedResultWithEvidence(requirements[0]!)],
|
|
156
|
+
title: testName,
|
|
157
|
+
});
|
|
158
|
+
const errors: string[] = [];
|
|
159
|
+
const reporter = new ToolcraftBrowserRuntimeEvidenceReporter({
|
|
160
|
+
acceptanceRequirements: [],
|
|
161
|
+
performanceRequirements: requirements,
|
|
162
|
+
reportError: (error) => errors.push(error),
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
reporter.onBegin?.({} as never, fakeSuite([marker, scenarioTest]));
|
|
166
|
+
expect(reporter.onEnd?.({ status: "passed" } as never)).toEqual({
|
|
167
|
+
status: "failed",
|
|
168
|
+
});
|
|
169
|
+
expect(errors).toContainEqual(expect.stringContaining("#warm"));
|
|
170
|
+
expect(errors).toContainEqual(expect.stringContaining("#sustained"));
|
|
171
|
+
});
|
|
172
|
+
|
|
138
173
|
test("runtime evidence reporter requires render-scale proof for every covered state", () => {
|
|
139
174
|
const testName = "browser: canvas render scale backing pixels";
|
|
140
175
|
const requirements: ToolcraftBrowserRuntimeRequirement[] = [
|
|
@@ -35,7 +35,10 @@ test("derived paths own one canonical browser evidence requirement set", () => {
|
|
|
35
35
|
},
|
|
36
36
|
] as const;
|
|
37
37
|
|
|
38
|
-
const requirements = deriveToolcraftPerformancePathRuntimeRequirements(
|
|
38
|
+
const requirements = deriveToolcraftPerformancePathRuntimeRequirements(
|
|
39
|
+
[path],
|
|
40
|
+
defineToolcraft({ canvas: { enabled: true }, panels: {} }),
|
|
41
|
+
);
|
|
39
42
|
|
|
40
43
|
expect(requirements.map(({ evidenceType }) => evidenceType)).toEqual([
|
|
41
44
|
"performance-measurement",
|
|
@@ -130,7 +133,7 @@ test("control schema derives segmented and discrete runtime evidence", () => {
|
|
|
130
133
|
);
|
|
131
134
|
});
|
|
132
135
|
|
|
133
|
-
test("typed
|
|
136
|
+
test("typed background coverage derives dedicated semantic evidence", () => {
|
|
134
137
|
const schema = defineToolcraft({
|
|
135
138
|
canvas: { enabled: true },
|
|
136
139
|
panels: {
|
|
@@ -138,19 +141,6 @@ test("typed visibility and background coverage derive dedicated semantic evidenc
|
|
|
138
141
|
sections: [
|
|
139
142
|
{
|
|
140
143
|
controls: {
|
|
141
|
-
conditional: {
|
|
142
|
-
defaultValue: 1,
|
|
143
|
-
label: "Conditional",
|
|
144
|
-
target: "feature.conditional",
|
|
145
|
-
type: "slider",
|
|
146
|
-
visibleWhen: { equals: true, target: "feature.enabled" },
|
|
147
|
-
},
|
|
148
|
-
enabled: {
|
|
149
|
-
defaultValue: false,
|
|
150
|
-
label: "Enabled",
|
|
151
|
-
target: "feature.enabled",
|
|
152
|
-
type: "switch",
|
|
153
|
-
},
|
|
154
144
|
includeBackground: {
|
|
155
145
|
defaultValue: true,
|
|
156
146
|
label: "Include",
|
|
@@ -178,14 +168,6 @@ test("typed visibility and background coverage derive dedicated semantic evidenc
|
|
|
178
168
|
});
|
|
179
169
|
const requirements = deriveToolcraftBrowserRuntimeRequirements(
|
|
180
170
|
[
|
|
181
|
-
{
|
|
182
|
-
browser: true,
|
|
183
|
-
browserTestName: "browser: conditional visibility",
|
|
184
|
-
evidence: "product-output",
|
|
185
|
-
id: "feature.conditional",
|
|
186
|
-
target: "feature.conditional",
|
|
187
|
-
visibilityCoverage: ["hidden", "visible"],
|
|
188
|
-
},
|
|
189
171
|
{
|
|
190
172
|
backgroundOutputCoverage: [
|
|
191
173
|
"preview-hidden-when-excluded",
|
|
@@ -202,17 +184,6 @@ test("typed visibility and background coverage derive dedicated semantic evidenc
|
|
|
202
184
|
],
|
|
203
185
|
schema,
|
|
204
186
|
);
|
|
205
|
-
|
|
206
|
-
expect(
|
|
207
|
-
requirements
|
|
208
|
-
.filter((requirement) => requirement.requirementId === "feature.conditional")
|
|
209
|
-
.map((requirement) => requirement.evidenceType),
|
|
210
|
-
).toEqual(
|
|
211
|
-
expect.arrayContaining([
|
|
212
|
-
"conditional-control-hidden",
|
|
213
|
-
"conditional-control-visible",
|
|
214
|
-
]),
|
|
215
|
-
);
|
|
216
187
|
expect(
|
|
217
188
|
requirements
|
|
218
189
|
.filter((requirement) => requirement.requirementId === "export.includeBackground")
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { expect, test } from "@playwright/test";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
expectToolcraftConditionalControlVisibility,
|
|
5
|
-
} from "./browser-conditional-output-evidence-helpers";
|
|
2
|
+
import { expectToolcraftBackgroundOutputSemantics } from "./browser-background-output-evidence";
|
|
3
|
+
import { expectToolcraftControlApplicabilityState } from "./browser-control-applicability-evidence";
|
|
6
4
|
import {
|
|
7
5
|
expectToolcraftLayerReorder,
|
|
8
6
|
expectToolcraftLayerSelection,
|
|
@@ -12,6 +10,7 @@ import {
|
|
|
12
10
|
attachedEvidenceTypes,
|
|
13
11
|
setProofState,
|
|
14
12
|
setSyntheticControlOwner,
|
|
13
|
+
setSyntheticSwitchControlOwner,
|
|
15
14
|
} from "./browser-semantic-evidence-test-helpers";
|
|
16
15
|
import {
|
|
17
16
|
expectToolcraftMediaLifecycle,
|
|
@@ -169,7 +168,6 @@ test("layer recipes reject collection substitution and prove exact reorder", asy
|
|
|
169
168
|
expect(attachedEvidenceTypes(testInfo, attachmentCount)).toEqual([
|
|
170
169
|
"product-observable-change",
|
|
171
170
|
"layer-reorder",
|
|
172
|
-
"product-observable-change",
|
|
173
171
|
"layer-selection",
|
|
174
172
|
]);
|
|
175
173
|
});
|
|
@@ -316,34 +314,81 @@ test("timeline recipes bind duration to renderer, keyframes to output, and loops
|
|
|
316
314
|
]);
|
|
317
315
|
});
|
|
318
316
|
|
|
319
|
-
test("
|
|
317
|
+
test("control applicability recipe proves exact target absence and presence", async ({
|
|
320
318
|
page,
|
|
321
319
|
}, testInfo) => {
|
|
322
320
|
await page.goto("/");
|
|
323
321
|
const session = await createToolcraftBrowserProofSession(page);
|
|
324
322
|
const attachmentCount = testInfo.attachments.length;
|
|
325
|
-
await
|
|
323
|
+
await setSyntheticSwitchControlOwner(page, "feature.enabled", false);
|
|
326
324
|
await setSyntheticControlOwner(page, "feature.conditional", true);
|
|
327
325
|
|
|
328
|
-
|
|
326
|
+
const hiddenCase = {
|
|
327
|
+
expectation: "hidden" as const,
|
|
328
|
+
selectorControlType: "switch" as const,
|
|
329
|
+
selectorLabel: "feature.enabled",
|
|
330
|
+
selectorTarget: "feature.enabled",
|
|
331
|
+
selectorValue: false,
|
|
332
|
+
target: "feature.conditional",
|
|
333
|
+
};
|
|
334
|
+
const visibleCase = {
|
|
335
|
+
...hiddenCase,
|
|
336
|
+
expectation: "visible" as const,
|
|
337
|
+
selectorValue: true,
|
|
338
|
+
};
|
|
339
|
+
const mismatchedAction = session.controlAction(
|
|
340
|
+
"feature.other",
|
|
341
|
+
() => undefined,
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
await expect(
|
|
345
|
+
expectToolcraftControlApplicabilityState(
|
|
346
|
+
session,
|
|
347
|
+
mismatchedAction,
|
|
348
|
+
hiddenCase,
|
|
349
|
+
{ baseRequirementId: "feature.conditional", timeoutMs: 50 },
|
|
350
|
+
),
|
|
351
|
+
).rejects.toThrow(/target-scoped selector action/);
|
|
352
|
+
expect(testInfo.attachments).toHaveLength(attachmentCount);
|
|
353
|
+
|
|
354
|
+
await expect(
|
|
355
|
+
expectToolcraftControlApplicabilityState(
|
|
356
|
+
session,
|
|
357
|
+
session.controlAction("feature.enabled", () => undefined),
|
|
358
|
+
hiddenCase,
|
|
359
|
+
{ baseRequirementId: "feature.conditional", timeoutMs: 50 },
|
|
360
|
+
),
|
|
361
|
+
).rejects.toThrow(/should be hidden/);
|
|
362
|
+
expect(testInfo.attachments).toHaveLength(attachmentCount);
|
|
363
|
+
|
|
364
|
+
await expectToolcraftControlApplicabilityState(
|
|
329
365
|
session,
|
|
330
366
|
session.controlAction("feature.enabled", (control, currentPage) => {
|
|
331
367
|
expect(control).toBeTruthy();
|
|
332
|
-
return
|
|
368
|
+
return Promise.all([
|
|
369
|
+
setSyntheticSwitchControlOwner(currentPage, "feature.enabled", false),
|
|
370
|
+
setSyntheticControlOwner(currentPage, "feature.conditional", false),
|
|
371
|
+
]).then(() => undefined);
|
|
333
372
|
}),
|
|
373
|
+
hiddenCase,
|
|
374
|
+
{ baseRequirementId: "feature.conditional" },
|
|
375
|
+
);
|
|
376
|
+
await expectToolcraftControlApplicabilityState(
|
|
377
|
+
session,
|
|
334
378
|
session.controlAction("feature.enabled", (control, currentPage) => {
|
|
335
379
|
expect(control).toBeTruthy();
|
|
336
|
-
return
|
|
380
|
+
return Promise.all([
|
|
381
|
+
setSyntheticSwitchControlOwner(currentPage, "feature.enabled", true),
|
|
382
|
+
setSyntheticControlOwner(currentPage, "feature.conditional", true),
|
|
383
|
+
]).then(() => undefined);
|
|
337
384
|
}),
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
target: "feature.conditional",
|
|
341
|
-
},
|
|
385
|
+
visibleCase,
|
|
386
|
+
{ baseRequirementId: "feature.conditional" },
|
|
342
387
|
);
|
|
343
388
|
|
|
344
389
|
expect(attachedEvidenceTypes(testInfo, attachmentCount)).toEqual([
|
|
345
|
-
"
|
|
346
|
-
"
|
|
390
|
+
"control-applicability-hidden",
|
|
391
|
+
"control-applicability-visible",
|
|
347
392
|
]);
|
|
348
393
|
});
|
|
349
394
|
|