100 lines
4.6 KiB
JavaScript
100 lines
4.6 KiB
JavaScript
"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 markup = fs.readFileSync(path.join(webRoot, "index.html"), "utf8");
|
|
const app = fs.readFileSync(path.join(webRoot, "app.js"), "utf8");
|
|
const styles = fs.readFileSync(path.join(webRoot, "styles.css"), "utf8");
|
|
const modalFocus = fs.readFileSync(path.join(webRoot, "legacy-modal-focus.js"), "utf8");
|
|
const inputSmoke = fs.readFileSync(path.join(
|
|
repositoryRoot, "scripts", "Test-LegacyPackageInput.mjs"), "utf8");
|
|
|
|
function section(source, startMarker, endMarker) {
|
|
const start = source.indexOf(startMarker);
|
|
assert.notEqual(start, -1, "missing start marker: " + startMarker);
|
|
const end = source.indexOf(endMarker, start + startMarker.length);
|
|
assert.ok(end > start, "missing end marker: " + endMarker);
|
|
return source.slice(start, end);
|
|
}
|
|
|
|
function navButton(tabId) {
|
|
const match = markup.match(new RegExp(
|
|
`<button[^>]*data-tab-id="${tabId}"[\\s\\S]*?<\\/button>`));
|
|
assert.ok(match, "missing navigation button: " + tabId);
|
|
return match[0];
|
|
}
|
|
|
|
test("GraphE and FSell or VI expose the original visible exit controls", () => {
|
|
assert.match(markup,
|
|
/id="manual-financial-workspace"[\s\S]*?<footer class="manual-dialog-footer">\s*<button id="manual-financial-exit" type="button">나가기<\/button>/u);
|
|
assert.match(markup,
|
|
/id="manual-list-workspace"[\s\S]*?<footer class="manual-dialog-footer">\s*<button id="manual-list-cancel" type="button">취소<\/button>/u);
|
|
assert.match(styles,
|
|
/\.manual-financial-dialog\s*\{[^}]*grid-template-rows:\s*46px minmax\(0, 1fr\) auto/u);
|
|
assert.match(styles,
|
|
/\.manual-list-dialog\s*\{[^}]*grid-template-rows:\s*46px minmax\(0, 1fr\) auto/u);
|
|
assert.match(styles, /\.manual-dialog-footer\s*\{[^}]*justify-content:\s*flex-end/u);
|
|
});
|
|
|
|
test("visible text controls reuse the exact top-close actions", () => {
|
|
const financialClose = section(
|
|
app, "function closeManualFinancial", "manualListButtons.forEach");
|
|
assert.equal((financialClose.match(/send\("close-manual-financial"/g) || []).length, 1);
|
|
assert.match(financialClose,
|
|
/manualClose\.addEventListener\("click", closeManualFinancial\)/);
|
|
assert.match(financialClose,
|
|
/manualExit\.addEventListener\("click", closeManualFinancial\)/);
|
|
|
|
const listClose = section(
|
|
app, "function closeManualList", "manualWorkspace.addEventListener");
|
|
assert.equal((listClose.match(/send\("close-manual-list"/g) || []).length, 1);
|
|
assert.match(listClose,
|
|
/manualListClose\.addEventListener\("click", closeManualList\)/);
|
|
assert.match(listClose,
|
|
/manualListCancel\.addEventListener\("click", closeManualList\)/);
|
|
});
|
|
|
|
test("text and top-close controls share locking and modal keyboard focus", () => {
|
|
assert.match(app, /manualExit\.disabled = manualClose\.disabled/);
|
|
assert.match(app, /manualListCancel\.disabled = manualListClose\.disabled/);
|
|
assert.match(app,
|
|
/setTransientControlsBusy\(manualDialog, state\.isBusy === true\)/);
|
|
assert.match(app, /setTransientControlsBusy\(manualListDialog, busy\)/);
|
|
assert.match(app,
|
|
/root\.querySelectorAll\("button, input, select, textarea"\)/);
|
|
assert.match(modalFocus,
|
|
/const focusableSelector = \[[\s\S]*?"button"[\s\S]*?\]\.join\(","\)/);
|
|
|
|
for (const id of ["manual-financial-exit", "manual-list-cancel"]) {
|
|
const button = markup.match(new RegExp(`<button id="${id}"[^>]*>`));
|
|
assert.ok(button, "missing visible close button: " + id);
|
|
assert.match(button[0], /type="button"/);
|
|
assert.doesNotMatch(button[0], /(?:disabled|tabindex="-1")/);
|
|
}
|
|
});
|
|
|
|
test("full UI input validation physically clicks the restored text controls", () => {
|
|
assert.match(inputSmoke,
|
|
/async function closeManualFinancial[\s\S]*?pointerClick\('document\.getElementById\("manual-financial-exit"\)'/);
|
|
assert.match(inputSmoke,
|
|
/async function closeManualList[\s\S]*?pointerClick\('document\.getElementById\("manual-list-cancel"\)'/);
|
|
});
|
|
|
|
test("clearer sidebar names keep the existing protocol tab IDs", () => {
|
|
const overseas = navButton("overseasStocks");
|
|
assert.match(overseas, /aria-label="해외시장"/u);
|
|
assert.match(overseas, /title="해외시장"/u);
|
|
assert.match(overseas, /<span class="workspace-nav-label">해외시장<\/span>/u);
|
|
|
|
const halt = navButton("tradingHalt");
|
|
assert.match(halt, /aria-label="거래정지"/u);
|
|
assert.match(halt, /title="거래정지"/u);
|
|
assert.match(halt, /<span class="workspace-nav-label">거래정지<\/span>/u);
|
|
});
|