feat: protect unsaved camera work
This commit is contained in:
@@ -44,6 +44,7 @@ test("Acoustic Camera가 8×8 CPU 실행·결과 저장·stale·재실행 흐름
|
||||
const objectUrls = [];
|
||||
const originalAnchorClick = windowObject.HTMLAnchorElement.prototype.click;
|
||||
const originalRevoke = windowObject.URL.revokeObjectURL.bind(windowObject.URL);
|
||||
const originalConfirm = windowObject.confirm.bind(windowObject);
|
||||
windowObject.HTMLAnchorElement.prototype.click = function captureDownload() {
|
||||
downloads.push({ fileName: this.download, url: this.href });
|
||||
};
|
||||
@@ -73,6 +74,10 @@ test("Acoustic Camera가 8×8 CPU 실행·결과 저장·stale·재실행 흐름
|
||||
"8×8 CPU 입력 검증",
|
||||
);
|
||||
assertEqual(documentObject.querySelector("#grid-preset").value, "custom", "custom grid preset");
|
||||
assert(
|
||||
documentObject.documentElement.dataset.unsavedWork.includes("Experiment"),
|
||||
"edited Experiment is marked unsaved",
|
||||
);
|
||||
|
||||
documentObject.querySelector("#run-button").click();
|
||||
await waitFor(
|
||||
@@ -85,6 +90,20 @@ test("Acoustic Camera가 8×8 CPU 실행·결과 저장·stale·재실행 흐름
|
||||
assert(documentObject.querySelectorAll("#metric-grid .metric-card").length >= 9, "result metrics rendered");
|
||||
assert(!documentObject.querySelector("#metric-grid").classList.contains("is-hidden"), "metrics visible");
|
||||
assert(documentObject.querySelector("#result-badge").textContent.includes("CPU"), "backend badge rendered");
|
||||
assert(documentObject.documentElement.dataset.unsavedWork.includes("Result"), "completed Result is unsaved");
|
||||
assert(
|
||||
documentObject.documentElement.dataset.unsavedWork.includes("비교 기록"),
|
||||
"comparison summary is unsaved",
|
||||
);
|
||||
let replacementConfirmCount = 0;
|
||||
windowObject.confirm = () => {
|
||||
replacementConfirmCount += 1;
|
||||
return false;
|
||||
};
|
||||
documentObject.querySelector("#run-button").click();
|
||||
await waitFor(() => replacementConfirmCount === 1, "unsaved Result replacement confirmation");
|
||||
assertEqual(documentObject.documentElement.dataset.runState, "done", "declined replacement keeps result");
|
||||
windowObject.confirm = originalConfirm;
|
||||
await nextPaint(windowObject);
|
||||
assert(canvas.toDataURL() !== initialCanvas, "result heatmap changed the scene canvas");
|
||||
|
||||
@@ -94,6 +113,10 @@ test("Acoustic Camera가 8×8 CPU 실행·결과 저장·stale·재실행 흐름
|
||||
"Result JSON download",
|
||||
);
|
||||
const resultDocument = await fetch(resultDownload.url).then((response) => response.json());
|
||||
assert(
|
||||
!documentObject.documentElement.dataset.unsavedWork.includes("Result"),
|
||||
"Result export clears Result dirty state",
|
||||
);
|
||||
const [scene, experiment] = await Promise.all([
|
||||
loadJson("/assets/sample-scenes/single-tone.scene.json"),
|
||||
loadJson("/assets/sample-scenes/single-tone.experiment.json"),
|
||||
@@ -156,7 +179,30 @@ test("Acoustic Camera가 8×8 CPU 실행·결과 저장·stale·재실행 흐름
|
||||
const historyText = documentObject.querySelector("#history-list").textContent;
|
||||
assert(historyText.includes("rectangular baseline"), "baseline history retained");
|
||||
assert(historyText.includes("Fermat spiral"), "comparison array history added");
|
||||
|
||||
documentObject.querySelector("#export-history-button").click();
|
||||
const historyDownload = await waitFor(
|
||||
() => downloads.find((download) => download.fileName.endsWith(".comparison-history.json")),
|
||||
"comparison history download",
|
||||
);
|
||||
const historyDocument = await fetch(historyDownload.url).then((response) => response.json());
|
||||
assertEqual(historyDocument.kind, "micarrsim.comparison-history", "comparison history kind");
|
||||
assertEqual(historyDocument.items.length, 2, "both comparison summaries exported");
|
||||
assert(
|
||||
!documentObject.documentElement.dataset.unsavedWork.includes("비교 기록"),
|
||||
"history export clears comparison dirty state",
|
||||
);
|
||||
|
||||
documentObject.querySelector("#export-result-button").click();
|
||||
documentObject.querySelector("#export-experiment-button").click();
|
||||
await waitFor(
|
||||
() => !documentObject.documentElement.dataset.unsavedWork.includes("Result") &&
|
||||
!documentObject.documentElement.dataset.unsavedWork.includes("Experiment"),
|
||||
"final Camera documents saved",
|
||||
);
|
||||
assertEqual(documentObject.documentElement.dataset.unsavedWork, "", "all Camera work is saved");
|
||||
} finally {
|
||||
windowObject.confirm = originalConfirm;
|
||||
windowObject.HTMLAnchorElement.prototype.click = originalAnchorClick;
|
||||
windowObject.URL.revokeObjectURL = originalRevoke;
|
||||
for (const url of objectUrls) originalRevoke(url);
|
||||
|
||||
Reference in New Issue
Block a user