Migrate remaining legacy operator workflows

This commit is contained in:
2026-07-12 05:39:27 +09:00
parent ffb8f43c19
commit a01836a2d7
132 changed files with 20566 additions and 720 deletions

View File

@@ -16,6 +16,10 @@ const playoutBridge = fs.readFileSync(
const operatorGate = fs.readFileSync(
path.join(repositoryRoot, "src", "MBN_STOCK_WEBVIEW.Core", "Playout", "OperatorMutationGate.cs"),
"utf8");
const stockMasterValidation = fs.readFileSync(
path.join(repositoryRoot, "src", "MBN_STOCK_WEBVIEW.Core", "Data",
"StockMasterIdentityValidation.cs"),
"utf8");
const krxSelection = Object.freeze({
market: "krx",
@@ -89,6 +93,11 @@ test("bridge contract pins every independent request and event name", () => {
mutation: "operator-catalog-mutation-results",
error: "operator-catalog-error"
});
assert.deepEqual(workflow.stockMasterContract, {
request: "search-stocks",
result: "stock-search-results",
error: "stock-search-error"
});
assert.deepEqual(workflow.limits, {
maximumThemeItems: 240,
maximumRecommendations: 100,
@@ -97,6 +106,43 @@ test("bridge contract pins every independent request and event name", () => {
});
});
test("stock master search accepts only complete unique typed identities", () => {
const request = workflow.createStockMasterSearchRequest("stock-master-1", " 삼성 ", 25);
assert.deepEqual(request, {
requestId: "stock-master-1",
query: "삼성",
maximumResults: 25
});
const base = {
requestId: request.requestId,
query: request.query,
retrievedAt: "2026-07-12T10:00:00+09:00",
totalRowCount: 1,
truncated: false,
results: [{
market: "kospi", source: "oracle", name: "삼성전자", code: "005930"
}]
};
assert.ok(workflow.normalizeStockMasterSearchResult(base, request));
assert.equal(workflow.normalizeStockMasterSearchResult({ ...base, truncated: true }, request), null);
assert.equal(workflow.normalizeStockMasterSearchResult({
...base,
results: [{ ...base.results[0], extra: true }]
}, request), null);
assert.equal(workflow.normalizeStockMasterSearchResult({
...base,
totalRowCount: 2,
results: [
base.results[0],
{ market: "kosdaq", source: "oracle", name: "삼성전자", code: "123456" }
]
}, request), null);
assert.equal(workflow.normalizeStockMasterSearchResult({
...base,
requestId: "stale"
}, request), null);
});
test("native partial pins the same contract and fail-closed write gates without a retry loop", () => {
for (const requestType of Object.values(workflow.bridgeContract.requests)) {
assert.match(nativeBridge, new RegExp(`"${requestType}"`));
@@ -120,6 +166,13 @@ test("native partial pins the same contract and fail-closed write gates without
assert.match(nativeBridge, /LatchOperatorCatalogWriteQuarantine/);
assert.match(nativeBridge, /OUTCOME_UNKNOWN/);
assert.match(nativeBridge, /OperatorCatalogMutationExecutor/);
assert.match(nativeBridge, /LegacyStockMasterIdentityValidationService/);
assert.match(nativeBridge,
/await validationBody\(requestToken\)[\s\S]*mutationDispatched = true;/s);
assert.match(stockMasterValidation, /STOCK_MASTER_VERIFY_KOSPI/);
assert.match(stockMasterValidation, /STOCK_MASTER_VERIFY_KOSDAQ/);
assert.match(stockMasterValidation, /STOCK_MASTER_VERIFY_NXT_KOSPI/);
assert.match(stockMasterValidation, /STOCK_MASTER_VERIFY_NXT_KOSDAQ/);
assert.doesNotMatch(nativeBridge, /MaximumRetryCount|Task\.Delay|while\s*\(/);
});
@@ -247,6 +300,23 @@ test("new theme drafts require a valid title before create and delete keeps full
});
});
test("existing theme edits preserve legacy three through eight digit codes", () => {
const edit = workflow.createThemeEditDraft(
{ ...krxSelection, themeCode: "007" },
{
...themePreview(),
selection: { ...themePreview().selection, themeCode: "007" }
});
edit.draft.themeTitle = "수정 테마";
assert.equal(
workflow.createThemeReplaceRequest("legacy-theme-replace", edit)
.expectedIdentity.themeCode,
"007");
assert.throws(() => workflow.createThemeCreateRequest(
"legacy-theme-create",
edit.draft), /eight-digit/i);
});
test("expert selection plus preview becomes editable and preserves buy amounts while reindexing", () => {
const edit = workflow.createExpertEditDraft(expertSelection, expertPreview());
assert.deepEqual(edit, {