Skip to content

Commit edce756

Browse files
author
DavidQ
committed
Fix Asteroids collisions and load Object Vector Studio defaults from schema - PR_26133_033-asteroids-collision-and-object-vector-schema-defaults
1 parent d4cae11 commit edce756

11 files changed

Lines changed: 469 additions & 81 deletions
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# PR_26133_033 Asteroids Collision And Object Vector Defaults Report
2+
3+
Date: 2026-05-14
4+
5+
## Scope
6+
7+
This change restores Asteroids collision behavior and moves Object Vector Studio V2 object/shape creation defaults into schema definitions while keeping object ids as the runtime SSoT.
8+
9+
## Collision Fixes
10+
11+
- Updated Asteroids asteroid collision-profile extraction to read point geometry from shape `tool: "polygon"`, matching the reduced Object Vector schema contract.
12+
- Confirmed Asteroids small, medium, and large asteroid profiles load polygon collision points from `games/Asteroids/game.manifest.json -> game.workspace.tools["object-vector-studio-v2"].objects[*].shapes[*].geometry`.
13+
- Added ship bullet vs UFO bullet crossfire collision resolution.
14+
- Preserved existing ship/asteroid, bullet/asteroid, UFO/asteroid, UFO bullet/asteroid, and ship/UFO crash collision flows.
15+
- No vector-map-editor fallback geometry was added or restored.
16+
17+
## Schema Defaults
18+
19+
- Added defaults to `tools/schemas/game.manifest.schema.json` for Object Vector Studio V2 object, shape common fields, style, transform, point2d, and all supported geometry definitions.
20+
- Mirrored the same defaults in `tools/schemas/tools/object-vector-studio-v2.schema.json` for standalone Object Vector Studio V2 validation/loading.
21+
- Added whole-object defaults for polygon and triangle geometry; polygon defaults use five points, and triangle defaults use exactly three points.
22+
23+
## Tool Default Loading
24+
25+
- Added `ObjectVectorStudioV2SchemaService.getDefinitionDefault()` so Object Vector Studio V2 clones defaults from the loaded schema.
26+
- New object creation now starts from the schema object default and applies the user-entered id/name/tags.
27+
- New shape creation now reads shape common, style, transform, and geometry defaults from schema definitions.
28+
- Missing schema defaults now produce visible blocked create/add failures instead of silent hardcoded fallback creation.
29+
- Shape transform origin remains derived from the created geometry bounds so current editing behavior stays centered; the transform base values come from the schema default.
30+
31+
## Workspace Launch
32+
33+
- Workspace Manager V2 generated Asteroids Object Vector payloads were verified with no `assetLibrary` field.
34+
- Generated `objects[*].tags` were verified present, including `object.asteroids.asteroid.small` tags `["asteroid", "small"]` loaded from the Asteroids manifest.
35+
36+
## Validation
37+
38+
- PASS - `npm run test:workspace-v2` -> 49 passed.
39+
- PASS - targeted Asteroids collision timing/stress checks for collision profiles and requested collision pairs.
40+
- PASS - targeted Asteroids validation smoke.
41+
- PASS - Node schema validation for `games/Asteroids/game.manifest.json` and generated workspace manifest.
42+
- PASS - search check found no Asteroids vector-map fallback geometry or `assetLibrary` payload usage outside schema rejection guards.

docs/dev/reports/playwright_v8_coverage_report.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# PR_26133_032 Playwright V8 Coverage Report
1+
# PR_26133_033 Playwright V8 Coverage Report
22

3-
Task: PR_26133_032-object-vector-schema-geometry-and-style-ssot
3+
Task: PR_26133_033-asteroids-collision-and-object-vector-schema-defaults
44
Date: 2026-05-14
55

66
## Result
@@ -27,8 +27,8 @@ PASS - Coverage reporting was generated during `npm run test:workspace-v2`.
2727

