Files
MBN_STOCK_WEBVIEW/tests/MBN_STOCK_WEBVIEW.LegacyApplication.Tests/LegacyOverseasOperatorControllerTests.cs

159 lines
6.8 KiB
C#

using MBN_STOCK_WEBVIEW.LegacyApplication;
using MMoneyCoderSharp.Data;
namespace MBN_STOCK_WEBVIEW.LegacyApplication.Tests;
public sealed class LegacyOverseasOperatorControllerTests
{
private static readonly DateTimeOffset RetrievedAt =
new(2026, 7, 15, 10, 0, 0, TimeSpan.FromHours(9));
[Fact]
public void OverseasSnapshotAndFixedIndexActionRemainControllerAuthoritative()
{
var controller = CreateController();
var selectedTab = controller.SelectTab(LegacyOperatorTabId.OverseasStocks);
Assert.NotNull(selectedTab.Overseas);
Assert.Equal(10, selectedTab.Overseas.FixedIndexTargets.Count);
Assert.Equal(12, selectedTab.Overseas.Actions.Count);
Assert.Equal(new LegacyMovingAverageSelection(true, true), selectedTab.MovingAverages);
Assert.Equal(
new LegacyOverseasMovingAverageSelection(true, true),
selectedTab.Overseas.MovingAverages);
controller.SelectOverseasFixedIndex("nasdaq");
controller.SetMovingAverages(ma5: false, ma20: true);
var state = controller.ActivateOverseasAction("index-candle-20d");
var row = Assert.Single(state.Playlist);
var entry = row.ToPlayoutEntry();
var selection = Assert.IsType<MBN_STOCK_WEBVIEW.Core.Playout.Scenes.LegacySceneSelection>(
entry.Selection);
Assert.Equal("legacy-overseas-00000001", row.RowId);
Assert.Equal("FOREIGN_INDEX", row.MarketText);
Assert.Equal("나스닥 캔들 20일", row.StockName);
Assert.Equal("MA20", row.GraphicType);
Assert.Equal("PRICE", row.Subtype);
Assert.Equal("1/1", row.PageText);
Assert.Equal("8040", entry.CutCode);
Assert.Equal("FOREIGN_INDEX", selection.GroupCode);
Assert.Equal("나스닥", selection.Subject);
Assert.Equal("NAS@IXIC|US|0", selection.DataCode);
}
[Fact]
public async Task OverseasIndustryAndStockSearchSelectionsMaterializeExactPlaylistRows()
{
var controller = CreateController(
industries: [new("반도체", "US Semiconductor", "NAS@SOX")],
stocks: [new("Apple", "NAS@AAPL", "US")]);
controller.SelectTab(LegacyOperatorTabId.OverseasStocks);
var industries = await controller.SearchOverseasIndustriesAsync("반도체");
var industryId = Assert.Single(industries.Overseas!.Industry.Results).SelectionId;
controller.SelectOverseasIndustry(industryId);
var industryState = controller.ActivateOverseasAction("industry-current");
var industryRow = Assert.Single(industryState.Playlist);
Assert.Equal("5001", industryRow.ToPlayoutEntry().CutCode);
Assert.Equal("FOREIGN_INDUSTRY", industryRow.PlayoutSelection!.GroupCode);
Assert.Equal("반도체", industryRow.PlayoutSelection.Subject);
Assert.Equal("1열판기본", industryRow.PlayoutSelection.GraphicType);
Assert.Equal("CURRENT", industryRow.PlayoutSelection.Subtype);
Assert.Equal("US Semiconductor|NAS@SOX|US|0", industryRow.PlayoutSelection.DataCode);
var stocks = await controller.SearchOverseasStocksAsync("apple");
var stockId = Assert.Single(stocks.Overseas!.Stock.Results).SelectionId;
controller.SelectOverseasStock(stockId);
var stockState = controller.ActivateOverseasAction("stock-candle-5d");
Assert.Equal(2, stockState.Playlist.Count);
var stockRow = stockState.Playlist[1];
Assert.Equal("8061", stockRow.ToPlayoutEntry().CutCode);
Assert.Equal("FOREIGN_STOCK", stockRow.PlayoutSelection!.GroupCode);
Assert.Equal("Apple", stockRow.PlayoutSelection.Subject);
Assert.Equal("MA5,MA20", stockRow.PlayoutSelection.GraphicType);
Assert.Equal("PRICE", stockRow.PlayoutSelection.Subtype);
Assert.Equal("NAS@AAPL|US|1", stockRow.PlayoutSelection.DataCode);
}
[Fact]
public async Task OverseasActionsRejectInactiveTabAndStaleSearchIds()
{
var controller = CreateController(
industries: [new("반도체", "US Semiconductor", "NAS@SOX")]);
var inactive = controller.SelectOverseasFixedIndex("nasdaq");
Assert.Equal(LegacyOperatorStatusKind.Error, inactive.StatusKind);
Assert.Null(inactive.Overseas);
controller.SelectTab(LegacyOperatorTabId.OverseasStocks);
var first = await controller.SearchOverseasIndustriesAsync("");
var staleId = Assert.Single(first.Overseas!.Industry.Results).SelectionId;
await controller.SearchOverseasIndustriesAsync("new generation");
var stale = controller.SelectOverseasIndustry(staleId);
Assert.Equal(LegacyOperatorStatusKind.Error, stale.StatusKind);
Assert.Null(stale.Overseas!.Industry.Selected);
}
private static LegacyOperatorController CreateController(
IReadOnlyList<OverseasIndustryIndexItem>? industries = null,
IReadOnlyList<WorldStockSearchItem>? stocks = null)
{
var workflow = new LegacyOverseasSelectionWorkflow(
new StaticIndustryService(industries ?? []),
new StaticStockService(stocks ?? []));
return new LegacyOperatorController(
new EmptyStockLookup(),
overseasWorkflow: workflow);
}
private sealed class EmptyStockLookup : ILegacyStockLookup
{
public Task<LegacyStockSearchData> SearchAsync(
string query,
CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
return Task.FromResult(new LegacyStockSearchData(query, [], []));
}
}
private sealed class StaticIndustryService(
IReadOnlyList<OverseasIndustryIndexItem> items) : IOverseasIndustryIndexSearchService
{
public Task<OverseasIndustryIndexSearchResult> SearchAsync(
string query,
int maximumResults = LegacyOverseasIndustryIndexSearchService.DefaultMaximumResults,
CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
return Task.FromResult(new OverseasIndustryIndexSearchResult(
query.Trim(),
RetrievedAt,
items,
IsTruncated: false));
}
}
private sealed class StaticStockService(
IReadOnlyList<WorldStockSearchItem> items) : IWorldStockSearchService
{
public Task<WorldStockSearchResult> SearchAsync(
string query,
int maximumResults = LegacyWorldStockSearchService.DefaultMaximumResults,
CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
return Task.FromResult(new WorldStockSearchResult(
query.Trim(),
RetrievedAt,
items,
IsTruncated: false));
}
}
}