Complete legacy operator UI and playout migration
This commit is contained in:
156
tests/Web/operator-command-matrix.test.cjs
Normal file
156
tests/Web/operator-command-matrix.test.cjs
Normal file
@@ -0,0 +1,156 @@
|
||||
"use strict";
|
||||
|
||||
const test = require("node:test");
|
||||
const assert = require("node:assert/strict");
|
||||
|
||||
const fixed = require("../../Web/legacy-fixed-workflow.js");
|
||||
const industry = require("../../Web/industry-workflow.js");
|
||||
const stock = require("../../Web/operator-workflow.js");
|
||||
const comparison = require("../../Web/comparison-workflow.js");
|
||||
|
||||
const now = new Date("2026-07-11T12:00:00+09:00");
|
||||
const kospiStock = Object.freeze({
|
||||
market: "kospi",
|
||||
stockName: "삼성전자",
|
||||
displayName: "삼성전자",
|
||||
stockCode: "005930",
|
||||
isNxt: false
|
||||
});
|
||||
const primaryIndustry = Object.freeze({
|
||||
market: "kospi",
|
||||
code: "001",
|
||||
name: "전기전자"
|
||||
});
|
||||
const secondaryIndustry = Object.freeze({
|
||||
market: "kospi",
|
||||
code: "002",
|
||||
name: "금융업"
|
||||
});
|
||||
const kosdaqPrimaryIndustry = Object.freeze({
|
||||
market: "kosdaq",
|
||||
code: "101",
|
||||
name: "IT"
|
||||
});
|
||||
const kosdaqSecondaryIndustry = Object.freeze({
|
||||
market: "kosdaq",
|
||||
code: "102",
|
||||
name: "제약"
|
||||
});
|
||||
const comparisonPair = Object.freeze([
|
||||
Object.freeze({ kind: "krx-stock", market: "kospi", stockName: "삼성전자", stockCode: "005930" }),
|
||||
Object.freeze({ kind: "krx-stock", market: "kospi", stockName: "SK하이닉스", stockCode: "000660" })
|
||||
]);
|
||||
|
||||
test("the original operator command matrix has exactly 412 visible slots", () => {
|
||||
assert.equal(fixed.actions.length, 328);
|
||||
assert.equal(industry.cuts.length * industry.markets.length, 44);
|
||||
assert.equal(stock.stockCuts.length, 31);
|
||||
assert.equal(comparison.actions.length, 9);
|
||||
assert.equal(
|
||||
fixed.actions.length + industry.cuts.length * industry.markets.length +
|
||||
stock.stockCuts.length + comparison.actions.length,
|
||||
412);
|
||||
|
||||
assert.equal(new Set(fixed.actions.map(value => value.id)).size, 328);
|
||||
assert.equal(new Set(industry.cuts.map(value => value.id)).size, 22);
|
||||
assert.equal(new Set(stock.stockCuts.map(value => value.id)).size, 31);
|
||||
assert.equal(new Set(comparison.actions.map(value => value.id)).size, 9);
|
||||
});
|
||||
|
||||
test("all 322 non-manual fixed slots create and strictly round-trip", () => {
|
||||
const available = fixed.actions.filter(value => value.available);
|
||||
assert.equal(available.length, 322);
|
||||
|
||||
for (const [index, action] of available.entries()) {
|
||||
const created = fixed.createFixedPlaylistEntry(action.id, {
|
||||
id: `fixed-matrix-${index + 1}`,
|
||||
fadeDuration: 6,
|
||||
now,
|
||||
ma5: true,
|
||||
ma20: true
|
||||
});
|
||||
const restored = fixed.restoreFixedPlaylistEntry(created, { now });
|
||||
assert.ok(restored, `${action.id} ${action.label}`);
|
||||
assert.equal(restored.builderKey, action.builderKey);
|
||||
assert.equal(restored.code, action.code);
|
||||
}
|
||||
});
|
||||
|
||||
test("the six fixed manual placeholders resolve only through their dedicated editors", () => {
|
||||
const manual = fixed.actions.filter(value => !value.available);
|
||||
assert.deepEqual(
|
||||
manual.map(value => [value.id, value.label, value.builderKey, value.code]),
|
||||
[
|
||||
["fixed-245", "개인 순매도 상위(수동)", "s5025", "5025"],
|
||||
["fixed-246", "외국인 순매도 상위(수동)", "s5025", "5025"],
|
||||
["fixed-247", "기관 순매도 상위(수동)", "s5025", "5025"],
|
||||
["fixed-262", "VI 발동(수동)", "s5074", "5074"],
|
||||
["fixed-293", "VI 발동(수동)", "s5074", "5074"],
|
||||
["fixed-320", "VI 발동(수동)", "s5074", "5074"]
|
||||
]);
|
||||
for (const action of manual) {
|
||||
assert.throws(() => fixed.createFixedPlaylistEntry(action.id, {
|
||||
id: `blocked-${action.id}`,
|
||||
fadeDuration: 6,
|
||||
now
|
||||
}), /manual|수동|입력/i);
|
||||
}
|
||||
});
|
||||
|
||||
test("all 44 industry slots create and strictly round-trip with explicit selections", () => {
|
||||
let ordinal = 0;
|
||||
for (const market of industry.markets) {
|
||||
const selected = market === "kospi" ? primaryIndustry : kosdaqPrimaryIndustry;
|
||||
const pair = market === "kospi"
|
||||
? [primaryIndustry, secondaryIndustry]
|
||||
: [kosdaqPrimaryIndustry, kosdaqSecondaryIndustry];
|
||||
for (const cut of industry.cuts) {
|
||||
ordinal += 1;
|
||||
const created = industry.createIndustryPlaylistEntry(market, cut.id, {
|
||||
id: `industry-matrix-${ordinal}`,
|
||||
fadeDuration: 6,
|
||||
selected,
|
||||
pair,
|
||||
now,
|
||||
ma5: true,
|
||||
ma20: true
|
||||
});
|
||||
const restored = industry.restoreIndustryPlaylistEntry(created, { now });
|
||||
assert.ok(restored, `${market} ${cut.id}`);
|
||||
assert.equal(restored.builderKey, created.builderKey);
|
||||
assert.equal(restored.code, created.code);
|
||||
}
|
||||
}
|
||||
assert.equal(ordinal, 44);
|
||||
});
|
||||
|
||||
test("all 31 stock and nine comparison slots create and strictly round-trip", () => {
|
||||
for (const [index, cut] of stock.stockCuts.entries()) {
|
||||
const created = stock.createStockPlaylistEntry(kospiStock, cut.id, {
|
||||
id: `stock-matrix-${index + 1}`,
|
||||
fadeDuration: 6,
|
||||
ma5: true,
|
||||
ma20: true
|
||||
});
|
||||
assert.ok(stock.restoreStockPlaylistEntry(created), cut.id);
|
||||
}
|
||||
|
||||
for (const [index, action] of comparison.actions.entries()) {
|
||||
const created = comparison.createComparisonPlaylistEntry(
|
||||
action.id,
|
||||
comparisonPair,
|
||||
{ id: `comparison-matrix-${index + 1}`, fadeDuration: 6 });
|
||||
assert.ok(comparison.restoreComparisonPlaylistEntry(created), action.id);
|
||||
}
|
||||
});
|
||||
|
||||
test("the four GraphE buttons remain outside the 412 slots and map to exact INPUT tables", () => {
|
||||
assert.deepEqual(
|
||||
stock.manualStockActions.map(value => [value.id, value.builderKey, value.prerequisiteTable]),
|
||||
[
|
||||
["manual-revenue-mix", "s5076", "INPUT_PIE"],
|
||||
["manual-growth-metrics", "s5079", "INPUT_GROW"],
|
||||
["manual-sales", "s5080", "INPUT_SELL"],
|
||||
["manual-operating-profit", "s5081", "INPUT_PROFIT"]
|
||||
]);
|
||||
});
|
||||
Reference in New Issue
Block a user