"use strict"; const assert = require("node:assert/strict"); const fs = require("node:fs"); const path = require("node:path"); const test = require("node:test"); const repositoryRoot = path.resolve(__dirname, "..", ".."); const webRoot = path.join(repositoryRoot, "src", "MBN_STOCK_WEBVIEW.LegacyParityApp", "Web"); const app = fs.readFileSync(path.join(webRoot, "app.js"), "utf8"); const markup = fs.readFileSync(path.join(webRoot, "index.html"), "utf8"); test("legacy shell exposes the original stock, cut, playlist and playout controls", () => { for (const id of [ "stock-search", "stock-search-button", "stock-results", "cut-list", "playlist-drop-zone", "playlist-rows", "legacy-dialog" ]) { assert.match(markup, new RegExp("id=\\\"" + id + "\\\"")); } assert.match(markup, /TAKE IN/); assert.match(markup, /TAKE OUT/); assert.match(markup, /NEXT/); assert.match(markup, /class="connection-state"[^>]*>미연결<\/div>/); assert.match(markup, /class="active" type="button" disabled>해외<\/button>/); assert.match(markup, /type="button" disabled>정지<\/button>/); }); test("web layer sends intent and does not own scene, DB identity or playlist state", () => { assert.doesNotMatch(app, /(?:sceneCode|cutCode|stockCode|dataCode|builderKey)/); assert.doesNotMatch(app, /(?:localStorage|sessionStorage|playlist\.push|fetch\s*\()/); assert.doesNotMatch(app, /\b(?:5001|N5001|5006|5011|5086|8035|8061|8040|8046|8051|8056|8003|5037)\b/); }); test("legacy double click is represented by pointer-down facts, not browser dblclick policy", () => { assert.match(app, /cut-pointer-down/); assert.match(app, /timestampMilliseconds/); assert.match(app, /event\.ctrlKey/); assert.match(app, /event\.shiftKey/); assert.doesNotMatch(app, /dblclick/); }); test("cut rows are reconciled in place so a state reply cannot cancel native drag", () => { assert.match(app, /dataset\.physicalIndex/); assert.match(app, /function createCutElement/); assert.doesNotMatch(app, /cutList\.replaceChildren/); }); test("state rendering preserves stock and playlist focus like native controls", () => { assert.match(app, /dataset\.resultIndex/); assert.match(app, /dataset\.rowId/); assert.doesNotMatch(app, /stockResults\.replaceChildren/); assert.doesNotMatch(app, /playlistRows\.replaceChildren/); }); test("separator rows preserve the original drag gesture", () => { assert.match(app, /element\.draggable = true/); assert.doesNotMatch(app, /draggable = !row\.isSeparator/); }); test("a C# busy snapshot freezes controls instead of silently accepting queued input", () => { const styles = fs.readFileSync(path.join(webRoot, "styles.css"), "utf8"); assert.match(app, /state\.isBusy === true/); assert.match(app, /classList\.toggle\("busy"/); assert.match(styles, /body\.busy \.operator-shell \{ pointer-events: none; \}/); });