84 lines
4.6 KiB
JavaScript
84 lines
4.6 KiB
JavaScript
"use strict";
|
|
|
|
const test = require("node:test");
|
|
const assert = require("node:assert/strict");
|
|
const fs = require("node:fs");
|
|
const path = require("node:path");
|
|
|
|
const root = path.resolve(__dirname, "..", "..");
|
|
const app = fs.readFileSync(path.join(root, "Web", "app.js"), "utf8");
|
|
const index = fs.readFileSync(path.join(root, "Web", "index.html"), "utf8");
|
|
const native = fs.readFileSync(path.join(root, "MainWindow.NamedKrxThemeRestore.cs"), "utf8");
|
|
const namedBridge = fs.readFileSync(path.join(root, "MainWindow.NamedPlaylists.cs"), "utf8");
|
|
|
|
function functionBody(name, nextName) {
|
|
const start = app.indexOf(`function ${name}(`);
|
|
const end = app.indexOf(`function ${nextName}(`, start + 1);
|
|
assert.ok(start >= 0 && end > start, `${name} must precede ${nextName}`);
|
|
return app.slice(start, end);
|
|
}
|
|
|
|
test("named KRX restore is correlated from one native load through page preflight", () => {
|
|
assert.match(index,
|
|
/src="named-krx-theme-restore-workflow\.js"[\s\S]*src="named-nxt-theme-restore-workflow\.js"/u);
|
|
assert.match(namedBridge,
|
|
/await PostNamedKrxThemeRestoreAsync\([\s\S]*await PostNamedNxtThemeRestoreAsync\(/u);
|
|
assert.match(native, /PostMessage\("named-krx-theme-restore-results"/u);
|
|
assert.match(app, /krxThemeRestorePending/u);
|
|
assert.match(app, /case "named-krx-theme-restore-results"/u);
|
|
assert.match(app, /case "named-krx-theme-restore-error"/u);
|
|
const finalize = functionBody("finalizeNamedManualRestores", "handleNamedManualListResults");
|
|
assert.match(finalize, /state\.namedPlaylist\.krxThemeRestorePending/u);
|
|
assert.match(finalize, /prepareNamedPagePreflight/u);
|
|
});
|
|
|
|
test("generic theme restore cannot trust a historical KRX code before native verification", () => {
|
|
const addTheme = functionBody("addThemeNamedCandidates", "addOverseasNamedCandidates");
|
|
assert.match(addTheme,
|
|
/rawRow\.groupCode === "테마" \|\| rawRow\.groupCode === "테마_NXT"/u);
|
|
const load = functionBody("handleNamedPlaylistLoadResults", "failNamedComparisonRestore");
|
|
assert.match(load, /namedKrxThemeRestoreWorkflow\.classify/u);
|
|
assert.match(load, /pendingKrxThemes\.length === 0/u);
|
|
assert.match(load, /krxThemeRestorePending = pendingKrxThemes\.length/u);
|
|
const resolve = functionBody("resolveNamedPlaylistRawRow", "prepareNamedPagePreflight");
|
|
assert.match(resolve,
|
|
/rawRow\?\.groupCode === "테마" \|\| rawRow\?\.groupCode === "테마_NXT"[\s\S]*return null/u);
|
|
});
|
|
|
|
test("current KRX identity stays branded in memory and old code is retained only for save", () => {
|
|
const materialize = functionBody("materializeNamedRestoration", "namedPlaylistPrepareBlockers");
|
|
assert.match(materialize,
|
|
/namedKrxThemeRestoreWorkflow\.isMaterializedEntry\(row\.entry\)/u);
|
|
const synchronize = functionBody("synchronizeThemeEntries", "clearOverseasTimeout");
|
|
assert.match(synchronize,
|
|
/namedKrxThemeRestoreWorkflow\.isMaterializedEntry\(item\)[\s\S]*\? item/u);
|
|
const fields = functionBody("namedLegacyFieldsForEntry", "isTrustedNamedPlaylistEntry");
|
|
assert.match(fields, /namedKrxThemeRestoreWorkflow\.legacySelectionForEntry\(entry\)/u);
|
|
assert.match(fields, /namedKrxThemeRestoreWorkflow\.matchesRaw\(entry, rawRow\)/u);
|
|
assert.match(fields, /KRX 테마의 과거 code와 현재 송출 code/u);
|
|
});
|
|
|
|
test("KRX failures are terminal and never trigger an automatic retry or playout", () => {
|
|
const failed = functionBody("failNamedKrxThemeRestore", "handleNamedKrxThemeRestoreResults");
|
|
assert.match(failed, /krxThemeRestorePending = null/u);
|
|
assert.doesNotMatch(app, /retryNamedKrxTheme|requestNamedKrxThemeRestore/u);
|
|
assert.doesNotMatch(native, /IPlayoutEngine|PrepareAsync|TakeInAsync|NextAsync|TakeOutAsync/u);
|
|
assert.match(native, /retryable = false/u);
|
|
});
|
|
|
|
test("KRX success accounting and post-load cancellation close every correlated busy record", () => {
|
|
const results = functionBody("handleNamedKrxThemeRestoreResults", "handleNamedKrxThemeRestoreError");
|
|
assert.match(results,
|
|
/state\.playlist\[pending\.itemIndex\] = entry;\s*restoredCount \+= 1;/u);
|
|
|
|
const clear = functionBody("clearNamedPlaylistLoadState", "saveNamedPlaylistBackup");
|
|
assert.match(clear, /krxThemeRestorePending = null/u);
|
|
const busy = functionBody("namedPlaylistBusy", "renderNamedPlaylist");
|
|
assert.match(busy, /state\.namedPlaylist\.krxThemeRestorePending/u);
|
|
const loadError = functionBody("handleNamedPlaylistError", "normalizePlayoutState");
|
|
assert.match(loadError, /error\.operation !== "load"/u);
|
|
assert.match(loadError,
|
|
/state\.namedPlaylist\.krxThemeRestorePending\?\.requestId === error\.requestId[\s\S]*krxThemeRestorePending = null/u);
|
|
assert.match(loadError, /복원 배치는 자동 재시도하지 않습니다/u);
|
|
});
|