78 lines
3.8 KiB
JavaScript
78 lines
3.8 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 read = relativePath => fs.readFileSync(path.join(root, relativePath), "utf8");
|
|
const app = read("Web/app.js");
|
|
const index = read("Web/index.html");
|
|
const styles = read("Web/styles.css");
|
|
const native = fs.readdirSync(root)
|
|
.filter(name => /^MainWindow(?:\..+)?\.cs$/u.test(name))
|
|
.map(name => read(name))
|
|
.join("\n");
|
|
|
|
function functionBody(source, name, nextName) {
|
|
const start = source.indexOf(`function ${name}(`);
|
|
assert.ok(start >= 0, `${name} must exist`);
|
|
const end = source.indexOf(`function ${nextName}(`, start + 1);
|
|
assert.ok(end > start, `${name} must precede ${nextName}`);
|
|
return source.slice(start, end);
|
|
}
|
|
|
|
test("trading-halt results expose an accessible stock-name sort header", () => {
|
|
assert.match(index,
|
|
/class="trading-halt-results-header" role="group" aria-label="거래 정지 검색 결과 정렬"[\s\S]*id="tradingHaltNameSort"[\s\S]*aria-controls="tradingHaltResults"[\s\S]*data-sort-direction="none">종목명 ↕<\/button>/u);
|
|
assert.match(styles, /\.trading-halt-results-header\s*\{/u);
|
|
assert.match(styles, /\.trading-halt-results-header button:disabled\s*\{/u);
|
|
});
|
|
|
|
test("render sorts only a copied display view and preserves market-code selection identity", () => {
|
|
const identity = functionBody(app, "tradingHaltIdentity", "toggleTradingHaltNameSort");
|
|
const render = functionBody(app, "renderTradingHaltWorkflow", "requestTradingHaltSearch");
|
|
|
|
assert.match(identity, /tradingHaltWorkflow\.tradingHaltIdentity\(value\)/u);
|
|
assert.doesNotMatch(identity, /displayName/u);
|
|
assert.match(render,
|
|
/sortTradingHaltsForDisplay\(\s*workflow\.results,\s*workflow\.sortDirection\)/u);
|
|
assert.match(render,
|
|
/tradingHaltIdentity\(item\) === selectedIdentity/u);
|
|
assert.doesNotMatch(render, /workflow\.results\.sort\(/u);
|
|
});
|
|
|
|
test("sort is blocked while pending, locked, or empty and otherwise toggles locally", () => {
|
|
const toggle = functionBody(app, "toggleTradingHaltNameSort", "selectTradingHalt");
|
|
const render = functionBody(app, "renderTradingHaltWorkflow", "requestTradingHaltSearch");
|
|
|
|
assert.match(toggle,
|
|
/isPlaylistSnapshotLocked\(\) \|\| workflow\.status !== "ready" \|\| !workflow\.results\.length/u);
|
|
assert.match(toggle,
|
|
/workflow\.sortDirection = tradingHaltWorkflow\.nextTradingHaltNameSort\(workflow\.sortDirection\)/u);
|
|
assert.match(render,
|
|
/const canSort = workflow\.status === "ready" && workflow\.results\.length > 0/u);
|
|
assert.match(render, /tradingHaltNameSort\.disabled = locked \|\| !canSort/u);
|
|
assert.doesNotMatch(toggle,
|
|
/postNative|requestTradingHaltSearch|state\.playlist|renderPlaylist|updatePreview/u);
|
|
});
|
|
|
|
test("each new search and matching result restores the server-default order", () => {
|
|
const request = functionBody(app, "requestTradingHaltSearch", "handleTradingHaltResults");
|
|
const results = functionBody(app, "handleTradingHaltResults", "handleTradingHaltError");
|
|
|
|
assert.match(request,
|
|
/workflow\.status = "loading";[\s\S]*workflow\.results = \[\];[\s\S]*workflow\.sortDirection = null;/u);
|
|
assert.match(results,
|
|
/clearTradingHaltTimeout\(\);\s*workflow\.sortDirection = null;[\s\S]*workflow\.results = \[\.\.\.response\.results\]/u);
|
|
});
|
|
|
|
test("the display sort adds no native command surface or playlist mutation", () => {
|
|
const toggle = functionBody(app, "toggleTradingHaltNameSort", "selectTradingHalt");
|
|
assert.doesNotMatch(toggle,
|
|
/postNative|state\.playlist|renderPlaylist|updatePreview|prepare|take-in|take-out/iu);
|
|
assert.doesNotMatch(native, /sort-trading-halt|trading-halt-sort/iu);
|
|
assert.doesNotMatch(app, /postNative\("(?:sort-trading-halt|trading-halt-sort)"/iu);
|
|
});
|