Files
MBN_STOCK_WEBVIEW/tests/MBN_STOCK_WEBVIEW.LegacyApplication.Tests/Comparison/LegacyOperatorComparisonIntegrationTests.cs

206 lines
8.1 KiB
C#

using MBN_STOCK_WEBVIEW.Core.Playout.Scenes;
using MMoneyCoderSharp.Data;
namespace MBN_STOCK_WEBVIEW.LegacyApplication.Tests;
public sealed class LegacyOperatorComparisonIntegrationTests
{
[Fact]
public async Task ComparisonTabBuildsPairAndAddsAuthoritativeSceneRow()
{
var data = new StaticComparisonDataService();
var store = new MemoryComparisonPairStore();
var controller = new LegacyOperatorController(
new EmptyStockLookup(),
comparisonWorkflow: new LegacyComparisonWorkflowController(data, store));
var selected = await controller.SelectTabAsync(LegacyOperatorTabId.Comparison);
Assert.NotNull(selected.Comparison);
Assert.Empty(selected.Comparison.SavedPairs);
var searched = await controller.SearchComparisonDomesticAsync("반도체");
var results = searched.Comparison!.DomesticSearch.Results;
controller.ChooseComparisonDomesticResult(results[0].SelectionId);
controller.ChooseComparisonDomesticResult(results[1].SelectionId);
var saved = await controller.AddComparisonPairAsync();
Assert.Single(saved.Comparison!.SavedPairs);
Assert.Single(store.Writes);
var added = controller.ActivateComparisonAction("comparison-candle");
var row = Assert.Single(added.Playlist);
Assert.Equal("5026", row.ToPlayoutEntry().CutCode);
Assert.Equal(
"KOSPI:000660|KOSPI:005930",
Assert.IsType<LegacySceneSelection>(row.ToPlayoutEntry().Selection).DataCode);
Assert.Equal("비교", row.MarketText);
}
[Fact]
public async Task ComparisonParentDoubleClickAddsOnlyDirectChildrenInOriginalOrder()
{
var controller = new LegacyOperatorController(
new EmptyStockLookup(),
comparisonWorkflow: new LegacyComparisonWorkflowController(
new StaticComparisonDataService(),
new MemoryComparisonPairStore()));
await controller.SelectTabAsync(LegacyOperatorTabId.Comparison);
var searched = await controller.SearchComparisonDomesticAsync("반도체");
controller.ChooseComparisonDomesticResult(
searched.Comparison!.DomesticSearch.Results[0].SelectionId);
controller.ChooseComparisonDomesticResult(
searched.Comparison.DomesticSearch.Results[1].SelectionId);
await controller.AddComparisonPairAsync();
var added = controller.ActivateComparisonSection(1);
Assert.Collection(
added.Playlist,
row => Assert.Equal("5026", row.SceneAlias),
row => Assert.Equal("5087", row.SceneAlias));
}
private sealed class EmptyStockLookup : ILegacyStockLookup
{
public Task<LegacyStockSearchData> SearchAsync(
string query,
CancellationToken cancellationToken = default) => Task.FromResult(
new LegacyStockSearchData(query, [], []));
}
private sealed class StaticComparisonDataService : ILegacyComparisonDataService
{
private static readonly IReadOnlyList<LegacyComparisonTarget> Domestic =
[
LegacyComparisonTarget.CreateKrxStock(
LegacyComparisonDomesticMarket.Kospi,
"삼성전자",
"005930"),
LegacyComparisonTarget.CreateKrxStock(
LegacyComparisonDomesticMarket.Kospi,
"SK하이닉스",
"000660")
];
public Task<IReadOnlyList<LegacyComparisonTarget>> SearchDomesticAsync(
string query,
int maximumResults,
CancellationToken cancellationToken = default) => Task.FromResult(Domestic);
public Task<IReadOnlyList<LegacyComparisonTarget>> SearchWorldAsync(
string query,
int maximumResults,
CancellationToken cancellationToken = default) => Task.FromResult<
IReadOnlyList<LegacyComparisonTarget>>([]);
public Task<LegacyComparisonTarget?> ResolveStoredTargetAsync(
LegacyComparisonStoredTargetReference target,
CancellationToken cancellationToken = default) => Task.FromResult<
LegacyComparisonTarget?>(null);
}
private sealed class MemoryComparisonPairStore : ILegacyComparisonPairStore
{
public List<IReadOnlyList<LegacyComparisonPairWriteRow>> Writes { get; } = [];
public Task<byte[]?> ReadCp949Async(CancellationToken cancellationToken = default) =>
Task.FromResult<byte[]?>(null);
public Task WriteCp949Async(
IReadOnlyList<LegacyComparisonPairWriteRow> rows,
CancellationToken cancellationToken = default)
{
Writes.Add(rows.ToArray());
return Task.CompletedTask;
}
}
}
public sealed class LegacyComparisonProductionAdapterTests
{
[Fact]
public async Task DataAdapterMapsDomesticNxtAndWorldIdentities()
{
var lookup = new StaticStockLookup();
var world = new StaticWorldLookup();
var service = new LegacyComparisonDataService(lookup, world);
var domestic = await service.SearchDomesticAsync("삼성", 10);
Assert.Equal(LegacyComparisonTargetKind.KrxStock, domestic[0].Kind);
Assert.Equal(LegacyComparisonTargetKind.NxtStock, domestic[1].Kind);
Assert.Equal("삼성전자(NXT)", domestic[1].DisplayName);
var overseas = Assert.Single(await service.SearchWorldAsync("APPLE", 10));
Assert.Equal("world:US:AAPL", overseas.TargetId);
var resolved = await service.ResolveStoredTargetAsync(
new LegacyComparisonStoredTargetReference("APPLE", string.Empty));
Assert.Equal(overseas, resolved);
}
[Fact]
public async Task FileStoreRoundTripsStrictCp949WithAtomicTarget()
{
var directory = Path.Combine(
Path.GetTempPath(),
$"mbn-comparison-{Guid.NewGuid():N}");
var path = Path.Combine(directory, "종목비교.dat");
try
{
var store = new LegacyComparisonPairFileStore(path);
await store.WriteCp949Async(
[
new LegacyComparisonPairWriteRow(
1,
"삼성전자",
"코스피",
"SK하이닉스",
"코스피")
]);
var bytes = Assert.IsType<byte[]>(await store.ReadCp949Async());
var parsed = Assert.Single(LegacyComparisonFileParser.Parse(bytes));
Assert.Equal("삼성전자", parsed.First.Name);
Assert.Empty(Directory.EnumerateFiles(directory, "*.tmp"));
}
finally
{
if (Directory.Exists(directory))
{
Directory.Delete(directory, recursive: true);
}
}
}
private sealed class StaticStockLookup : ILegacyStockLookup
{
public Task<LegacyStockSearchData> SearchAsync(
string query,
CancellationToken cancellationToken = default) => Task.FromResult(
new LegacyStockSearchData(
query,
["삼성전자", "삼성전자(NXT)"],
[
new LegacyStockIdentity(
LegacyDomesticStockMarket.Kospi,
"삼성전자",
"005930"),
new LegacyStockIdentity(
LegacyDomesticStockMarket.NxtKospi,
"삼성전자(NXT)",
"005930")
]));
}
private sealed class StaticWorldLookup : IWorldStockSearchService
{
public Task<WorldStockSearchResult> SearchAsync(
string query,
int maximumResults = LegacyWorldStockSearchService.DefaultMaximumResults,
CancellationToken cancellationToken = default) => Task.FromResult(
new WorldStockSearchResult(
query.Trim(),
DateTimeOffset.UtcNow,
[new WorldStockSearchItem("APPLE", "AAPL", "US")],
false));
}
}