fix: rebind imported experiments to active inputs
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { validateResult } from "/packages/contracts/validation.js";
|
||||
import { validateExperiment, validateResult } from "/packages/contracts/validation.js";
|
||||
|
||||
async function waitFor(predicate, label, timeoutMs = 30000) {
|
||||
const deadline = performance.now() + timeoutMs;
|
||||
@@ -344,7 +344,7 @@ test("Acoustic Camera가 8×8 CPU 실행·결과 저장·stale·재실행 흐름
|
||||
}
|
||||
});
|
||||
|
||||
test("Acoustic Camera가 Experiment 선로드와 Scene·Array 재import에서 다중 분석 대역을 보존한다", async () => {
|
||||
test("Acoustic Camera가 Experiment를 현재 입력에 연결하고 Scene·Array 재import에서도 다중 대역을 보존한다", async () => {
|
||||
const frame = document.createElement("iframe");
|
||||
frame.src = "/apps/acoustic-camera/?integration-test=1&band-preservation=1";
|
||||
frame.style.cssText = "position:fixed;left:-20000px;top:0;width:1400px;height:1000px;border:0";
|
||||
@@ -393,7 +393,8 @@ test("Acoustic Camera가 Experiment 선로드와 Scene·Array 재import에서
|
||||
assert(link.relList.contains("noopener"), "Builder tab cannot replace Camera through opener");
|
||||
}
|
||||
|
||||
const scene = await loadJson("/assets/sample-scenes/single-tone.scene.json");
|
||||
const openScene = await loadJson("/assets/sample-scenes/single-tone.scene.json");
|
||||
const scene = structuredClone(openScene);
|
||||
scene.id = "two-tone-band-preservation";
|
||||
scene.name = "Two-tone band preservation";
|
||||
const secondSource = structuredClone(scene.sources[0]);
|
||||
@@ -404,7 +405,10 @@ test("Acoustic Camera가 Experiment 선로드와 Scene·Array 재import에서
|
||||
secondSource.signal.phaseDeg = 45;
|
||||
scene.sources.push(secondSource);
|
||||
|
||||
const arrayDefinition = await loadJson("/assets/array-geometries/rectangular-16x12.array.json");
|
||||
const openArrayDefinition = await loadJson(
|
||||
"/assets/array-geometries/rectangular-16x12.array.json",
|
||||
);
|
||||
const arrayDefinition = structuredClone(openArrayDefinition);
|
||||
arrayDefinition.id = "custom-array-band-preservation";
|
||||
arrayDefinition.name = "Custom array band preservation";
|
||||
|
||||
@@ -427,13 +431,15 @@ test("Acoustic Camera가 Experiment 선로드와 Scene·Array 재import에서
|
||||
);
|
||||
dispatchFiles(windowObject, documentObject.querySelector("#experiment-input"), [experimentFile]);
|
||||
await waitFor(
|
||||
() => documentObject.documentElement.dataset.inputBusy === "false",
|
||||
"clean-state Experiment-first import",
|
||||
() => documentObject.documentElement.dataset.inputBusy === "false" &&
|
||||
documentObject.documentElement.dataset.cameraValid === "true" &&
|
||||
!documentObject.querySelector("#run-button").disabled,
|
||||
"Experiment import and automatic reference binding",
|
||||
);
|
||||
assertEqual(
|
||||
documentObject.querySelector("#experiment-id").value,
|
||||
experiment.id,
|
||||
"Experiment loads before its referenced Scene",
|
||||
"Experiment document loads before its originally referenced Scene",
|
||||
);
|
||||
assertEqual(readBandEditors().length, 2, "Experiment-first import renders every analysis band");
|
||||
assertEqual(
|
||||
@@ -441,22 +447,77 @@ test("Acoustic Camera가 Experiment 선로드와 Scene·Array 재import에서
|
||||
JSON.stringify(expectedBands),
|
||||
"Experiment-first import preserves band IDs, ranges, and colors",
|
||||
);
|
||||
await waitFor(
|
||||
() => documentObject.documentElement.dataset.cameraValid === "false" &&
|
||||
documentObject.querySelector("#validation-message").textContent.includes("sceneId") &&
|
||||
documentObject.querySelector("#validation-message").textContent.includes("arrayId"),
|
||||
"pending Scene and Array linkage validation",
|
||||
);
|
||||
assert(
|
||||
documentObject.querySelector("#validation-message").textContent.includes("다릅니다"),
|
||||
"Experiment-first import explains the pending document ID mismatch",
|
||||
!documentObject.querySelector("#validation-message").textContent.includes("sceneId") &&
|
||||
!documentObject.querySelector("#validation-message").textContent.includes("arrayId") &&
|
||||
!documentObject.querySelector("#run-status").textContent.includes("연결 대기"),
|
||||
"automatic binding does not leave a reference mismatch warning",
|
||||
);
|
||||
assert(
|
||||
documentObject.querySelector("#run-status").textContent.includes("분석 대역 2개") &&
|
||||
documentObject.querySelector("#run-status").textContent.includes(scene.id) &&
|
||||
documentObject.querySelector("#run-status").textContent.includes(arrayDefinition.id) &&
|
||||
documentObject.querySelector("#run-status").textContent.includes("연결 대기"),
|
||||
"Experiment-first status reports every band and pending reference",
|
||||
documentObject.querySelector("#run-status").textContent.includes("실행 준비 완료"),
|
||||
"Experiment import reaches a ready state with every band",
|
||||
);
|
||||
|
||||
documentObject.querySelector("#export-experiment-button").click();
|
||||
const reboundDownload = await waitFor(
|
||||
() => downloads.find((download) => download.fileName.endsWith(".experiment.json")),
|
||||
"automatically rebound Experiment export",
|
||||
);
|
||||
const reboundExperiment = await fetch(reboundDownload.url).then((response) => response.json());
|
||||
assertEqual(reboundExperiment.sceneId, openScene.id, "import binds the open Scene ID");
|
||||
assertEqual(
|
||||
reboundExperiment.arrayId,
|
||||
openArrayDefinition.id,
|
||||
"import binds the open Array ID",
|
||||
);
|
||||
assertEqual(
|
||||
JSON.stringify(reboundExperiment.frequencyBands),
|
||||
JSON.stringify(expectedBands),
|
||||
"automatic reference binding preserves every imported band",
|
||||
);
|
||||
assertEqual(
|
||||
(await validateExperiment(reboundExperiment, {
|
||||
scene: openScene,
|
||||
arrayDefinition: openArrayDefinition,
|
||||
})).length,
|
||||
0,
|
||||
"rebound Experiment passes relationship validation",
|
||||
);
|
||||
downloads.length = 0;
|
||||
|
||||
const contextInvalidExperiment = structuredClone(experiment);
|
||||
contextInvalidExperiment.id = "nyquist-invalid-after-rebind";
|
||||
contextInvalidExperiment.frequencyBands[0].maxHz = openScene.sampleRate / 2;
|
||||
assertEqual(
|
||||
(await validateExperiment(contextInvalidExperiment)).length,
|
||||
0,
|
||||
"Nyquist fixture is valid without a Scene context",
|
||||
);
|
||||
const contextInvalidFile = new windowObject.File(
|
||||
[JSON.stringify(contextInvalidExperiment)],
|
||||
"nyquist-invalid-after-rebind.experiment.json",
|
||||
{ type: "application/json" },
|
||||
);
|
||||
dispatchFiles(
|
||||
windowObject,
|
||||
documentObject.querySelector("#experiment-input"),
|
||||
[contextInvalidFile],
|
||||
);
|
||||
await waitFor(
|
||||
() => documentObject.documentElement.dataset.inputBusy === "false" &&
|
||||
documentObject.documentElement.dataset.cameraValid === "true",
|
||||
"relationship-invalid Experiment rejection",
|
||||
);
|
||||
assertEqual(
|
||||
documentObject.querySelector("#experiment-id").value,
|
||||
experiment.id,
|
||||
"context relationship validation rejects the imported Experiment before assignment",
|
||||
);
|
||||
assertEqual(
|
||||
JSON.stringify(readBandEditors()),
|
||||
JSON.stringify(expectedBands),
|
||||
"failed relationship validation leaves the current bands unchanged",
|
||||
);
|
||||
|
||||
let replacementConfirmCount = 0;
|
||||
@@ -487,7 +548,7 @@ test("Acoustic Camera가 Experiment 선로드와 Scene·Array 재import에서
|
||||
() => documentObject.documentElement.dataset.inputBusy === "false" &&
|
||||
documentObject.querySelectorAll("#source-summary .source-line").length === 2 &&
|
||||
documentObject.querySelectorAll("#band-list .band-editor").length === 2 &&
|
||||
documentObject.documentElement.dataset.cameraValid === "false",
|
||||
documentObject.documentElement.dataset.cameraValid === "true",
|
||||
"source-added Scene reimport",
|
||||
);
|
||||
assertEqual(
|
||||
|
||||
Reference in New Issue
Block a user