2828
```text
2929
(83%) tools/object-vector-studio-v2/js/bootstrap.js - executed lines 109/109; executed functions 5/6
30-
(93%) tools/object-vector-studio-v2/js/ToolStarterApp.js - executed lines 4345/4345; executed functions 451/483
31-
(95%) tools/object-vector-studio-v2/js/services/ObjectVectorStudioV2SchemaService.js - executed lines 417/417; executed functions 53/56
30+
(93%) tools/object-vector-studio-v2/js/ToolStarterApp.js - executed lines 4333/4333; executed functions 453/485
31+
(95%) tools/object-vector-studio-v2/js/services/ObjectVectorStudioV2SchemaService.js - executed lines 453/453; executed functions 55/58
3232
(98%) src/engine/rendering/ObjectVectorRuntimeAssetService.js - executed lines 915/915; executed functions 107/109
3333
```
3434

@@ -40,4 +40,4 @@ PASS - Coverage reporting was generated during `npm run test:workspace-v2`.
4040

4141
## PR-Specific Note
4242

43-
The Workspace V2 run exercised the Object Vector Studio V2 editor, schema service, runtime object-vector asset service, Asteroids runtime object-vector loading, and browser UI paths for fill/stroke opacity plus point2d geometry. Coverage remains advisory only.
43+
The Workspace V2 run exercised Object Vector Studio V2 launch, schema loading, schema-driven shape creation, generated Asteroids object-vector payload validation, and Asteroids runtime object-vector loading. Coverage remains advisory only.
Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# PR_26133_032 Workspace V2 Playwright Results
1+
# PR_26133_033 Workspace V2 Playwright Results
22

3-
Task: PR_26133_032-object-vector-schema-geometry-and-style-ssot
3+
Task: PR_26133_033-asteroids-collision-and-object-vector-schema-defaults
44
Date: 2026-05-14
55

66
## Result
@@ -10,21 +10,20 @@ PASS - `npm run test:workspace-v2` completed successfully.
1010
- Command: `npm run test:workspace-v2`
1111
- Playwright target: `tests/playwright/tools/WorkspaceManagerV2.spec.mjs --project=playwright --workers=1 --reporter=list`
1212
- Final result: 49 passed, 0 failed.
13-
- Focused rerun before the full suite: 1 passed for the Object Vector Studio V2 schema-only palette gate after opacity-control test updates.
13+
- Runtime/console guard: Workspace V2 tests that monitor page errors completed with no reported page errors.
1414

1515
## PR-Specific Coverage
1616

17-
- Fill and stroke opacity controls apply to selected Object Vector shapes and persist as `fillOpacity` / `strokeOpacity`.
18-
- Object Vector Studio V2 loads Asteroids object tags from `objects[*].tags` with no `assetLibrary` payload.
19-
- Polygon editing enforces the new minimum of 4 points; default created polygons use 5 points.
20-
- Triangle shapes use fixed 3-point triangle geometry and keep Add/Delete Point hidden.
21-
- Line geometry loads/edits through `point1` / `point2`.
22-
- Transform origin loads/edits through `origin: { x, y }`.
23-
- Runtime object-vector rendering uses object ids as SSoT and validates the reduced Object Vector payload.
24-
- Runtime console checks: covered Workspace V2 flows asserted no page errors or console errors where the suite monitors them.
17+
- Object Vector Studio V2 schema defaults are present in the game manifest schema and the standalone tool schema.
18+
- New rectangle creation was verified against schema-cloned geometry/style/transform defaults.
19+
- Workspace Manager V2 generated the Asteroids Object Vector payload without `assetLibrary` and with `objects[*].tags` present.
20+
- Launching Object Vector Studio V2 for Asteroids from Workspace Manager V2 loaded 6 objects and validated the payload.
21+
- Dirty-state and save validation still pass after the generated manifest cleanup.
2522

2623
## Additional Validation
2724

28-
PASS - Custom manifest/schema validation loaded `games/Asteroids/game.manifest.json`, validated the embedded Object Vector Studio V2 payload, and loaded it through `ObjectVectorRuntimeAssetService`.
25+
PASS - Targeted Asteroids collision checks covered ship/asteroid, bullet/asteroid, UFO/asteroid, UFO bullet/asteroid, ship bullet/UFO bullet crossfire, and ship/UFO crash cases.
2926

30-
PASS - `node --check` for changed Object Vector JS and the Workspace Manager V2 Playwright spec.
27+
PASS - Targeted Asteroids validation smoke completed.
28+
29+
PASS - Node schema validation reported `games/Asteroids/game.manifest.json` and the generated workspace manifest as schema-valid.

