feat: complete legacy parity and modernize operator UI
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using MBN_STOCK_WEBVIEW.Core.Playout;
|
||||
using MBN_STOCK_WEBVIEW.Core.Playout.Scenes;
|
||||
|
||||
namespace MBN_STOCK_WEBVIEW.LegacyApplication.Tests;
|
||||
@@ -97,6 +98,90 @@ public sealed class LegacyManualListsWorkflowTests
|
||||
Assert.DoesNotContain("005930", draft.StockName, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VI_delete_all_requires_MmoneyCoder_confirmation_before_changing_the_draft()
|
||||
{
|
||||
var store = new FakeStore
|
||||
{
|
||||
Vi = new LegacyManualViStoreSnapshot(
|
||||
[new LegacyManualViStoredItem("P005930", "삼성전자")],
|
||||
new string('a', 64))
|
||||
};
|
||||
var lookup = new FakeLookup();
|
||||
var controller = new LegacyOperatorController(
|
||||
lookup,
|
||||
manualListsWorkflow: new LegacyManualListsWorkflow(store, lookup));
|
||||
await controller.OpenManualViAsync();
|
||||
|
||||
var requested = controller.DeleteAllManualViItems();
|
||||
|
||||
Assert.Equal("모두 삭제하겠습니까?", requested.Dialog?.Message);
|
||||
Assert.Equal("MmoneyCoder", requested.Dialog?.Caption);
|
||||
Assert.True(requested.Dialog?.IsConfirmation);
|
||||
Assert.Single(requested.ManualLists!.ViItems);
|
||||
|
||||
var canceled = controller.CancelDialog();
|
||||
Assert.Null(canceled.Dialog);
|
||||
Assert.Single(canceled.ManualLists!.ViItems);
|
||||
|
||||
controller.DeleteAllManualViItems();
|
||||
var confirmed = await controller.ConfirmDialogAsync();
|
||||
|
||||
Assert.Null(confirmed.Dialog);
|
||||
Assert.Empty(confirmed.ManualLists!.ViItems);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VI_blank_search_loads_the_complete_lookup_generation()
|
||||
{
|
||||
var store = new FakeStore();
|
||||
var lookup = new FakeLookup
|
||||
{
|
||||
DisplayNames = ["삼성전자", "카카오"],
|
||||
MasterCatalog =
|
||||
[
|
||||
new LegacyStockIdentity(
|
||||
LegacyDomesticStockMarket.Kospi,
|
||||
"삼성전자",
|
||||
"005930"),
|
||||
new LegacyStockIdentity(
|
||||
LegacyDomesticStockMarket.Kosdaq,
|
||||
"카카오",
|
||||
"035720")
|
||||
]
|
||||
};
|
||||
var workflow = new LegacyManualListsWorkflow(store, lookup);
|
||||
await workflow.OpenViAsync();
|
||||
|
||||
var searched = await workflow.SearchViAsync(" ");
|
||||
|
||||
Assert.Equal(string.Empty, lookup.LastQuery);
|
||||
Assert.Equal(2, searched.SearchResults.Count);
|
||||
Assert.False(searched.SearchIsTruncated);
|
||||
Assert.Equal(LegacyOperatorStatusKind.Information, searched.StatusKind);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VI_search_keeps_a_finite_ten_thousand_row_ui_boundary_and_warns()
|
||||
{
|
||||
var store = new FakeStore();
|
||||
var lookup = new FakeLookup
|
||||
{
|
||||
DisplayNames = Enumerable.Repeat(
|
||||
"삼성전자",
|
||||
LegacyManualListsWorkflow.MaximumSearchResults + 1).ToArray()
|
||||
};
|
||||
var workflow = new LegacyManualListsWorkflow(store, lookup);
|
||||
await workflow.OpenViAsync();
|
||||
|
||||
var searched = await workflow.SearchViAsync(string.Empty);
|
||||
|
||||
Assert.Equal(10_000, searched.SearchResults.Count);
|
||||
Assert.True(searched.SearchIsTruncated);
|
||||
Assert.Equal(LegacyOperatorStatusKind.Warning, searched.StatusKind);
|
||||
Assert.Contains("10,000", searched.StatusMessage, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VI_stale_preflight_never_writes_or_retries()
|
||||
{
|
||||
@@ -295,7 +380,7 @@ public sealed class LegacyManualListsWorkflowTests
|
||||
Assert.Equal(section.Actions.Count, completed.Playlist.Count);
|
||||
Assert.Equal(
|
||||
section.Actions.Select(action => action.Label),
|
||||
completed.Playlist.Select(row => row.StockName));
|
||||
completed.Playlist.Select(row => row.RawCutLabel));
|
||||
Assert.Equal(
|
||||
new[] { "INDIVIDUAL", "FOREIGN", "INSTITUTION" },
|
||||
completed.Playlist.TakeLast(3).Select(row => row.PlayoutSelection!.GroupCode));
|
||||
@@ -359,9 +444,11 @@ public sealed class LegacyManualListsWorkflowTests
|
||||
{
|
||||
var store = new FakeStore();
|
||||
var lookup = new FakeLookup();
|
||||
var pagePlans = new FiveRowPagePlanProvider();
|
||||
var controller = new LegacyOperatorController(
|
||||
lookup,
|
||||
manualListsWorkflow: new LegacyManualListsWorkflow(store, lookup));
|
||||
manualListsWorkflow: new LegacyManualListsWorkflow(store, lookup),
|
||||
fixedPagePlanProvider: pagePlans);
|
||||
await controller.SelectTabAsync(LegacyOperatorTabId.Index);
|
||||
var section = LegacyFixedActionCatalog.Default
|
||||
.GetSections(LegacyFixedMarket.Index)[7];
|
||||
@@ -377,12 +464,16 @@ public sealed class LegacyManualListsWorkflowTests
|
||||
Assert.Equal(section.Actions.Count, completed.Playlist.Count);
|
||||
Assert.Equal(
|
||||
section.Actions.Take(manualIndex).Select(action => action.Label),
|
||||
completed.Playlist.Take(manualIndex).Select(row => row.StockName));
|
||||
completed.Playlist.Take(manualIndex).Select(row => row.RawCutLabel));
|
||||
Assert.Equal(
|
||||
section.Actions.Skip(manualIndex + 1).Select(action => action.Label),
|
||||
completed.Playlist.Skip(manualIndex + 1).Select(row => row.StockName));
|
||||
completed.Playlist.Skip(manualIndex + 1).Select(row => row.RawCutLabel));
|
||||
Assert.Equal("5074", completed.Playlist[manualIndex].SceneAlias);
|
||||
Assert.Equal("PAGED_VI", completed.Playlist[manualIndex].PlayoutSelection!.GroupCode);
|
||||
Assert.All(
|
||||
completed.Playlist.Where((_, index) => index != manualIndex),
|
||||
row => Assert.Equal("1/3", row.PageText));
|
||||
Assert.Equal(section.Actions.Count - 1, pagePlans.CallCount);
|
||||
Assert.Equal(1, store.WriteViCalls);
|
||||
}
|
||||
|
||||
@@ -414,18 +505,51 @@ public sealed class LegacyManualListsWorkflowTests
|
||||
Assert.Empty(switchedTab.Playlist);
|
||||
}
|
||||
|
||||
private sealed class FiveRowPagePlanProvider : ILegacyScenePagePlanProvider
|
||||
{
|
||||
public int CallCount { get; private set; }
|
||||
|
||||
public Task<LegacyScenePagePlan> CreatePagePlanAsync(
|
||||
LegacyPlaylistEntry entry,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
CallCount++;
|
||||
Assert.Equal("5074", entry.CutCode);
|
||||
return Task.FromResult(new LegacyScenePagePlan(
|
||||
"s5074",
|
||||
11,
|
||||
ScenePageSize.Five,
|
||||
3,
|
||||
11,
|
||||
false));
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class FakeLookup : ILegacyStockLookup
|
||||
{
|
||||
public IReadOnlyList<string> DisplayNames { get; init; } = ["삼성전자"];
|
||||
|
||||
public IReadOnlyList<LegacyStockIdentity> MasterCatalog { get; init; } =
|
||||
[
|
||||
new LegacyStockIdentity(
|
||||
LegacyDomesticStockMarket.Kospi,
|
||||
"삼성전자",
|
||||
"005930")
|
||||
];
|
||||
|
||||
public string? LastQuery { get; private set; }
|
||||
|
||||
public Task<LegacyStockSearchData> SearchAsync(
|
||||
string query,
|
||||
CancellationToken cancellationToken = default) =>
|
||||
Task.FromResult(new LegacyStockSearchData(
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
LastQuery = query;
|
||||
return Task.FromResult(new LegacyStockSearchData(
|
||||
query,
|
||||
["삼성전자"],
|
||||
[new LegacyStockIdentity(
|
||||
LegacyDomesticStockMarket.Kospi,
|
||||
"삼성전자",
|
||||
"005930")]));
|
||||
DisplayNames,
|
||||
MasterCatalog));
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class FakeStore : ILegacyManualListStore
|
||||
|
||||
Reference in New Issue
Block a user