feat: add configurable operator appearance and layout
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
namespace MBN_STOCK_WEBVIEW.LegacyWeb.Tests;
|
||||
|
||||
public sealed class LegacyOperatorFeedbackWebContractTests
|
||||
{
|
||||
private static readonly string App = File.ReadAllText(Path.Combine(
|
||||
FindRepositoryRoot(),
|
||||
"src",
|
||||
"MBN_STOCK_WEBVIEW.LegacyParityApp",
|
||||
"Web",
|
||||
"app.js"));
|
||||
|
||||
[Fact]
|
||||
public void StockSearchFeedbackStaysConciseAndUsesNativeState()
|
||||
{
|
||||
var feedback = Slice(
|
||||
App,
|
||||
"function renderStockSearchMeta(state)",
|
||||
"function pointerPosition(event)");
|
||||
|
||||
Assert.Contains("state.isBusy === true", feedback, StringComparison.Ordinal);
|
||||
Assert.Contains("label = \"검색 중\"", feedback, StringComparison.Ordinal);
|
||||
Assert.Contains("String(results.length) + \"건\"", feedback,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains("row.index === state.selectedStockIndex", feedback,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains("selected.displayName", feedback, StringComparison.Ordinal);
|
||||
Assert.Contains("stockSearchMeta.hidden = label.length === 0", feedback,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains("stockResults.dataset.emptyLabel = \"결과 없음\"", feedback,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains("delete stockResults.dataset.emptyLabel", feedback,
|
||||
StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptyCutFeedbackDistinguishesStockSelectionAndClearsWhenRowsReturn()
|
||||
{
|
||||
var cuts = Slice(App, "function renderCuts(state)", "cutList.addEventListener");
|
||||
|
||||
Assert.Contains("state.cutRows.length === 0", cuts, StringComparison.Ordinal);
|
||||
Assert.Contains("Number.isInteger(state.selectedStockIndex)", cuts,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains("? \"컷 없음\"", cuts, StringComparison.Ordinal);
|
||||
Assert.Contains(": \"종목을 선택하세요\"", cuts, StringComparison.Ordinal);
|
||||
Assert.Contains("delete cutList.dataset.emptyLabel", cuts,
|
||||
StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GlobalBusyFeedbackDoesNotMislabelEveryOperationAsSearch()
|
||||
{
|
||||
var render = Slice(App, "function render(state)",
|
||||
"Object.keys(operatorFolderControls)");
|
||||
|
||||
Assert.Contains("document.body.classList.toggle(\"busy\", isBusy)", render,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains("document.body.setAttribute(\"aria-busy\"", render,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains("renderStockResults(state);\n renderStockSearchMeta(state);", render,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains("isBusy ? \"처리 중\"", render, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("종목을 검색하고 있습니다.", render, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private static string Slice(string source, string startMarker, string endMarker)
|
||||
{
|
||||
var start = source.IndexOf(startMarker, StringComparison.Ordinal);
|
||||
Assert.True(start >= 0, $"Missing start marker: {startMarker}");
|
||||
var end = source.IndexOf(endMarker, start, StringComparison.Ordinal);
|
||||
Assert.True(end > start, $"Missing end marker: {endMarker}");
|
||||
return source[start..end];
|
||||
}
|
||||
|
||||
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 could not be located.");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user