"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"); function functionSource(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).trim(); } function recreateWith(stubs) { const source = functionSource( "recreatePlaylistEntryWithEnabled", "playlistEntryManualEditBlockReason"); return new Function( "namedKrxThemeRestoreWorkflow", "namedNxtThemeRestoreWorkflow", "namedForeignStockRestoreWorkflow", "foreignIndexCandleRestoreWorkflow", "manualFinancialWorkflow", "manualListsWorkflow", `return (${source});`)( stubs.krx, stubs.nxt, stubs.foreignStock, stubs.foreignIndex, stubs.manualFinancial, stubs.manualLists); } function stubSet() { const recreate = label => (entry, enabled) => entry.trusted === label ? Object.freeze({ ...entry, enabled, retainedBrand: label }) : null; return { krx: { isMaterializedEntry: entry => entry.trusted === "krx", withEnabled: recreate("krx") }, nxt: { isMaterializedEntry: entry => entry.trusted === "nxt", withEnabled: recreate("nxt") }, foreignStock: { source: "legacy-named-foreign-stock-workflow", withEnabled: recreate("foreign-stock") }, foreignIndex: { withEnabled: recreate("foreign-index") }, manualFinancial: { withEnabled: recreate("manual-financial") }, manualLists: { withEnabled: recreate("manual-lists") } }; } test("a frozen ordinary entry toggles through an immutable replacement", () => { const recreate = recreateWith(stubSet()); const entry = Object.freeze({ id: "ordinary", code: "5001", enabled: true, operator: Object.freeze({ source: "legacy-stock-workflow" }) }); const replacement = recreate(entry, false); assert.notEqual(replacement, entry); assert.equal(entry.enabled, true); assert.equal(replacement.enabled, false); assert.equal(replacement.id, entry.id); }); test("every capability-branded entry delegates to its trust-preserving workflow", () => { const recreate = recreateWith(stubSet()); const cases = [ ["krx", { source: "legacy-theme-workflow", namedKrxRestore: {} }], ["nxt", { source: "legacy-theme-workflow", namedNxtRestore: {} }], ["foreign-stock", { source: "legacy-named-foreign-stock-workflow" }], ["foreign-index", { source: "legacy-foreign-index-candle-workflow" }], ["manual-financial", { source: "manual-financial-workflow" }], ["manual-lists", { source: "legacy-manual-lists-workflow" }] ]; for (const [trusted, operator] of cases) { const entry = Object.freeze({ id: trusted, enabled: true, trusted, operator }); const replacement = recreate(entry, false); assert.equal(replacement.retainedBrand, trusted); assert.equal(replacement.enabled, false); assert.equal(entry.enabled, true); } }); test("a proof-shaped but unbranded named entry fails closed instead of becoming a plain clone", () => { const recreate = recreateWith(stubSet()); const forgedKrx = Object.freeze({ id: "forged-krx", enabled: true, operator: Object.freeze({ source: "legacy-theme-workflow", namedKrxRestore: Object.freeze({ schemaVersion: 1 }) }) }); assert.equal(recreate(forgedKrx, false), null); }); test("checkbox, enabled-all and current-row paths never assign into playlist entries", () => { const render = functionSource("renderPlaylist", "selectPlaylistRow"); const all = functionSource("toggleAllEntriesEnabled", "moveSelected"); const current = functionSource("toggleCurrentEntryEnabled", "savePlaylist"); assert.match(render, /replacePlaylistEntryEnabledAt\(index, checkbox\.checked\)/u); assert.match(render, /renderPlaylist\(\)/u); assert.match(all, /state\.playlist\.map\(item => recreatePlaylistEntryWithEnabled/u); assert.match(all, /replacements\.some\(item => !item\)/u); assert.match(current, /replacePlaylistEntryEnabledAt\(state\.currentIndex, item\.enabled === false\)/u); assert.doesNotMatch(`${render}\n${all}\n${current}`, /item\.enabled\s*=(?!=)/u); });