113 lines
5.8 KiB
JavaScript
113 lines
5.8 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { readFile } from "node:fs/promises";
|
|
import { test } from "node:test";
|
|
|
|
const sourceRoot = new URL("../src/", import.meta.url);
|
|
|
|
async function read(relativePath) {
|
|
return readFile(new URL(relativePath, sourceRoot), "utf8");
|
|
}
|
|
|
|
test("simulation is a dedicated Polygon workspace with a bounded feature slice", async () => {
|
|
const [productModel, workspaceHub, workspace, styles] = await Promise.all([
|
|
read("productModel.ts"),
|
|
read("workspaces/Workspaces.tsx"),
|
|
read("workspaces/simulation/SimulationWorkspace.tsx"),
|
|
read("styles.css"),
|
|
]);
|
|
|
|
assert.match(productModel, /id: "simulations"[\s\S]*root: "polygon"[\s\S]*kind: "simulations"/);
|
|
assert.match(workspaceHub, /case "simulations":[\s\S]*<SimulationWorkspace \/>/);
|
|
assert.match(workspace, /simulation-catalog__table/);
|
|
assert.match(workspace, /<SimulationViewport[\s\S]*project=\{selected\}/);
|
|
assert.match(workspace, /<ConfirmationModal/);
|
|
assert.match(styles, /styles\/simulation\.css/);
|
|
});
|
|
|
|
test("browser upload remains same-origin, resumable and token-free", async () => {
|
|
const [core, window] = await Promise.all([
|
|
read("core/simulation/projects.ts"),
|
|
read("components/simulation/SimulationProjectWindow.tsx"),
|
|
]);
|
|
|
|
assert.match(core, /const API_ROOT = "\/api\/v1\/simulation-worlds\/projects"/);
|
|
assert.match(core, /method: "HEAD"/);
|
|
assert.match(core, /method: "PATCH"/);
|
|
assert.match(core, /"Upload-Offset"/);
|
|
assert.doesNotMatch(core, /Authorization|Bearer|18090|Worker 006/);
|
|
assert.match(window, /accept="\.zip,\.rar,\.7z"/);
|
|
assert.match(window, /webkitdirectory/);
|
|
assert.match(window, /webkitGetAsEntry/);
|
|
assert.match(window, /ровно одна сцена \.lcc или \.lcc2/);
|
|
assert.doesNotMatch(window, /Загружаем источник/);
|
|
});
|
|
|
|
test("failed simulation can restart from its retained Mission Core source", async () => {
|
|
const [core, workspace] = await Promise.all([
|
|
read("core/simulation/projects.ts"),
|
|
read("workspaces/simulation/SimulationWorkspace.tsx"),
|
|
]);
|
|
|
|
assert.match(core, /retrySimulationProject/);
|
|
assert.match(core, /\$\{API_ROOT\}\/\$\{encodeURIComponent\(projectId\)\}\/build/);
|
|
assert.match(workspace, /Повторить сборку/);
|
|
});
|
|
|
|
test("PlayCanvas owns the realtime scene graph without an iframe or React entity tree", async () => {
|
|
const [runtime, viewport, packageDocument] = await Promise.all([
|
|
read("components/simulation/PlayCanvasRuntime.ts"),
|
|
read("components/simulation/SimulationViewport.tsx"),
|
|
readFile(new URL("../package.json", import.meta.url), "utf8"),
|
|
]);
|
|
|
|
assert.match(packageDocument, /"playcanvas": "2\.21\.4"/);
|
|
assert.doesNotMatch(packageDocument, /@playcanvas\/react/);
|
|
assert.match(runtime, /new Application\(canvas/);
|
|
assert.match(runtime, /setCanvasFillMode\(FILLMODE_NONE/);
|
|
assert.match(runtime, /setCanvasResolution\(RESOLUTION_AUTO\)/);
|
|
assert.match(runtime, /new Asset\([^,]+, "gsplat"/);
|
|
assert.match(runtime, /camera\.script\?\.create\(CameraControls/);
|
|
assert.match(runtime, /const HOME_POSITION = new Vec3\(0, 1, 0\)/);
|
|
assert.match(runtime, /const HOME_FOCUS = new Vec3\(1, 1, 0\)/);
|
|
assert.match(runtime, /maximum: \{[^}]*lodRangeMin: 0, lodRangeMax: 5, pixelRatio: 2, splatBudget: 4_000_000, targetFps: 60/);
|
|
assert.match(runtime, /app\.scene\.gsplat\.splatBudget = profile\.splatBudget/);
|
|
assert.match(runtime, /app\.autoRender = false/);
|
|
assert.match(runtime, /WEBGL_lose_context/);
|
|
assert.match(runtime, /selected\.horizontal[^\n]+frame\.mouse\[0\] \*= -1/);
|
|
assert.match(runtime, /selected\.vertical[^\n]+frame\.mouse\[1\] \*= -1/);
|
|
assert.match(runtime, /setCameraInversion/);
|
|
assert.match(runtime, /async setViewMode\([\s\S]*this\.resetCameraInteraction\(\);[\s\S]*this\.viewMode = mode/);
|
|
assert.match(runtime, /input\._pointerId = -1/);
|
|
assert.match(runtime, /state\.mouse\.fill\(0\)/);
|
|
assert.match(runtime, /new Asset\([\s\S]*"container"/);
|
|
assert.match(runtime, /instantiateRenderEntity/);
|
|
assert.match(runtime, /applyWorldTransform/);
|
|
assert.match(runtime, /setLayerWorldTransform/);
|
|
assert.match(runtime, /PLAYCANVAS_X_180_TRANSFORM/);
|
|
assert.match(runtime, /PLAYCANVAS_Y_180_TRANSFORM/);
|
|
assert.match(runtime, /PLAYCANVAS_Z_180_TRANSFORM/);
|
|
assert.match(runtime, /DracoDecoderModule/);
|
|
assert.match(runtime, /draco_decoder_gltf\.wasm/);
|
|
assert.match(runtime, /ensureCollision/);
|
|
assert.match(runtime, /app\.root\.addChild/);
|
|
assert.match(runtime, /dispose\(\)/);
|
|
assert.doesNotMatch(`${runtime}\n${viewport}`, /iframe|<GSplat/);
|
|
assert.match(viewport, /Collision недоступен/);
|
|
assert.match(viewport, /Для этой сборки collision GLB не был запрошен/);
|
|
assert.match(viewport, /<Select[\s\S]*Качество Gaussian-сцены/);
|
|
assert.match(viewport, /useState<SimulationQuality>\(project\.viewerSettings\.quality\)/);
|
|
assert.match(viewport, /runtimeRef\.current\?\.home\(\)/);
|
|
assert.match(viewport, /Настройки сцены/);
|
|
assert.match(viewport, /Инверсия визуального слоя/);
|
|
assert.match(viewport, /Инверсия collision-слоя/);
|
|
assert.match(viewport, /Инверсия управления по горизонтали/);
|
|
assert.match(viewport, /Инверсия управления по вертикали/);
|
|
assert.match(viewport, /Ось инверсии визуального слоя/);
|
|
assert.match(viewport, /Ось инверсии collision-слоя/);
|
|
assert.match(viewport, /saveSimulationViewerSettings/);
|
|
assert.match(viewport, /onProjectChange\?\.\(saved\)/);
|
|
assert.match(viewport, /const worldManifestRevision = JSON\.stringify\(project\.worldManifest\)/);
|
|
assert.match(viewport, /\[project\.projectId, worldManifestRevision\]/);
|
|
assert.doesNotMatch(viewport, /\[project\.projectId, project\.worldManifest\]/);
|
|
});
|