feat: complete legacy parity and modernize operator UI

This commit is contained in:
2026-07-22 12:34:46 +09:00
parent fc4007d676
commit 939c252d23
149 changed files with 26515 additions and 1736 deletions

View File

@@ -146,6 +146,51 @@ public sealed class LegacyOverseasSelectionWorkflowTests
StringComparison.Ordinal);
}
[Fact]
public async Task DuplicateIndustryDisplayNamesRemainDistinctOpaqueSelections()
{
var workflow = CreateWorkflow(industries:
[
new OverseasIndustryIndexItem("Shared", "First Input", "NAS@ONE"),
new OverseasIndustryIndexItem("Shared", "Second Input", "NAS@TWO")
]);
var searched = await workflow.SearchIndustriesAsync(string.Empty);
Assert.Equal(2, searched.Industry.Results.Count);
Assert.Equal("Shared", searched.Industry.Results[0].KoreanName);
Assert.Equal("Shared", searched.Industry.Results[1].KoreanName);
Assert.NotEqual(
searched.Industry.Results[0].SelectionId,
searched.Industry.Results[1].SelectionId);
workflow.SelectIndustry(searched.Industry.Results[1].SelectionId);
var draft = workflow.MaterializePlaylistDraft("industry-current");
Assert.Equal("Second Input|NAS@TWO|US|0", draft.Selection.DataCode);
}
[Fact]
public async Task IsolatedStockRowsAreReportedWithoutRejectingValidSelections()
{
var stockResult = new WorldStockSearchResult(
string.Empty,
RetrievedAt,
[new WorldStockSearchItem("Apple", "NAS@AAPL", "US")],
IsTruncated: true,
IsolatedInvalidRowCount: 16);
var workflow = new LegacyOverseasSelectionWorkflow(
new RecordingIndustryService([]),
new QueueStockService(stockResult));
var snapshot = await workflow.SearchStocksAsync(string.Empty);
Assert.Equal(LegacyOverseasSearchStatus.Ready, snapshot.Stock.Status);
Assert.Single(snapshot.Stock.Results);
Assert.Equal(16, snapshot.Stock.IsolatedInvalidRowCount);
Assert.True(snapshot.Stock.IsTruncated);
}
[Fact]
public void FixedIndexActionsMaterializeExactAliasIdentityPageAndMovingAverages()
{
@@ -482,7 +527,7 @@ public sealed class LegacyOverseasSelectionWorkflowTests
await Assert.ThrowsAsync<ArgumentOutOfRangeException>(() =>
workflow.SearchIndustriesAsync("", 0));
await Assert.ThrowsAsync<ArgumentOutOfRangeException>(() =>
workflow.SearchStocksAsync("", 501));
workflow.SearchStocksAsync("", LegacyOverseasSelectionWorkflow.MaximumResults + 1));
await Assert.ThrowsAsync<ArgumentException>(() =>
workflow.SearchIndustriesAsync(new string('x', 65)));
await Assert.ThrowsAsync<ArgumentException>(() =>