"use strict"; const test = require("node:test"); const assert = require("node:assert/strict"); const fs = require("node:fs"); const path = require("node:path"); const industry = require("../../Web/industry-workflow.js"); const legacyRows = require("../../Web/legacy-named-row-workflow.js"); const namedPlaylists = require("../../Web/named-playlist-workflow.js"); const root = path.resolve(__dirname, "../.."); const app = fs.readFileSync(path.join(root, "Web/app.js"), "utf8"); const legacy = fs.readFileSync(path.join(root, "Web/legacy-named-row-workflow.js"), "utf8"); test("named industry restore creates candidates only from the exact fixed descriptor", () => { const start = app.indexOf("function addIndustryNamedCandidates("); const end = app.indexOf("function addThemeNamedCandidates(", start); assert.ok(start >= 0 && end > start); const resolver = app.slice(start, end); assert.match(resolver, /legacyNamedRowWorkflow\.industryFixedDescriptor\(rawRow\)/u); assert.match(resolver, /descriptor\.market/u); assert.match(resolver, /descriptor\.cutId/u); assert.doesNotMatch(resolver, /industryWorkflow\.cuts\.forEach/u); assert.doesNotMatch(resolver, /code:\s*`R/u); assert.doesNotMatch(app, /code:\s*`R\$\{itemIndex/u); }); test("the exact legacy signature is closed to two markets and three fixed actions", () => { assert.match(legacy, /"업종_코스피": "kospi"/u); assert.match(legacy, /"업종_코스닥": "kosdaq"/u); assert.match(legacy, /"5단 표그래프": "five-row"/u); assert.match(legacy, /"네모그래프": "square"/u); assert.match(legacy, /"섹터지수": "sector"/u); assert.match(legacy, /case "legacy-industry-workflow"/u); }); test("five-row fixed restore remains on the fresh page-plan path", () => { assert.match(app, /const namedPagedBuilderKeys = new Set\(\["s5074", "s5077", "s5088"\]\)/u); assert.match(app, /prepareNamedPagePreflight\(restoration\)/u); assert.match(app, /requestNamedPlaylistPagePlans\(\)/u); assert.match(app, /industryWorkflow\.restoreIndustryPlaylistEntry\(entry\)/u); }); test("a stored five-row page is replaced by today's selection and mandatory fresh preflight", () => { const rawRow = { itemIndex: 0, enabled: true, groupCode: "업종_코스피", subject: "코스피", graphicType: "5단 표그래프", subtype: "", pageText: "1/6", dataCode: "" }; const load = namedPlaylists.normalizeLoadResponse({ requestId: "industry-load-1", definition: { programCode: "00000001", title: "Industry" }, retrievedAt: "2026-07-12T09:00:00+09:00", totalRowCount: 1, canMutate: true, writeQuarantined: false, rows: [rawRow] }); const restoration = namedPlaylists.restoreRawRows(load, row => { const descriptor = legacyRows.industryFixedDescriptor(row); return industry.createIndustryPlaylistEntry(descriptor.market, descriptor.cutId, { id: "industry-fixed-five-row", fadeDuration: 6, now: new Date(2026, 6, 12, 9, 0, 0) }); }, legacyRows.matchesCanonicalEntry); assert.equal(restoration.rows[0].trusted, true); assert.equal(restoration.rows[0].entry.selection.dataCode, "2026-07-12"); const preflight = namedPlaylists.preparePagePreflight( restoration, entry => entry.builderKey === "s5074"); assert.equal(preflight.rows[0].pageRecalculationRequired, true); assert.equal(preflight.readyForPrepare, false); const request = namedPlaylists.createPagePlanRequest("industry-page-plan-1", preflight); assert.equal(request.entries[0].selection.dataCode, "2026-07-12"); assert.equal(request.entries[0].code, "5074"); });