@flighthq/scene-document 0.5.1-next.903.f434bc2 → 0.5.1-next.905.5fbf787
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/README.md
CHANGED
|
@@ -13,5 +13,5 @@ Import the supported application-facing API from `@flighthq/scene-document`. The
|
|
|
13
13
|
This package is part of the locked-version Flight SDK graph. Applications may instead install and import `@flighthq/sdk` when package-level tree shaking is sufficient.
|
|
14
14
|
|
|
15
15
|
- [Flight project](https://github.com/flighthq/flight)
|
|
16
|
-
- [Source for @flighthq/scene-document@0.5.1-next.
|
|
17
|
-
- [License](https://github.com/flighthq/flight/blob/
|
|
16
|
+
- [Source for @flighthq/scene-document@0.5.1-next.905.5fbf787](https://github.com/flighthq/flight/tree/5fbf7874064c384307542d68b4dcb6a895ff0dcf/packages/scene-document)
|
|
17
|
+
- [License](https://github.com/flighthq/flight/blob/5fbf7874064c384307542d68b4dcb6a895ff0dcf/LICENSE.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flighthq/scene-document",
|
|
3
|
-
"version": "0.5.1-next.
|
|
3
|
+
"version": "0.5.1-next.905.5fbf787",
|
|
4
4
|
"author": "Joshua Granick and other contributors",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -38,15 +38,15 @@
|
|
|
38
38
|
"clean:dist": "tsx ../../scripts/clean-package-dist.ts"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@flighthq/camera": "0.5.1-next.
|
|
42
|
-
"@flighthq/entity": "0.5.1-next.
|
|
43
|
-
"@flighthq/geometry": "0.5.1-next.
|
|
44
|
-
"@flighthq/lighting": "0.5.1-next.
|
|
45
|
-
"@flighthq/node": "0.5.1-next.
|
|
46
|
-
"@flighthq/registry": "0.5.1-next.
|
|
47
|
-
"@flighthq/scene2d": "0.5.1-next.
|
|
48
|
-
"@flighthq/scene3d": "0.5.1-next.
|
|
49
|
-
"@flighthq/types": "0.5.1-next.
|
|
41
|
+
"@flighthq/camera": "0.5.1-next.905.5fbf787",
|
|
42
|
+
"@flighthq/entity": "0.5.1-next.905.5fbf787",
|
|
43
|
+
"@flighthq/geometry": "0.5.1-next.905.5fbf787",
|
|
44
|
+
"@flighthq/lighting": "0.5.1-next.905.5fbf787",
|
|
45
|
+
"@flighthq/node": "0.5.1-next.905.5fbf787",
|
|
46
|
+
"@flighthq/registry": "0.5.1-next.905.5fbf787",
|
|
47
|
+
"@flighthq/scene2d": "0.5.1-next.905.5fbf787",
|
|
48
|
+
"@flighthq/scene3d": "0.5.1-next.905.5fbf787",
|
|
49
|
+
"@flighthq/types": "0.5.1-next.905.5fbf787"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@flighthq/camera": "*",
|
|
@@ -3,7 +3,12 @@ import { createAmbientLight } from '@flighthq/lighting/contract';
|
|
|
3
3
|
import type { FlightDocument } from '@flighthq/types/contract';
|
|
4
4
|
import { FlightDocumentRefusalReason } from '@flighthq/types/contract';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
explainFlightDocumentText,
|
|
8
|
+
formatFlightDocumentText,
|
|
9
|
+
initializeFlightDocumentRefusalExplanation,
|
|
10
|
+
parseFlightDocumentText,
|
|
11
|
+
} from './flightDocumentText';
|
|
7
12
|
import { parseSceneDocumentYamlSubset } from './sceneDocumentYamlSubset';
|
|
8
13
|
|
|
9
14
|
describe('explainFlightDocumentText', () => {
|
|
@@ -265,6 +270,11 @@ describe('formatFlightDocumentText', () => {
|
|
|
265
270
|
});
|
|
266
271
|
});
|
|
267
272
|
|
|
273
|
+
describe('initializeFlightDocumentRefusalExplanation', () => {
|
|
274
|
+
it('is the construction initializer of createFlightDocumentRefusalExplanation', () => {
|
|
275
|
+
expect(typeof initializeFlightDocumentRefusalExplanation).toBe('function');
|
|
276
|
+
});
|
|
277
|
+
});
|
|
268
278
|
describe('parseFlightDocumentText', () => {
|
|
269
279
|
it('parses mixed dimensions over one shared resource table', () => {
|
|
270
280
|
const document = parseFlightDocumentText(
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
checkUnregisteredNodeKindsFromRaw,
|
|
19
19
|
createDocumentRefusal,
|
|
20
20
|
createSceneRefusal,
|
|
21
|
+
initializeDocumentRefusal,
|
|
21
22
|
} from './sceneDocumentRefusal';
|
|
22
23
|
|
|
23
24
|
describe('checkFlightDocumentFields', () => {
|
|
@@ -225,3 +226,8 @@ function createTestSchemas(registeredKind: string): FlightDocumentSchemaRegistry
|
|
|
225
226
|
shapeCommandSchemas: createKeyedTable('flight-document.shape-command', 'none'),
|
|
226
227
|
};
|
|
227
228
|
}
|
|
229
|
+
describe('initializeDocumentRefusal', () => {
|
|
230
|
+
it('is the construction initializer of createDocumentRefusal', () => {
|
|
231
|
+
expect(typeof initializeDocumentRefusal).toBe('function');
|
|
232
|
+
});
|
|
233
|
+
});
|
|
@@ -31,6 +31,8 @@ import {
|
|
|
31
31
|
createFlightDocumentScene2DMaterializationFromText,
|
|
32
32
|
explainFlightDocumentRefusal,
|
|
33
33
|
explainFlightDocumentRefusalFromText,
|
|
34
|
+
initializeFlightDocumentFromScene2D,
|
|
35
|
+
initializeFlightDocumentScene2DMaterialization,
|
|
34
36
|
} from './sceneDocumentScene2DMaterialization';
|
|
35
37
|
|
|
36
38
|
describe('createFlightDocumentFromScene2D', () => {
|
|
@@ -574,6 +576,109 @@ describe('formatFlightDocumentText', () => {
|
|
|
574
576
|
});
|
|
575
577
|
});
|
|
576
578
|
|
|
579
|
+
describe('initializeFlightDocumentFromScene2D', () => {
|
|
580
|
+
it('is the construction initializer of createFlightDocumentFromScene2D', () => {
|
|
581
|
+
expect(typeof initializeFlightDocumentFromScene2D).toBe('function');
|
|
582
|
+
});
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
describe('initializeFlightDocumentScene2DMaterialization', () => {
|
|
586
|
+
it('is the construction initializer of createFlightDocumentScene2DMaterialization', () => {
|
|
587
|
+
expect(typeof initializeFlightDocumentScene2DMaterialization).toBe('function');
|
|
588
|
+
});
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
function createTestDocument(
|
|
592
|
+
scene: FlightDocumentScene,
|
|
593
|
+
resources: FlightDocumentResourceDescriptor[] = [],
|
|
594
|
+
): FlightDocument {
|
|
595
|
+
return { defaultScene: 0, resources, scenes: [scene], version: 1 };
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
function singleTargetLayout(target: string) {
|
|
599
|
+
return {
|
|
600
|
+
targets: [target],
|
|
601
|
+
tree: { nodes: [{ containerStyle: null, itemStyle: null, kind: 'acme.Leaf', parentIndex: -1 }] },
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
function createTestSchemas(): FlightDocumentSchemaRegistry {
|
|
606
|
+
const displayObjectSchema: FlightDocumentNodeSchema = {
|
|
607
|
+
createNode: (fields: Readonly<FlightDocumentFields>, _resources: FlightDocumentResourceLookup) => {
|
|
608
|
+
const obj = createDisplayObject();
|
|
609
|
+
applyTransformFields(obj, fields);
|
|
610
|
+
return obj;
|
|
611
|
+
},
|
|
612
|
+
fields: TRANSFORM_FIELD_SCHEMAS,
|
|
613
|
+
kind: DisplayObjectKind,
|
|
614
|
+
writeNodeFields: (out: FlightDocumentFields, source: Readonly<NodeAny>) => {
|
|
615
|
+
writeTransformFields(out, source as Node2D);
|
|
616
|
+
return true;
|
|
617
|
+
},
|
|
618
|
+
};
|
|
619
|
+
|
|
620
|
+
const spriteSchema: FlightDocumentNodeSchema = {
|
|
621
|
+
createNode: (fields: Readonly<FlightDocumentFields>, _resources: FlightDocumentResourceLookup) => {
|
|
622
|
+
const sprite = createSprite();
|
|
623
|
+
applyTransformFields(sprite, fields);
|
|
624
|
+
return sprite;
|
|
625
|
+
},
|
|
626
|
+
fields: TRANSFORM_FIELD_SCHEMAS,
|
|
627
|
+
kind: SpriteKind,
|
|
628
|
+
writeNodeFields: (out: FlightDocumentFields, source: Readonly<NodeAny>) => {
|
|
629
|
+
writeTransformFields(out, source as Node2D);
|
|
630
|
+
return true;
|
|
631
|
+
},
|
|
632
|
+
};
|
|
633
|
+
|
|
634
|
+
let nodeSchemas = createKeyedTable<FlightDocumentNodeSchema>('flight-document.node', 'none');
|
|
635
|
+
nodeSchemas = withRegistryTableEntry(nodeSchemas, DisplayObjectKind, displayObjectSchema);
|
|
636
|
+
nodeSchemas = withRegistryTableEntry(nodeSchemas, SpriteKind, spriteSchema);
|
|
637
|
+
|
|
638
|
+
return {
|
|
639
|
+
interactiveStateExtensionSchemas: createKeyedTable('flight-document.interactive-state-extension', 'none'),
|
|
640
|
+
interactiveStateTransitionSchemas: createKeyedTable('flight-document.interactive-state-transition', 'none'),
|
|
641
|
+
nodeSchemas,
|
|
642
|
+
resourceSchemas: createKeyedTable('flight-document.resource', 'none'),
|
|
643
|
+
shapeCommandSchemas: createKeyedTable('flight-document.shape-command', 'none'),
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
function applyTransformFields(target: Node2D, fields: Readonly<FlightDocumentFields>): void {
|
|
648
|
+
if (typeof fields['name'] === 'string') target.name = fields['name'];
|
|
649
|
+
if (typeof fields['x'] === 'number') target.x = fields['x'];
|
|
650
|
+
if (typeof fields['y'] === 'number') target.y = fields['y'];
|
|
651
|
+
if (typeof fields['scaleX'] === 'number') target.scaleX = fields['scaleX'];
|
|
652
|
+
if (typeof fields['scaleY'] === 'number') target.scaleY = fields['scaleY'];
|
|
653
|
+
if (typeof fields['rotation'] === 'number') target.rotation = fields['rotation'];
|
|
654
|
+
if (typeof fields['alpha'] === 'number') target.alpha = fields['alpha'];
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
function writeTransformFields(out: FlightDocumentFields, source: Readonly<Node2D>): void {
|
|
658
|
+
if (source.name !== null) out['name'] = source.name;
|
|
659
|
+
if (source.x !== 0) out['x'] = source.x;
|
|
660
|
+
if (source.y !== 0) out['y'] = source.y;
|
|
661
|
+
if (source.scaleX !== 1) out['scaleX'] = source.scaleX;
|
|
662
|
+
if (source.scaleY !== 1) out['scaleY'] = source.scaleY;
|
|
663
|
+
if (source.rotation !== 0) out['rotation'] = source.rotation;
|
|
664
|
+
if (source.alpha !== 1) out['alpha'] = source.alpha;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
const TRANSFORM_FIELD_SCHEMAS = [
|
|
668
|
+
{
|
|
669
|
+
defaultValue: undefined,
|
|
670
|
+
name: 'name',
|
|
671
|
+
required: false,
|
|
672
|
+
validate: (v: unknown) => typeof v === 'string' || v === null,
|
|
673
|
+
},
|
|
674
|
+
{ defaultValue: 0, name: 'x', required: false, validate: (v: unknown) => typeof v === 'number' },
|
|
675
|
+
{ defaultValue: 0, name: 'y', required: false, validate: (v: unknown) => typeof v === 'number' },
|
|
676
|
+
{ defaultValue: 1, name: 'scaleX', required: false, validate: (v: unknown) => typeof v === 'number' },
|
|
677
|
+
{ defaultValue: 1, name: 'scaleY', required: false, validate: (v: unknown) => typeof v === 'number' },
|
|
678
|
+
{ defaultValue: 0, name: 'rotation', required: false, validate: (v: unknown) => typeof v === 'number' },
|
|
679
|
+
{ defaultValue: 1, name: 'alpha', required: false, validate: (v: unknown) => typeof v === 'number' },
|
|
680
|
+
] as const;
|
|
681
|
+
|
|
577
682
|
describe('model-to-text explain parity', () => {
|
|
578
683
|
it.each<{
|
|
579
684
|
document: Readonly<FlightDocument>;
|
|
@@ -623,6 +728,22 @@ describe('model-to-text explain parity', () => {
|
|
|
623
728
|
});
|
|
624
729
|
});
|
|
625
730
|
|
|
731
|
+
function rootDocument2D(kind: string, fields: Record<string, unknown>): FlightDocument {
|
|
732
|
+
return {
|
|
733
|
+
defaultScene: 0,
|
|
734
|
+
resources: [],
|
|
735
|
+
scenes: [
|
|
736
|
+
{
|
|
737
|
+
backgroundColor: null,
|
|
738
|
+
kind: 'Scene2D',
|
|
739
|
+
layouts: [],
|
|
740
|
+
scene: { children: [], fields, kind },
|
|
741
|
+
tokens: [],
|
|
742
|
+
},
|
|
743
|
+
],
|
|
744
|
+
version: 1,
|
|
745
|
+
} as unknown as FlightDocument;
|
|
746
|
+
}
|
|
626
747
|
describe('Scene2D interactive-state materialization', () => {
|
|
627
748
|
it('returns inert bindings for the exact root and nested live nodes', () => {
|
|
628
749
|
const document = rootDocument2D(DisplayObjectKind, { alpha: 0.5 });
|
|
@@ -714,97 +835,6 @@ describe('Scene2D interactive-state materialization', () => {
|
|
|
714
835
|
});
|
|
715
836
|
});
|
|
716
837
|
|
|
717
|
-
function createTestDocument(
|
|
718
|
-
scene: FlightDocumentScene,
|
|
719
|
-
resources: FlightDocumentResourceDescriptor[] = [],
|
|
720
|
-
): FlightDocument {
|
|
721
|
-
return { defaultScene: 0, resources, scenes: [scene], version: 1 };
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
function singleTargetLayout(target: string) {
|
|
725
|
-
return {
|
|
726
|
-
targets: [target],
|
|
727
|
-
tree: { nodes: [{ containerStyle: null, itemStyle: null, kind: 'acme.Leaf', parentIndex: -1 }] },
|
|
728
|
-
};
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
function createTestSchemas(): FlightDocumentSchemaRegistry {
|
|
732
|
-
const displayObjectSchema: FlightDocumentNodeSchema = {
|
|
733
|
-
createNode: (fields: Readonly<FlightDocumentFields>, _resources: FlightDocumentResourceLookup) => {
|
|
734
|
-
const obj = createDisplayObject();
|
|
735
|
-
applyTransformFields(obj, fields);
|
|
736
|
-
return obj;
|
|
737
|
-
},
|
|
738
|
-
fields: TRANSFORM_FIELD_SCHEMAS,
|
|
739
|
-
kind: DisplayObjectKind,
|
|
740
|
-
writeNodeFields: (out: FlightDocumentFields, source: Readonly<NodeAny>) => {
|
|
741
|
-
writeTransformFields(out, source as Node2D);
|
|
742
|
-
return true;
|
|
743
|
-
},
|
|
744
|
-
};
|
|
745
|
-
|
|
746
|
-
const spriteSchema: FlightDocumentNodeSchema = {
|
|
747
|
-
createNode: (fields: Readonly<FlightDocumentFields>, _resources: FlightDocumentResourceLookup) => {
|
|
748
|
-
const sprite = createSprite();
|
|
749
|
-
applyTransformFields(sprite, fields);
|
|
750
|
-
return sprite;
|
|
751
|
-
},
|
|
752
|
-
fields: TRANSFORM_FIELD_SCHEMAS,
|
|
753
|
-
kind: SpriteKind,
|
|
754
|
-
writeNodeFields: (out: FlightDocumentFields, source: Readonly<NodeAny>) => {
|
|
755
|
-
writeTransformFields(out, source as Node2D);
|
|
756
|
-
return true;
|
|
757
|
-
},
|
|
758
|
-
};
|
|
759
|
-
|
|
760
|
-
let nodeSchemas = createKeyedTable<FlightDocumentNodeSchema>('flight-document.node', 'none');
|
|
761
|
-
nodeSchemas = withRegistryTableEntry(nodeSchemas, DisplayObjectKind, displayObjectSchema);
|
|
762
|
-
nodeSchemas = withRegistryTableEntry(nodeSchemas, SpriteKind, spriteSchema);
|
|
763
|
-
|
|
764
|
-
return {
|
|
765
|
-
interactiveStateExtensionSchemas: createKeyedTable('flight-document.interactive-state-extension', 'none'),
|
|
766
|
-
interactiveStateTransitionSchemas: createKeyedTable('flight-document.interactive-state-transition', 'none'),
|
|
767
|
-
nodeSchemas,
|
|
768
|
-
resourceSchemas: createKeyedTable('flight-document.resource', 'none'),
|
|
769
|
-
shapeCommandSchemas: createKeyedTable('flight-document.shape-command', 'none'),
|
|
770
|
-
};
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
function applyTransformFields(target: Node2D, fields: Readonly<FlightDocumentFields>): void {
|
|
774
|
-
if (typeof fields['name'] === 'string') target.name = fields['name'];
|
|
775
|
-
if (typeof fields['x'] === 'number') target.x = fields['x'];
|
|
776
|
-
if (typeof fields['y'] === 'number') target.y = fields['y'];
|
|
777
|
-
if (typeof fields['scaleX'] === 'number') target.scaleX = fields['scaleX'];
|
|
778
|
-
if (typeof fields['scaleY'] === 'number') target.scaleY = fields['scaleY'];
|
|
779
|
-
if (typeof fields['rotation'] === 'number') target.rotation = fields['rotation'];
|
|
780
|
-
if (typeof fields['alpha'] === 'number') target.alpha = fields['alpha'];
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
function writeTransformFields(out: FlightDocumentFields, source: Readonly<Node2D>): void {
|
|
784
|
-
if (source.name !== null) out['name'] = source.name;
|
|
785
|
-
if (source.x !== 0) out['x'] = source.x;
|
|
786
|
-
if (source.y !== 0) out['y'] = source.y;
|
|
787
|
-
if (source.scaleX !== 1) out['scaleX'] = source.scaleX;
|
|
788
|
-
if (source.scaleY !== 1) out['scaleY'] = source.scaleY;
|
|
789
|
-
if (source.rotation !== 0) out['rotation'] = source.rotation;
|
|
790
|
-
if (source.alpha !== 1) out['alpha'] = source.alpha;
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
const TRANSFORM_FIELD_SCHEMAS = [
|
|
794
|
-
{
|
|
795
|
-
defaultValue: undefined,
|
|
796
|
-
name: 'name',
|
|
797
|
-
required: false,
|
|
798
|
-
validate: (v: unknown) => typeof v === 'string' || v === null,
|
|
799
|
-
},
|
|
800
|
-
{ defaultValue: 0, name: 'x', required: false, validate: (v: unknown) => typeof v === 'number' },
|
|
801
|
-
{ defaultValue: 0, name: 'y', required: false, validate: (v: unknown) => typeof v === 'number' },
|
|
802
|
-
{ defaultValue: 1, name: 'scaleX', required: false, validate: (v: unknown) => typeof v === 'number' },
|
|
803
|
-
{ defaultValue: 1, name: 'scaleY', required: false, validate: (v: unknown) => typeof v === 'number' },
|
|
804
|
-
{ defaultValue: 0, name: 'rotation', required: false, validate: (v: unknown) => typeof v === 'number' },
|
|
805
|
-
{ defaultValue: 1, name: 'alpha', required: false, validate: (v: unknown) => typeof v === 'number' },
|
|
806
|
-
] as const;
|
|
807
|
-
|
|
808
838
|
// ★ ROOT-NODE FIDELITY. The writer captures the root's kind and fields (`writeNode(source.root, …)`), but
|
|
809
839
|
// the reader built a fresh container with `createScene2D()` and materialized only `scene.children` — so
|
|
810
840
|
// everything authored ON the root was silently dropped. Write preserved what read discarded, which makes
|
|
@@ -879,20 +909,3 @@ describe('Scene2D root fidelity', () => {
|
|
|
879
909
|
expect(resourceKeys).toEqual([]);
|
|
880
910
|
});
|
|
881
911
|
});
|
|
882
|
-
|
|
883
|
-
function rootDocument2D(kind: string, fields: Record<string, unknown>): FlightDocument {
|
|
884
|
-
return {
|
|
885
|
-
defaultScene: 0,
|
|
886
|
-
resources: [],
|
|
887
|
-
scenes: [
|
|
888
|
-
{
|
|
889
|
-
backgroundColor: null,
|
|
890
|
-
kind: 'Scene2D',
|
|
891
|
-
layouts: [],
|
|
892
|
-
scene: { children: [], fields, kind },
|
|
893
|
-
tokens: [],
|
|
894
|
-
},
|
|
895
|
-
],
|
|
896
|
-
version: 1,
|
|
897
|
-
} as unknown as FlightDocument;
|
|
898
|
-
}
|
|
@@ -43,6 +43,8 @@ import {
|
|
|
43
43
|
createFlightDocumentScene3DMaterializationFromText,
|
|
44
44
|
explainFlightDocumentScene3DRefusal,
|
|
45
45
|
explainFlightDocumentScene3DRefusalFromText,
|
|
46
|
+
initializeFlightDocumentFromScene3D,
|
|
47
|
+
initializeFlightDocumentScene3DMaterialization,
|
|
46
48
|
} from './sceneDocumentScene3DMaterialization';
|
|
47
49
|
|
|
48
50
|
describe('createFlightDocumentFromScene3D', () => {
|
|
@@ -548,6 +550,18 @@ describe('explainFlightDocumentScene3DRefusalFromText', () => {
|
|
|
548
550
|
});
|
|
549
551
|
});
|
|
550
552
|
|
|
553
|
+
describe('initializeFlightDocumentFromScene3D', () => {
|
|
554
|
+
it('is the construction initializer of createFlightDocumentFromScene3D', () => {
|
|
555
|
+
expect(typeof initializeFlightDocumentFromScene3D).toBe('function');
|
|
556
|
+
});
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
describe('initializeFlightDocumentScene3DMaterialization', () => {
|
|
560
|
+
it('is the construction initializer of createFlightDocumentScene3DMaterialization', () => {
|
|
561
|
+
expect(typeof initializeFlightDocumentScene3DMaterialization).toBe('function');
|
|
562
|
+
});
|
|
563
|
+
});
|
|
564
|
+
|
|
551
565
|
describe('model-to-text explain parity', () => {
|
|
552
566
|
// Keep the table annotated so every fixture is checked against the container schema rather than inferred
|
|
553
567
|
// only from its own literal.
|
|
@@ -763,68 +777,6 @@ describe('Scene3D layout materialization', () => {
|
|
|
763
777
|
});
|
|
764
778
|
});
|
|
765
779
|
|
|
766
|
-
// ★ ROOT-NODE FIDELITY, 3D half. Same defect as 2D: the reader built a fresh container and materialized
|
|
767
|
-
// only the authored root's children, so the root's own kind and fields were dropped while the writer
|
|
768
|
-
// captured them.
|
|
769
|
-
describe('Scene3D root fidelity', () => {
|
|
770
|
-
it('preserves the authored root kind', () => {
|
|
771
|
-
const schemas = createTestSchemas();
|
|
772
|
-
const document = rootDocument3D(Node3DKind, {}, schemas);
|
|
773
|
-
const materialization = createFlightDocumentScene3DMaterialization(document, schemas);
|
|
774
|
-
expect(materialization).not.toBeNull();
|
|
775
|
-
expect(materialization!.scene.root.kind).toBe(Node3DKind);
|
|
776
|
-
});
|
|
777
|
-
|
|
778
|
-
it('preserves fields authored on the root', () => {
|
|
779
|
-
const schemas = createTestSchemas();
|
|
780
|
-
const document = rootDocument3D(Node3DKind, { name: 'authored-root' }, schemas);
|
|
781
|
-
const materialization = createFlightDocumentScene3DMaterialization(document, schemas);
|
|
782
|
-
expect(materialization).not.toBeNull();
|
|
783
|
-
expect(materialization!.scene.root.name).toBe('authored-root');
|
|
784
|
-
});
|
|
785
|
-
|
|
786
|
-
it('refuses a registered root whose kind belongs to the other dimension', () => {
|
|
787
|
-
const schemas = createTestSchemas();
|
|
788
|
-
schemas.nodeSchemas = withRegistryTableEntry(schemas.nodeSchemas, DisplayObjectKind, {
|
|
789
|
-
createNode: () => createDisplayObject() as unknown as NodeAny,
|
|
790
|
-
fields: [],
|
|
791
|
-
kind: DisplayObjectKind,
|
|
792
|
-
writeNodeFields: () => true,
|
|
793
|
-
});
|
|
794
|
-
const document = rootDocument3D(DisplayObjectKind, {}, schemas);
|
|
795
|
-
expect(createFlightDocumentScene3DMaterialization(document, schemas)).toBeNull();
|
|
796
|
-
expect(explainFlightDocumentScene3DRefusal(document, schemas)).toMatchObject({
|
|
797
|
-
reason: FlightDocumentRefusalReason.RootKindMismatch,
|
|
798
|
-
});
|
|
799
|
-
});
|
|
800
|
-
|
|
801
|
-
it('passes a genuinely empty resource map to a root-dimension probe', () => {
|
|
802
|
-
const schemas = createTestSchemas();
|
|
803
|
-
let resourceKeys: string[] | null = null;
|
|
804
|
-
schemas.nodeSchemas = withRegistryTableEntry(schemas.nodeSchemas, DisplayObjectKind, {
|
|
805
|
-
createNode: (_fields, resources) => {
|
|
806
|
-
resourceKeys = Object.keys(resources);
|
|
807
|
-
return createDisplayObject() as unknown as NodeAny;
|
|
808
|
-
},
|
|
809
|
-
fields: [],
|
|
810
|
-
kind: DisplayObjectKind,
|
|
811
|
-
writeNodeFields: () => true,
|
|
812
|
-
});
|
|
813
|
-
|
|
814
|
-
explainFlightDocumentScene3DRefusal(rootDocument3D(DisplayObjectKind, {}, schemas), schemas);
|
|
815
|
-
|
|
816
|
-
expect(resourceKeys).toEqual([]);
|
|
817
|
-
});
|
|
818
|
-
});
|
|
819
|
-
|
|
820
|
-
describe('Scene3DDocumentCamera', () => {
|
|
821
|
-
it('has no direction field', () => {
|
|
822
|
-
expectTypeOf<keyof Scene3DDocumentCamera>().toEqualTypeOf<
|
|
823
|
-
'far' | 'name' | 'near' | 'node' | 'projection' | 'transform'
|
|
824
|
-
>();
|
|
825
|
-
});
|
|
826
|
-
});
|
|
827
|
-
|
|
828
780
|
function createTestDocument(
|
|
829
781
|
scene: FlightDocumentScene,
|
|
830
782
|
resources: FlightDocumentResourceDescriptor[] = [],
|
|
@@ -876,9 +828,57 @@ function createTestSchemas(): FlightDocumentSchemaRegistry {
|
|
|
876
828
|
};
|
|
877
829
|
}
|
|
878
830
|
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
831
|
+
// ★ ROOT-NODE FIDELITY, 3D half. Same defect as 2D: the reader built a fresh container and materialized
|
|
832
|
+
// only the authored root's children, so the root's own kind and fields were dropped while the writer
|
|
833
|
+
// captured them.
|
|
834
|
+
describe('Scene3D root fidelity', () => {
|
|
835
|
+
it('preserves the authored root kind', () => {
|
|
836
|
+
const schemas = createTestSchemas();
|
|
837
|
+
const document = rootDocument3D(Node3DKind, {}, schemas);
|
|
838
|
+
const materialization = createFlightDocumentScene3DMaterialization(document, schemas);
|
|
839
|
+
expect(materialization).not.toBeNull();
|
|
840
|
+
expect(materialization!.scene.root.kind).toBe(Node3DKind);
|
|
841
|
+
});
|
|
842
|
+
|
|
843
|
+
it('preserves fields authored on the root', () => {
|
|
844
|
+
const schemas = createTestSchemas();
|
|
845
|
+
const document = rootDocument3D(Node3DKind, { name: 'authored-root' }, schemas);
|
|
846
|
+
const materialization = createFlightDocumentScene3DMaterialization(document, schemas);
|
|
847
|
+
expect(materialization).not.toBeNull();
|
|
848
|
+
expect(materialization!.scene.root.name).toBe('authored-root');
|
|
849
|
+
});
|
|
850
|
+
|
|
851
|
+
it('refuses a registered root whose kind belongs to the other dimension', () => {
|
|
852
|
+
const schemas = createTestSchemas();
|
|
853
|
+
schemas.nodeSchemas = withRegistryTableEntry(schemas.nodeSchemas, DisplayObjectKind, {
|
|
854
|
+
createNode: () => createDisplayObject() as unknown as NodeAny,
|
|
855
|
+
fields: [],
|
|
856
|
+
kind: DisplayObjectKind,
|
|
857
|
+
writeNodeFields: () => true,
|
|
858
|
+
});
|
|
859
|
+
const document = rootDocument3D(DisplayObjectKind, {}, schemas);
|
|
860
|
+
expect(createFlightDocumentScene3DMaterialization(document, schemas)).toBeNull();
|
|
861
|
+
expect(explainFlightDocumentScene3DRefusal(document, schemas)).toMatchObject({
|
|
862
|
+
reason: FlightDocumentRefusalReason.RootKindMismatch,
|
|
863
|
+
});
|
|
864
|
+
});
|
|
865
|
+
|
|
866
|
+
it('passes a genuinely empty resource map to a root-dimension probe', () => {
|
|
867
|
+
const schemas = createTestSchemas();
|
|
868
|
+
let resourceKeys: string[] | null = null;
|
|
869
|
+
schemas.nodeSchemas = withRegistryTableEntry(schemas.nodeSchemas, DisplayObjectKind, {
|
|
870
|
+
createNode: (_fields, resources) => {
|
|
871
|
+
resourceKeys = Object.keys(resources);
|
|
872
|
+
return createDisplayObject() as unknown as NodeAny;
|
|
873
|
+
},
|
|
874
|
+
fields: [],
|
|
875
|
+
kind: DisplayObjectKind,
|
|
876
|
+
writeNodeFields: () => true,
|
|
877
|
+
});
|
|
878
|
+
|
|
879
|
+
explainFlightDocumentScene3DRefusal(rootDocument3D(DisplayObjectKind, {}, schemas), schemas);
|
|
880
|
+
|
|
881
|
+
expect(resourceKeys).toEqual([]);
|
|
882
882
|
});
|
|
883
883
|
});
|
|
884
884
|
|
|
@@ -933,3 +933,16 @@ function getScene3DLights(source: Readonly<Scene3DLightsLike>): Readonly<Light>[
|
|
|
933
933
|
}
|
|
934
934
|
return lights;
|
|
935
935
|
}
|
|
936
|
+
describe('Scene3DDocumentCamera', () => {
|
|
937
|
+
it('has no direction field', () => {
|
|
938
|
+
expectTypeOf<keyof Scene3DDocumentCamera>().toEqualTypeOf<
|
|
939
|
+
'far' | 'name' | 'near' | 'node' | 'projection' | 'transform'
|
|
940
|
+
>();
|
|
941
|
+
});
|
|
942
|
+
});
|
|
943
|
+
|
|
944
|
+
describe('Scene3DDocumentLight', () => {
|
|
945
|
+
it('has no direction field', () => {
|
|
946
|
+
expectTypeOf<keyof Scene3DDocumentLight>().toEqualTypeOf<'descriptor' | 'name' | 'node' | 'transform'>();
|
|
947
|
+
});
|
|
948
|
+
});
|