namespace MBN_STOCK_WEBVIEW.LegacyWeb.Tests; public sealed class LegacyOverseasParityWebTests { private static readonly string RepositoryRoot = FindRepositoryRoot(); private static readonly string WebRoot = Path.Combine( RepositoryRoot, "src", "MBN_STOCK_WEBVIEW.LegacyParityApp", "Web"); private static readonly string App = File.ReadAllText(Path.Combine(WebRoot, "app.js")); private static readonly string Styles = File.ReadAllText(Path.Combine(WebRoot, "styles.css")); [Fact] public void OverseasTabUsesTheOriginalThreeVerticalGroups() { var render = Section("function renderOverseas(state)", "function renderComparison(state)"); Assert.Contains("overseas-fixed-group", render, StringComparison.Ordinal); Assert.Contains("overseas-search-group", render, StringComparison.Ordinal); Assert.Contains("\uD574\uC678\uC9C0\uC218", render, StringComparison.Ordinal); Assert.Contains("\uD574\uC678 \uC5C5\uC885\uC9C0\uC218", render, StringComparison.Ordinal); Assert.Contains("\uD574\uC678 \uC885\uBAA9", render, StringComparison.Ordinal); Assert.Contains("\uC5C5\uC885 \uAC80\uC0C9", render, StringComparison.Ordinal); Assert.Contains("\uC885\uBAA9 \uAC80\uC0C9", render, StringComparison.Ordinal); Assert.Contains("\u0031\uC5F4\uD310", render, StringComparison.Ordinal); Assert.Contains("periodButtons(\"fixedIndex\")", render, StringComparison.Ordinal); Assert.Contains("periodButtons(kind)", render, StringComparison.Ordinal); Assert.Contains("model.isTruncated === true", render, StringComparison.Ordinal); Assert.Contains("검색 결과가 최대 500건으로 제한되었습니다.", render, StringComparison.Ordinal); Assert.Contains("overseas-truncation", Styles, StringComparison.Ordinal); Assert.DoesNotContain("overseas-action-panel", render, StringComparison.Ordinal); Assert.DoesNotContain("overseas-selected", render, StringComparison.Ordinal); Assert.DoesNotContain("overseas-note", render, StringComparison.Ordinal); Assert.DoesNotContain("document.createElement(\"details\")", render, StringComparison.Ordinal); foreach (var selector in new[] { ".overseas-workspace", ".overseas-fixed-body", ".overseas-period-actions", ".overseas-result-area", ".overseas-results" }) { Assert.Contains(selector, Styles, StringComparison.Ordinal); } } [Fact] public void OverseasRowsSelectImmediatelyAndOnlyDispatchOpaqueNativeIdentifiers() { var render = Section("function renderOverseas(state)", "function renderComparison(state)"); var click = Section( "categoryTree.addEventListener(\"click\"", "categoryTree.addEventListener(\"change\""); var overseasClick = click[click.IndexOf( "const overseasTarget = event.target.closest(\"button[data-overseas-target-id]\");", StringComparison.Ordinal)..click.IndexOf("const comparisonChoice", StringComparison.Ordinal)]; var updater = Section("function updateOverseasWorkspace", "function markOverseasRowSelected"); Assert.Contains("function selectOverseasRow(row)", App, StringComparison.Ordinal); Assert.Contains("markOverseasRowSelected(row);", App, StringComparison.Ordinal); Assert.Contains("selectOverseasRow(overseasTarget);", overseasClick, StringComparison.Ordinal); Assert.Contains("selectOverseasRow(overseasResult);", overseasClick, StringComparison.Ordinal); Assert.DoesNotContain("setTimeout", overseasClick, StringComparison.Ordinal); Assert.Contains("existingWorkspace && structureKey === overseasRenderStructureKey", render, StringComparison.Ordinal); Assert.Contains("updateOverseasWorkspace(existingWorkspace, overseas", render, StringComparison.Ordinal); Assert.DoesNotContain("categoryTree.replaceChildren", updater, StringComparison.Ordinal); foreach (var intent in new[] { "select-overseas-fixed-index", "search-overseas-industries", "search-overseas-stocks", "select-overseas-industry", "select-overseas-stock", "activate-overseas-action" }) { Assert.Contains($"\"{intent}\"", App, StringComparison.Ordinal); } Assert.DoesNotContain("nationCode", render, StringComparison.Ordinal); Assert.DoesNotContain("FOREIGN_", render, StringComparison.Ordinal); Assert.DoesNotContain("symbol", render, StringComparison.OrdinalIgnoreCase); Assert.Contains("event.key === \"Enter\"", App, StringComparison.Ordinal); } [Fact] public void OverseasListsUseOneTabStopAndNativeSingleSelectionKeyboardSemantics() { var helper = Section("function moveOverseasListSelection", "function renderOverseas(state)"); var keyDown = Section( "categoryTree.addEventListener(\"keydown\"", "window.addEventListener(\"pointerup\""); Assert.Contains("list.getAttribute(\"aria-disabled\") === \"true\"", helper, StringComparison.Ordinal); Assert.Contains("list.querySelectorAll(\"button\")", helper, StringComparison.Ordinal); Assert.Contains("selectOverseasRow(nextRow);", helper, StringComparison.Ordinal); Assert.Contains("nextRow.scrollIntoView({ block: \"nearest\", inline: \"nearest\" });", helper, StringComparison.Ordinal); Assert.Contains("const overseasList = event.target.closest(\"[data-overseas-list]\");", keyDown, StringComparison.Ordinal); Assert.Contains("event.stopPropagation();", keyDown, StringComparison.Ordinal); Assert.Contains("moveOverseasListSelection(overseasList, event.key);", keyDown, StringComparison.Ordinal); Assert.Contains("button.tabIndex = -1;", App, StringComparison.Ordinal); Assert.Contains("fixedList.tabIndex = 0;", App, StringComparison.Ordinal); Assert.Contains("list.tabIndex = 0;", App, StringComparison.Ordinal); } private static string Section(string startToken, string endToken) { var start = App.IndexOf(startToken, StringComparison.Ordinal); var end = App.IndexOf(endToken, start + startToken.Length, StringComparison.Ordinal); Assert.True(start >= 0 && end > start, $"Unable to locate {startToken} section."); return App[start..end]; } private static string FindRepositoryRoot() { var current = new DirectoryInfo(AppContext.BaseDirectory); while (current is not null) { if (Directory.Exists(Path.Combine(current.FullName, "src")) && Directory.Exists(Path.Combine(current.FullName, "tests"))) { return current.FullName; } current = current.Parent; } throw new DirectoryNotFoundException("Repository root was not found."); } }