games/Asteroids/game/AsteroidsWorld.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,32 @@ export default class AsteroidsWorld {
603603
this.status = 'Ship destroyed.';
604604
}
605605

606+
resolveBulletCrossfire(events) {
607+
for (let bulletIndex = this.bullets.length - 1; bulletIndex >= 0; bulletIndex -= 1) {
608+
const bullet = this.bullets[bulletIndex];
609+
const bulletPolygon = bullet.getCollisionPolygon();
610+
611+
for (let ufoBulletIndex = this.ufoBullets.length - 1; ufoBulletIndex >= 0; ufoBulletIndex -= 1) {
612+
const ufoBullet = this.ufoBullets[ufoBulletIndex];
613+
if (!arePolygonsColliding(bulletPolygon, ufoBullet.getCollisionPolygon())) {
614+
continue;
615+
}
616+
617+
this.bullets.splice(bulletIndex, 1);
618+
this.ufoBullets.splice(ufoBulletIndex, 1);
619+
events.explosions.push({
620+
x: (bullet.x + ufoBullet.x) / 2,
621+
y: (bullet.y + ufoBullet.y) / 2,
622+
size: 1,
623+
source: 'bullet-crossfire',
624+
});
625+
events.sfx.push('bangSmall');
626+
this.status = 'Opposing shots collided.';
627+
break;
628+
}
629+
}
630+
}
631+
606632
updateStep(dtSeconds, input) {
607633
const events = createWorldEvents();
608634

@@ -663,6 +689,7 @@ export default class AsteroidsWorld {
663689

664690
this.ufoBullets.forEach((bullet) => bullet.update(safeDtSeconds, this.bounds));
665691
this.ufoBullets = this.ufoBullets.filter((bullet) => bullet.isAlive());
692+
this.resolveBulletCrossfire(events);
666693

667694
if (this.ufo) {
668695
const ufoPolygon = this.ufo.getCollisionPolygon();

games/Asteroids/game/asteroidObjectGeometry.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ function sortedShapes(object) {
6060
function extractPrimaryPolygonPoints(object) {
6161
const shape = sortedShapes(object).find((candidate) => (
6262
candidate?.visible !== false
63-
&& candidate?.type === 'polygon'
63+
&& candidate?.tool === 'polygon'
6464
&& asArray(candidate?.geometry?.points).length >= 3
6565
));
6666
return asArray(shape?.geometry?.points).map(cleanPoint);

tests/games/AsteroidsCollisionTimingStress.test.mjs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ function assertClose(actual, expected, message) {
6161

6262
export function run() {
6363
const asteroidGeometryProfiles = createAsteroidsTestGeometryProfiles();
64+
Object.entries(asteroidGeometryProfiles).forEach(([size, profile]) => {
65+
assert.equal(profile.points.length >= 4, true, `Asteroid size ${size} should load polygon collision points from object-vector-studio-v2 tool geometry.`);
66+
});
67+
6468
const collisionWorld = new AsteroidsWorld({ width: 960, height: 720 }, { rng: () => 0.5, asteroidGeometryProfiles });
6569
collisionWorld.ufoSpawnTimer = Number.POSITIVE_INFINITY;
6670
collisionWorld.asteroids = [createStationaryAsteroid(collisionWorld, { x: 480, y: 400, size: 3 })];
@@ -75,6 +79,89 @@ export function run() {
7579
assert.equal(collisionWorld.bullets.length, 0);
7680
assert.equal(collisionWorld.asteroids.length, 2);
7781

82+
const shipImpactWorld = new AsteroidsWorld({ width: 960, height: 720 }, { rng: () => 0.5, asteroidGeometryProfiles });
83+
shipImpactWorld.ufoSpawnTimer = Number.POSITIVE_INFINITY;
84+
shipImpactWorld.ship.invulnerable = 0;
85+
shipImpactWorld.asteroids = [createStationaryAsteroid(shipImpactWorld, {
86+
x: shipImpactWorld.ship.x,
87+
y: shipImpactWorld.ship.y,
88+
size: 3,
89+
})];
90+
const shipImpactEvents = shipImpactWorld.update(0, createInput());
91+
assert.equal(shipImpactEvents.shipDestroyed, true);
92+
assert.equal(shipImpactWorld.shipActive, false);
93+
94+
const ufoImpactWorld = new AsteroidsWorld({ width: 960, height: 720 }, { rng: () => 0.5, asteroidGeometryProfiles });
95+
ufoImpactWorld.ufoSpawnTimer = Number.POSITIVE_INFINITY;
96+
ufoImpactWorld.asteroids = [createStationaryAsteroid(ufoImpactWorld, { x: 480, y: 360, size: 3 })];
97+
ufoImpactWorld.ufo = ufoImpactWorld.createUfoEntity('large', 1);
98+
ufoImpactWorld.ufo.x = 480;
99+
ufoImpactWorld.ufo.y = 360;
100+
ufoImpactWorld.ufo.vx = 0;
101+
ufoImpactWorld.ufo.vy = 0;
102+
ufoImpactWorld.ufo.turnTimer = Number.POSITIVE_INFINITY;
103+
ufoImpactWorld.ufo.fireTimer = Number.POSITIVE_INFINITY;
104+
const ufoImpactEvents = ufoImpactWorld.update(0, createInput());
105+
assert.equal(ufoImpactWorld.ufo, null);
106+
assert.equal(ufoImpactEvents.explosions.some((explosion) => explosion.source === 'ufo'), true);
107+
108+
const ufoBulletImpactWorld = new AsteroidsWorld({ width: 960, height: 720 }, { rng: () => 0.5, asteroidGeometryProfiles });
109+
ufoBulletImpactWorld.ufoSpawnTimer = Number.POSITIVE_INFINITY;
110+
ufoBulletImpactWorld.asteroids = [createStationaryAsteroid(ufoBulletImpactWorld, { x: 480, y: 360, size: 3 })];
111+
ufoBulletImpactWorld.ufo = ufoBulletImpactWorld.createUfoEntity('large', 1);
112+
ufoBulletImpactWorld.ufo.x = 80;
113+
ufoBulletImpactWorld.ufo.y = 80;
114+
ufoBulletImpactWorld.ufo.vx = 0;
115+
ufoBulletImpactWorld.ufo.vy = 0;
116+
ufoBulletImpactWorld.ufo.turnTimer = Number.POSITIVE_INFINITY;
117+
ufoBulletImpactWorld.ufo.fireTimer = Number.POSITIVE_INFINITY;
118+
ufoBulletImpactWorld.ufoBullets = [ufoBulletImpactWorld.createBulletFromState(createBulletState({
119+
x: 480,
120+
y: 360,
121+
vx: 0,
122+
vy: 0,
123+
}))];
124+
const ufoBulletImpactEvents = ufoBulletImpactWorld.update(0, createInput());
125+
assert.equal(ufoBulletImpactWorld.ufoBullets.length, 0);
126+
assert.equal(ufoBulletImpactWorld.asteroids.length, 2);
127+
assert.equal(ufoBulletImpactEvents.explosions.length > 0, true);
128+
129+
const bulletCrossfireWorld = new AsteroidsWorld({ width: 960, height: 720 }, { rng: () => 0.5, asteroidGeometryProfiles });
130+
bulletCrossfireWorld.ufoSpawnTimer = Number.POSITIVE_INFINITY;
131+
bulletCrossfireWorld.asteroids = [];
132+
bulletCrossfireWorld.ufo = null;
133+
bulletCrossfireWorld.bullets = [bulletCrossfireWorld.createBulletFromState(createBulletState({
134+
x: 480,
135+
y: 360,
136+
vx: 0,
137+
vy: 0,
138+
}))];
139+
bulletCrossfireWorld.ufoBullets = [bulletCrossfireWorld.createBulletFromState(createBulletState({
140+
x: 480,
141+
y: 360,
142+
vx: 0,
143+
vy: 0,
144+
}))];
145+
const bulletCrossfireEvents = bulletCrossfireWorld.update(0, createInput());
146+
assert.equal(bulletCrossfireWorld.bullets.length, 0);
147+
assert.equal(bulletCrossfireWorld.ufoBullets.length, 0);
148+
assert.equal(bulletCrossfireEvents.explosions.some((explosion) => explosion.source === 'bullet-crossfire'), true);
149+
150+
const shipUfoCrashWorld = new AsteroidsWorld({ width: 960, height: 720 }, { rng: () => 0.5, asteroidGeometryProfiles });
151+
shipUfoCrashWorld.ufoSpawnTimer = Number.POSITIVE_INFINITY;
152+
shipUfoCrashWorld.asteroids = [];
153+
shipUfoCrashWorld.ship.invulnerable = 0;
154+
shipUfoCrashWorld.ufo = shipUfoCrashWorld.createUfoEntity('large', 1);
155+
shipUfoCrashWorld.ufo.x = shipUfoCrashWorld.ship.x;
156+
shipUfoCrashWorld.ufo.y = shipUfoCrashWorld.ship.y;
157+
shipUfoCrashWorld.ufo.vx = 0;
158+
shipUfoCrashWorld.ufo.vy = 0;
159+
shipUfoCrashWorld.ufo.turnTimer = Number.POSITIVE_INFINITY;
160+
shipUfoCrashWorld.ufo.fireTimer = Number.POSITIVE_INFINITY;
161+
const shipUfoCrashEvents = shipUfoCrashWorld.update(0, createInput());
162+
assert.equal(shipUfoCrashEvents.shipDestroyed, true);
163+
assert.equal(shipUfoCrashWorld.ufo, null);
164+
78165
const waveWorld = new AsteroidsWorld({ width: 960, height: 720 }, { rng: () => 0.25, asteroidGeometryProfiles });
79166
waveWorld.ufoSpawnTimer = Number.POSITIVE_INFINITY;
80167
waveWorld.asteroids = [createStationaryAsteroid(waveWorld, { x: 480, y: 400, size: 1 })];

tests/playwright/tools/WorkspaceManagerV2.spec.mjs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,6 +1211,30 @@ test.describe("Workspace Manager V2 bootstrap", () => {
12111211
await expect(page.locator("body.tools-platform-tool-page[data-tool-id='object-vector-studio-v2']")).toBeVisible();
12121212
await expect(page.locator("[data-tool-starter-header]")).toContainText("Object Vector Studio V2");
12131213
await expect(page.locator("#statusLog")).toHaveValue(/OK Object Vector Studio V2 schema contract loaded from \/tools\/schemas\/tools\/object-vector-studio-v2\.schema\.json\./);
1214+
const objectVectorSchemaDefaults = await page.evaluate(async () => {
1215+
const toolSchema = window.__objectVectorStudioV2App.schemaService.schema;
1216+
const gameSchema = await fetch("/tools/schemas/game.manifest.schema.json", { cache: "no-store" }).then((response) => response.json());
1217+
return {
1218+
gameObjectDefaultTags: gameSchema.$defs.objectVectorStudioObject.default.tags,
1219+
gamePolygonDefaultPointCount: gameSchema.$defs.objectVectorStudioPolygonGeometry.default.points.length,
1220+
gameShapeCommonDefaultTool: gameSchema.$defs.objectVectorStudioShapeCommon.default.tool,
1221+
gameTransformDefaultOrigin: gameSchema.$defs.objectVectorStudioTransform.default.origin,
1222+
toolPolygonDefaultPointCount: toolSchema.$defs.polygonGeometry.default.points.length,
1223+
toolShapeCommonDefaultTool: toolSchema.$defs.shapeCommon.default.tool,
1224+
toolStyleDefaultStrokeWidth: toolSchema.$defs.style.default.strokeWidth,
1225+
toolTransformDefaultOrigin: toolSchema.$defs.transform.default.origin
1226+
};
1227+
});
1228+
expect(objectVectorSchemaDefaults).toEqual({
1229+
gameObjectDefaultTags: [],
1230+
gamePolygonDefaultPointCount: 5,
1231+
gameShapeCommonDefaultTool: "polygon",
1232+
gameTransformDefaultOrigin: { x: 0, y: 0 },
1233+
toolPolygonDefaultPointCount: 5,
1234+
toolShapeCommonDefaultTool: "polygon",
1235+
toolStyleDefaultStrokeWidth: 3,
1236+
toolTransformDefaultOrigin: { x: 0, y: 0 }
1237+
});
12141238
await expect(page.locator('[data-launch-mode-nav="tool"]')).toBeVisible();
12151239
await expect(page.locator('[data-launch-mode-nav="tool"] button')).toHaveText(["Import", "Copy JSON", "Export", "Export SVG"]);
12161240
await expect(page.locator('[data-launch-mode-nav="workspace"]')).toBeHidden();
@@ -1869,6 +1893,44 @@ test.describe("Workspace Manager V2 bootstrap", () => {
18691893
await expect(page.locator("#objectVectorStudioV2DeleteShapeButton")).toHaveCount(0);
18701894
await expect(page.locator("#statusLog")).toHaveValue(/OK Created rectangle shape on Asteroids Ship\./);
18711895
await expect(page.locator("#statusLog")).toHaveValue(/OK Render mode svg-work-surface: rendered Asteroids Ship with 1 visible shapes; capture mode none\./);
1896+
const createdRectangleSchemaDefaults = await page.evaluate(() => {
1897+
const app = window.__objectVectorStudioV2App;
1898+
const schema = app.schemaService.schema;
1899+
const shape = app.selectedShape();
1900+
return {
1901+
geometry: shape.geometry,
1902+
locked: shape.locked,
1903+
schemaGeometry: schema.$defs.rectangleGeometry.default,
1904+
schemaShapeCommon: schema.$defs.shapeCommon.default,
1905+
schemaStyle: schema.$defs.style.default,
1906+
schemaTransform: schema.$defs.transform.default,
1907+
style: shape.style,
1908+
tool: shape.tool,
1909+
transform: shape.transform,
1910+
visible: shape.visible
1911+
};
1912+
});
1913+
expect(createdRectangleSchemaDefaults).toMatchObject({
1914+
geometry: createdRectangleSchemaDefaults.schemaGeometry,
1915+
locked: createdRectangleSchemaDefaults.schemaShapeCommon.locked,
1916+
style: {
1917+
fill: "#ffffff",
1918+
fillOpacity: createdRectangleSchemaDefaults.schemaStyle.fillOpacity,
1919+
stroke: "#ffffff",
1920+
strokeOpacity: createdRectangleSchemaDefaults.schemaStyle.strokeOpacity,
1921+
strokeWidth: createdRectangleSchemaDefaults.schemaStyle.strokeWidth
1922+
},
1923+
tool: "rectangle",
1924+
transform: {
1925+
origin: { x: -40, y: 0 },
1926+
rotation: createdRectangleSchemaDefaults.schemaTransform.rotation,
1927+
scaleX: createdRectangleSchemaDefaults.schemaTransform.scaleX,
1928+
scaleY: createdRectangleSchemaDefaults.schemaTransform.scaleY,
1929+
x: createdRectangleSchemaDefaults.schemaTransform.x,
1930+
y: createdRectangleSchemaDefaults.schemaTransform.y
1931+
},
1932+
visible: createdRectangleSchemaDefaults.schemaShapeCommon.visible
1933+
});
18721934

18731935
await page.locator('[data-shape-tool="circle"]').click();
18741936
await expect(page.locator("#objectVectorStudioV2ObjectsCount")).toHaveText("(18 obj, 2 shapes)");
@@ -7278,6 +7340,10 @@ test.describe("Workspace Manager V2 bootstrap", () => {
72787340
await page.locator("#activeGameSelect").selectOption("Asteroids");
72797341
await expectWorkspaceReturnRehydrated(page);
72807342
await expect(page.locator("#saveWorkspaceButton")).toBeDisabled();
7343+
const generatedObjectVectorPayload = JSON.parse(await page.locator("#workspaceContextOutput").inputValue()).tools["object-vector-studio-v2"];
7344+
expect(generatedObjectVectorPayload.assetLibrary).toBeUndefined();
7345+
expect(generatedObjectVectorPayload.objects.every((object) => Array.isArray(object.tags))).toBe(true);
7346+
expect(generatedObjectVectorPayload.objects.find((object) => object.id === "object.asteroids.asteroid.small").tags).toEqual(["asteroid", "small"]);
72817347

72827348
await page.locator('[data-workspace-tool-id="object-vector-studio-v2"]').click();
72837349
await expect(page).toHaveURL(/object-vector-studio-v2\/index\.html.*launch=workspace/);

0 commit comments

Comments
 (0)