feat: complete legacy parity and modernize operator UI
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace MBN_STOCK_WEBVIEW.LegacyWeb.Tests;
|
||||
|
||||
public sealed class LegacyExplicitModalExitContractTests
|
||||
{
|
||||
private static readonly string RepositoryRoot = FindRepositoryRoot();
|
||||
private static readonly string WebRoot = Path.Combine(
|
||||
RepositoryRoot,
|
||||
"src",
|
||||
"MBN_STOCK_WEBVIEW.LegacyParityApp",
|
||||
"Web");
|
||||
private static readonly string Markup = File.ReadAllText(Path.Combine(WebRoot, "index.html"));
|
||||
private static readonly string App = File.ReadAllText(Path.Combine(WebRoot, "app.js"));
|
||||
private static readonly string Styles = File.ReadAllText(Path.Combine(WebRoot, "styles.css"));
|
||||
private static readonly string ModalFocus = File.ReadAllText(
|
||||
Path.Combine(WebRoot, "legacy-modal-focus.js"));
|
||||
private static readonly string InputSmoke = File.ReadAllText(Path.Combine(
|
||||
RepositoryRoot,
|
||||
"scripts",
|
||||
"Test-LegacyPackageInput.mjs"));
|
||||
|
||||
[Theory]
|
||||
[InlineData(
|
||||
"manual-financial-workspace",
|
||||
"manual-financial-exit",
|
||||
"나가기")]
|
||||
[InlineData(
|
||||
"manual-list-workspace",
|
||||
"manual-list-cancel",
|
||||
"취소")]
|
||||
public void Original_text_exit_is_a_focusable_footer_button(
|
||||
string workspaceId,
|
||||
string buttonId,
|
||||
string label)
|
||||
{
|
||||
Assert.Matches(
|
||||
$"id=\"{workspaceId}\"[\\s\\S]*?<footer class=\"manual-dialog-footer\">" +
|
||||
$"\\s*<button id=\"{buttonId}\" type=\"button\">{label}</button>",
|
||||
Markup);
|
||||
Assert.DoesNotMatch(
|
||||
$"<button id=\"{buttonId}\"[^>]*(?:disabled|tabindex=\"-1\")",
|
||||
Markup);
|
||||
Assert.Contains("\"button\"", ModalFocus, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(
|
||||
"closeManualFinancial",
|
||||
"manualClose",
|
||||
"manualExit",
|
||||
"close-manual-financial")]
|
||||
[InlineData(
|
||||
"closeManualList",
|
||||
"manualListClose",
|
||||
"manualListCancel",
|
||||
"close-manual-list")]
|
||||
public void Text_and_top_exit_share_one_close_handler(
|
||||
string handler,
|
||||
string topButton,
|
||||
string textButton,
|
||||
string intent)
|
||||
{
|
||||
Assert.Contains($"function {handler}()", App, StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
$"{topButton}.addEventListener(\"click\", {handler})",
|
||||
App,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
$"{textButton}.addEventListener(\"click\", {handler})",
|
||||
App,
|
||||
StringComparison.Ordinal);
|
||||
|
||||
var handlerStart = App.IndexOf($"function {handler}()", StringComparison.Ordinal);
|
||||
var nextListener = App.IndexOf(
|
||||
$"{topButton}.addEventListener",
|
||||
handlerStart,
|
||||
StringComparison.Ordinal);
|
||||
Assert.True(handlerStart >= 0 && nextListener > handlerStart);
|
||||
var body = App[handlerStart..nextListener];
|
||||
Assert.Single(Regex.Matches(body, $"send\\(\"{intent}\"").Cast<Match>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Text_exit_lock_state_tracks_the_existing_top_exit()
|
||||
{
|
||||
Assert.Contains(
|
||||
"manualExit.disabled = manualClose.disabled;",
|
||||
App,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"manualListCancel.disabled = manualListClose.disabled;",
|
||||
App,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"root.querySelectorAll(\"button, input, select, textarea\")",
|
||||
App,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"setTransientControlsBusy(manualDialog, state.isBusy === true);",
|
||||
App,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"setTransientControlsBusy(manualListDialog, busy);",
|
||||
App,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Matches(
|
||||
@"\.manual-financial-dialog\s*\{[^}]*grid-template-rows:\s*46px minmax\(0, 1fr\) auto",
|
||||
Styles);
|
||||
Assert.Matches(
|
||||
@"\.manual-list-dialog\s*\{[^}]*grid-template-rows:\s*46px minmax\(0, 1fr\) auto",
|
||||
Styles);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Full_UI_input_validation_clicks_the_restored_text_exit_controls()
|
||||
{
|
||||
Assert.Matches(
|
||||
@"async function closeManualFinancial[\s\S]*?pointerClick\('document\.getElementById\(""manual-financial-exit""\)'",
|
||||
InputSmoke);
|
||||
Assert.Matches(
|
||||
@"async function closeManualList[\s\S]*?pointerClick\('document\.getElementById\(""manual-list-cancel""\)'",
|
||||
InputSmoke);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("overseasStocks", "해외시장")]
|
||||
[InlineData("tradingHalt", "거래정지")]
|
||||
public void Clear_sidebar_name_preserves_the_existing_tab_identity(
|
||||
string tabId,
|
||||
string displayName)
|
||||
{
|
||||
var match = Regex.Match(
|
||||
Markup,
|
||||
$"<button[^>]*data-tab-id=\"{tabId}\"[\\s\\S]*?</button>");
|
||||
Assert.True(match.Success);
|
||||
Assert.Contains($"aria-label=\"{displayName}\"", match.Value,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains($"title=\"{displayName}\"", match.Value,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains($">{displayName}</span>", match.Value,
|
||||
StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private static string FindRepositoryRoot()
|
||||
{
|
||||
var directory = new DirectoryInfo(AppContext.BaseDirectory);
|
||||
while (directory is not null)
|
||||
{
|
||||
if (File.Exists(Path.Combine(directory.FullName, "MBN_STOCK_WEBVIEW.sln")))
|
||||
{
|
||||
return directory.FullName;
|
||||
}
|
||||
|
||||
directory = directory.Parent;
|
||||
}
|
||||
|
||||
throw new DirectoryNotFoundException("Repository root was not found.");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user