556 lines
23 KiB
C#
556 lines
23 KiB
C#
using MMoneyCoderSharp.Data;
|
|
|
|
namespace MBN_STOCK_WEBVIEW.LegacyApplication.Tests;
|
|
|
|
public sealed class LegacyTabActivationParityTests
|
|
{
|
|
[Fact]
|
|
public async Task ThemeEachActivation_LoadsOriginalEmptyQueryOncePerActivation()
|
|
{
|
|
// Original evidence: Control/UC4.cs UC4_Load starts timer1 and its first
|
|
// timer1_Tick calls GetThemeByKeyword with the initially empty txts value.
|
|
var service = new CountingThemeService();
|
|
var controller = new LegacyOperatorController(
|
|
Lookup(),
|
|
themeWorkflow: new LegacyThemeWorkflow(service));
|
|
|
|
var first = await controller.SelectTabAsync(LegacyOperatorTabId.Theme);
|
|
Assert.Equal(string.Empty, service.Queries.Single());
|
|
var firstResultId = Assert.Single(first.Theme!.SearchResults).ResultId;
|
|
controller.SetThemeSort("GAIN_DESC");
|
|
var selected = await controller.SelectThemeAsync(firstResultId);
|
|
Assert.Equal(LegacyThemeSort.GainRateDescending, selected.Theme!.Sort);
|
|
Assert.NotNull(selected.Theme.SelectedTheme);
|
|
|
|
await controller.SelectTabAsync(LegacyOperatorTabId.Theme);
|
|
Assert.Single(service.Queries);
|
|
|
|
await controller.SelectTabAsync(LegacyOperatorTabId.Index);
|
|
var second = await controller.SelectTabAsync(LegacyOperatorTabId.Theme);
|
|
|
|
Assert.Collection(
|
|
service.Queries,
|
|
query => Assert.Equal(string.Empty, query),
|
|
query => Assert.Equal(string.Empty, query));
|
|
Assert.Single(second.Theme!.SearchResults);
|
|
Assert.Equal(LegacyThemeSort.InputOrder, second.Theme.Sort);
|
|
Assert.Null(second.Theme.SelectedResultId);
|
|
Assert.Null(second.Theme.SelectedTheme);
|
|
Assert.Empty(second.Theme.PreviewItems);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ExpertEachActivation_LoadsOriginalFullListOncePerActivation()
|
|
{
|
|
// Original evidence: Control/UC6.cs UC6_Load calls Data_Load, whose query
|
|
// reads the complete EXPERT_LIST without a filter.
|
|
var service = new CountingExpertService();
|
|
var controller = new LegacyOperatorController(
|
|
Lookup(),
|
|
expertWorkflow: new LegacyExpertWorkflowController(service));
|
|
|
|
var first = await controller.SelectTabAsync(LegacyOperatorTabId.Expert);
|
|
Assert.Equal(string.Empty, service.Queries.Single());
|
|
Assert.Single(first.Expert!.Search.Results);
|
|
|
|
await controller.SelectTabAsync(LegacyOperatorTabId.Expert);
|
|
Assert.Single(service.Queries);
|
|
|
|
await controller.SelectTabAsync(LegacyOperatorTabId.Index);
|
|
var second = await controller.SelectTabAsync(LegacyOperatorTabId.Expert);
|
|
|
|
Assert.Collection(
|
|
service.Queries,
|
|
query => Assert.Equal(string.Empty, query),
|
|
query => Assert.Equal(string.Empty, query));
|
|
Assert.Single(second.Expert!.Search.Results);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task DragSwapThatActivatesTheme_UsesTheSameNativeInitialLoad()
|
|
{
|
|
var service = new CountingThemeService();
|
|
var controller = new LegacyOperatorController(
|
|
Lookup(),
|
|
themeWorkflow: new LegacyThemeWorkflow(service));
|
|
|
|
var state = await controller.SwapTabsAsync(
|
|
LegacyOperatorTabId.Theme,
|
|
LegacyOperatorTabId.Exchange);
|
|
|
|
Assert.Equal(string.Empty, service.Queries.Single());
|
|
Assert.Single(state.Theme!.SearchResults);
|
|
Assert.Equal(
|
|
LegacyOperatorTabId.Theme,
|
|
Assert.Single(state.Tabs!, tab => tab.IsActive).Id);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SupersededThemeActivation_DoesNotCommitAndRetriesWhenNeeded()
|
|
{
|
|
var service = new DelayedThemeService();
|
|
var controller = new LegacyOperatorController(
|
|
Lookup(),
|
|
themeWorkflow: new LegacyThemeWorkflow(service));
|
|
|
|
var firstActivation = controller.SelectTabAsync(LegacyOperatorTabId.Theme);
|
|
await service.FirstRequestStarted.Task.WaitAsync(TimeSpan.FromSeconds(5));
|
|
|
|
controller.SelectTab(LegacyOperatorTabId.Index);
|
|
service.ReleaseFirstRequest.TrySetResult();
|
|
var superseded = await firstActivation;
|
|
|
|
Assert.Equal(
|
|
LegacyOperatorTabId.Index,
|
|
Assert.Single(superseded.Tabs!, tab => tab.IsActive).Id);
|
|
|
|
var retried = await controller.SelectTabAsync(LegacyOperatorTabId.Theme);
|
|
Assert.Equal(2, service.CallCount);
|
|
Assert.Single(retried.Theme!.SearchResults);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(LegacyOperatorTabId.KospiIndustry, IndustryMarket.Kospi)]
|
|
[InlineData(LegacyOperatorTabId.KosdaqIndustry, IndustryMarket.Kosdaq)]
|
|
public async Task IndustryEachActivation_ReloadsAndClearsUc2Selections(
|
|
LegacyOperatorTabId tabId,
|
|
IndustryMarket market)
|
|
{
|
|
var service = new CountingIndustryService();
|
|
var controller = new LegacyOperatorController(
|
|
Lookup(),
|
|
industryWorkflow: new LegacyIndustrySelectionWorkflow(service));
|
|
|
|
await controller.SelectTabAsync(tabId);
|
|
controller.SelectIndustry(0, doubleClick: true);
|
|
var selected = controller.SelectIndustry(1, doubleClick: true);
|
|
Assert.NotNull(selected.Industry!.SelectedIndustry);
|
|
Assert.NotNull(selected.Industry.FirstIndustry);
|
|
Assert.NotNull(selected.Industry.SecondIndustry);
|
|
|
|
await controller.SelectTabAsync(tabId);
|
|
Assert.Single(service.Markets);
|
|
|
|
await controller.SelectTabAsync(LegacyOperatorTabId.Index);
|
|
var reentered = await controller.SelectTabAsync(tabId);
|
|
|
|
Assert.Equal([market, market], service.Markets);
|
|
Assert.Equal(2, reentered.Industry!.Industries.Count);
|
|
Assert.Null(reentered.Industry.SelectedIndex);
|
|
Assert.Null(reentered.Industry.SelectedIndustry);
|
|
Assert.Null(reentered.Industry.FirstIndustry);
|
|
Assert.Null(reentered.Industry.SecondIndustry);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ComparisonEachActivation_ReloadsPairsAndClearsUc3DraftAndSearch()
|
|
{
|
|
var store = new CountingComparisonPairStore();
|
|
var controller = new LegacyOperatorController(
|
|
Lookup(),
|
|
comparisonWorkflow: new LegacyComparisonWorkflowController(
|
|
new StaticComparisonDataService(),
|
|
store));
|
|
|
|
await controller.SelectTabAsync(LegacyOperatorTabId.Comparison);
|
|
var searched = await controller.SearchComparisonDomesticAsync("semiconductor");
|
|
var results = searched.Comparison!.DomesticSearch.Results;
|
|
controller.ChooseComparisonDomesticResult(results[0].SelectionId);
|
|
var drafted = controller.ChooseComparisonDomesticResult(results[1].SelectionId);
|
|
Assert.NotNull(drafted.Comparison!.FirstTarget);
|
|
Assert.NotNull(drafted.Comparison.SecondTarget);
|
|
|
|
await controller.SelectTabAsync(LegacyOperatorTabId.Comparison);
|
|
Assert.Equal(1, store.ReadCount);
|
|
|
|
await controller.SelectTabAsync(LegacyOperatorTabId.Index);
|
|
var reentered = await controller.SelectTabAsync(LegacyOperatorTabId.Comparison);
|
|
|
|
Assert.Equal(2, store.ReadCount);
|
|
Assert.Equal(LegacyComparisonSearchStatus.Idle, reentered.Comparison!.DomesticSearch.Status);
|
|
Assert.Empty(reentered.Comparison.DomesticSearch.Results);
|
|
Assert.Equal(string.Empty, reentered.Comparison.DomesticSearch.Query);
|
|
Assert.Null(reentered.Comparison.FirstTarget);
|
|
Assert.Null(reentered.Comparison.SecondTarget);
|
|
Assert.Empty(reentered.Comparison.SavedPairs);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ComparisonReentry_InvalidatesPairLoadFromDiscardedUc3()
|
|
{
|
|
var store = new DelayedComparisonPairStore();
|
|
var controller = new LegacyOperatorController(
|
|
Lookup(),
|
|
comparisonWorkflow: new LegacyComparisonWorkflowController(
|
|
new StaticComparisonDataService(),
|
|
store));
|
|
|
|
var firstActivation = controller.SelectTabAsync(LegacyOperatorTabId.Comparison);
|
|
await store.FirstReadStarted.Task.WaitAsync(TimeSpan.FromSeconds(5));
|
|
controller.SelectTab(LegacyOperatorTabId.Index);
|
|
controller.SelectTab(LegacyOperatorTabId.Comparison);
|
|
store.ReleaseFirstRead.TrySetResult();
|
|
await firstActivation;
|
|
|
|
Assert.Equal(LegacyOperatorStatusKind.Neutral, controller.Current.Comparison!.StatusKind);
|
|
Assert.Equal(string.Empty, controller.Current.Comparison.StatusMessage);
|
|
Assert.Empty(controller.Current.Comparison.SavedPairs);
|
|
|
|
var reloaded = await controller.SelectTabAsync(LegacyOperatorTabId.Comparison);
|
|
Assert.Equal(2, store.ReadCount);
|
|
Assert.Equal(LegacyOperatorStatusKind.Information, reloaded.Comparison!.StatusKind);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task OverseasStocksReentry_ResetsUc5StateAndKeepsMainMovingAverages()
|
|
{
|
|
var workflow = new LegacyOverseasSelectionWorkflow(
|
|
new StaticOverseasIndustryService(),
|
|
new StaticOverseasStockService());
|
|
var controller = new LegacyOperatorController(Lookup(), overseasWorkflow: workflow);
|
|
controller.SelectTab(LegacyOperatorTabId.OverseasStocks);
|
|
controller.SelectOverseasFixedIndex("nasdaq");
|
|
var industries = await controller.SearchOverseasIndustriesAsync("industry");
|
|
controller.SelectOverseasIndustry(
|
|
Assert.Single(industries.Overseas!.Industry.Results).SelectionId);
|
|
var stocks = await controller.SearchOverseasStocksAsync("stock");
|
|
controller.SelectOverseasStock(
|
|
Assert.Single(stocks.Overseas!.Stock.Results).SelectionId);
|
|
controller.SetMovingAverages(ma5: false, ma20: true);
|
|
|
|
controller.SelectTab(LegacyOperatorTabId.Index);
|
|
var reentered = controller.SelectTab(LegacyOperatorTabId.OverseasStocks);
|
|
|
|
Assert.Equal("dow-jones", reentered.Overseas!.SelectedFixedIndex?.TargetId);
|
|
Assert.Equal(LegacyOverseasSearchStatus.Idle, reentered.Overseas.Industry.Status);
|
|
Assert.Equal(string.Empty, reentered.Overseas.Industry.Query);
|
|
Assert.Empty(reentered.Overseas.Industry.Results);
|
|
Assert.Null(reentered.Overseas.Industry.Selected);
|
|
Assert.Equal(LegacyOverseasSearchStatus.Idle, reentered.Overseas.Stock.Status);
|
|
Assert.Equal(string.Empty, reentered.Overseas.Stock.Query);
|
|
Assert.Empty(reentered.Overseas.Stock.Results);
|
|
Assert.Null(reentered.Overseas.Stock.Selected);
|
|
Assert.Equal(
|
|
new LegacyOverseasMovingAverageSelection(false, true),
|
|
reentered.Overseas.MovingAverages);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task TradingHaltReentry_ResetsUc7QuerySelectionAndSort()
|
|
{
|
|
var controller = new LegacyOperatorController(
|
|
Lookup(),
|
|
tradingHaltWorkflow: new LegacyTradingHaltWorkflowController(
|
|
new StaticTradingHaltService()));
|
|
controller.SelectTab(LegacyOperatorTabId.TradingHalt);
|
|
var searched = await controller.SearchTradingHaltsAsync("halted");
|
|
controller.SelectTradingHalt(
|
|
Assert.Single(searched.TradingHalt!.Results).SelectionId);
|
|
controller.ToggleTradingHaltSort();
|
|
controller.SetMovingAverages(ma5: false, ma20: true);
|
|
|
|
controller.SelectTab(LegacyOperatorTabId.Index);
|
|
var reentered = controller.SelectTab(LegacyOperatorTabId.TradingHalt);
|
|
|
|
Assert.Equal(LegacyTradingHaltRequestStatus.Idle, reentered.TradingHalt!.Status);
|
|
Assert.Equal(string.Empty, reentered.TradingHalt.Query);
|
|
Assert.Empty(reentered.TradingHalt.Results);
|
|
Assert.Null(reentered.TradingHalt.Selected);
|
|
Assert.Equal(LegacyTradingHaltNameSort.None, reentered.TradingHalt.NameSort);
|
|
Assert.False(reentered.TradingHalt.Ma5);
|
|
Assert.True(reentered.TradingHalt.Ma20);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task OverseasReentry_InvalidatesSearchCompletionFromDiscardedUc5()
|
|
{
|
|
var service = new DelayedOverseasIndustryService();
|
|
var controller = new LegacyOperatorController(
|
|
Lookup(),
|
|
overseasWorkflow: new LegacyOverseasSelectionWorkflow(
|
|
service,
|
|
new StaticOverseasStockService()));
|
|
controller.SelectTab(LegacyOperatorTabId.OverseasStocks);
|
|
|
|
var pending = controller.SearchOverseasIndustriesAsync("old");
|
|
await service.RequestStarted.Task.WaitAsync(TimeSpan.FromSeconds(5));
|
|
controller.SelectTab(LegacyOperatorTabId.Index);
|
|
controller.SelectTab(LegacyOperatorTabId.OverseasStocks);
|
|
service.ReleaseRequest.TrySetResult();
|
|
await pending;
|
|
|
|
Assert.Equal(LegacyOverseasSearchStatus.Idle, controller.Current.Overseas!.Industry.Status);
|
|
Assert.Equal(string.Empty, controller.Current.Overseas.Industry.Query);
|
|
Assert.Empty(controller.Current.Overseas.Industry.Results);
|
|
}
|
|
|
|
private static ILegacyStockLookup Lookup() =>
|
|
new StaticLookup(new LegacyStockSearchData(string.Empty, [], []));
|
|
|
|
private sealed class StaticLookup : ILegacyStockLookup
|
|
{
|
|
private readonly LegacyStockSearchData _data;
|
|
|
|
public StaticLookup(LegacyStockSearchData data)
|
|
{
|
|
_data = data;
|
|
}
|
|
|
|
public Task<LegacyStockSearchData> SearchAsync(
|
|
string text,
|
|
CancellationToken cancellationToken = default) => Task.FromResult(_data);
|
|
}
|
|
|
|
private sealed class CountingThemeService : IThemeSelectionService
|
|
{
|
|
private static readonly ThemeSelectionIdentity Identity = new(
|
|
ThemeMarket.Krx,
|
|
ThemeSession.NotApplicable,
|
|
"00000001",
|
|
"Theme A");
|
|
|
|
public List<string> Queries { get; } = [];
|
|
|
|
public Task<ThemeSearchResult> SearchAsync(
|
|
string query,
|
|
ThemeSession nxtSession,
|
|
int maximumResults = LegacyThemeSelectionService.DefaultMaximumResults,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
Queries.Add(query);
|
|
return Task.FromResult(CreateThemeResult(query, nxtSession));
|
|
}
|
|
|
|
public Task<ThemePreviewResult> PreviewAsync(
|
|
ThemeSelectionIdentity identity,
|
|
int maximumItems = LegacyThemeSelectionService.DefaultMaximumPreviewItems,
|
|
CancellationToken cancellationToken = default) => Task.FromResult(
|
|
new ThemePreviewResult(identity, DateTimeOffset.UtcNow, [], false));
|
|
|
|
public static ThemeSearchResult CreateThemeResult(
|
|
string query,
|
|
ThemeSession nxtSession) => new(
|
|
query,
|
|
nxtSession,
|
|
DateTimeOffset.UtcNow,
|
|
[new ThemeSelectorItem(Identity, DataSourceKind.Oracle)],
|
|
false);
|
|
}
|
|
|
|
private sealed class DelayedThemeService : IThemeSelectionService
|
|
{
|
|
private int _callCount;
|
|
|
|
public TaskCompletionSource FirstRequestStarted { get; } = new(
|
|
TaskCreationOptions.RunContinuationsAsynchronously);
|
|
|
|
public TaskCompletionSource ReleaseFirstRequest { get; } = new(
|
|
TaskCreationOptions.RunContinuationsAsynchronously);
|
|
|
|
public int CallCount => Volatile.Read(ref _callCount);
|
|
|
|
public async Task<ThemeSearchResult> SearchAsync(
|
|
string query,
|
|
ThemeSession nxtSession,
|
|
int maximumResults = LegacyThemeSelectionService.DefaultMaximumResults,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
if (Interlocked.Increment(ref _callCount) == 1)
|
|
{
|
|
FirstRequestStarted.TrySetResult();
|
|
await ReleaseFirstRequest.Task.WaitAsync(cancellationToken);
|
|
}
|
|
|
|
return CountingThemeService.CreateThemeResult(query, nxtSession);
|
|
}
|
|
|
|
public Task<ThemePreviewResult> PreviewAsync(
|
|
ThemeSelectionIdentity identity,
|
|
int maximumItems = LegacyThemeSelectionService.DefaultMaximumPreviewItems,
|
|
CancellationToken cancellationToken = default) => Task.FromResult(
|
|
new ThemePreviewResult(identity, DateTimeOffset.UtcNow, [], false));
|
|
}
|
|
|
|
private sealed class CountingExpertService : IExpertSelectionService
|
|
{
|
|
private static readonly ExpertSelectionIdentity Identity = new("0001", "Expert A");
|
|
|
|
public List<string> Queries { get; } = [];
|
|
|
|
public Task<ExpertSearchResult> SearchAsync(
|
|
string query = "",
|
|
int maximumResults = LegacyExpertSelectionService.DefaultMaximumResults,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
Queries.Add(query);
|
|
return Task.FromResult(new ExpertSearchResult(
|
|
query,
|
|
DateTimeOffset.UtcNow,
|
|
[new ExpertSelectorItem(Identity, DataSourceKind.Oracle)],
|
|
false));
|
|
}
|
|
|
|
public Task<ExpertPreviewResult> PreviewAsync(
|
|
ExpertSelectionIdentity identity,
|
|
int maximumItems = LegacyExpertSelectionService.DefaultMaximumPreviewItems,
|
|
CancellationToken cancellationToken = default) => Task.FromResult(
|
|
new ExpertPreviewResult(identity, DateTimeOffset.UtcNow, [], false));
|
|
}
|
|
|
|
private sealed class CountingIndustryService : IIndustrySelectionService
|
|
{
|
|
public List<IndustryMarket> Markets { get; } = [];
|
|
|
|
public Task<IReadOnlyList<IndustrySelection>> GetAsync(
|
|
IndustryMarket market,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
Markets.Add(market);
|
|
return Task.FromResult<IReadOnlyList<IndustrySelection>>(
|
|
[
|
|
new(market, "Industry 1", "001"),
|
|
new(market, "Industry 2", "002")
|
|
]);
|
|
}
|
|
}
|
|
|
|
private sealed class StaticComparisonDataService : ILegacyComparisonDataService
|
|
{
|
|
private static readonly IReadOnlyList<LegacyComparisonTarget> Domestic =
|
|
[
|
|
LegacyComparisonTarget.CreateKrxStock(
|
|
LegacyComparisonDomesticMarket.Kospi,
|
|
"Samsung Electronics",
|
|
"005930"),
|
|
LegacyComparisonTarget.CreateKrxStock(
|
|
LegacyComparisonDomesticMarket.Kospi,
|
|
"SK Hynix",
|
|
"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 CountingComparisonPairStore : ILegacyComparisonPairStore
|
|
{
|
|
public int ReadCount { get; private set; }
|
|
|
|
public Task<byte[]?> ReadCp949Async(CancellationToken cancellationToken = default)
|
|
{
|
|
ReadCount++;
|
|
return Task.FromResult<byte[]?>(null);
|
|
}
|
|
|
|
public Task WriteCp949Async(
|
|
IReadOnlyList<LegacyComparisonPairWriteRow> rows,
|
|
CancellationToken cancellationToken = default) => Task.CompletedTask;
|
|
}
|
|
|
|
private sealed class DelayedComparisonPairStore : ILegacyComparisonPairStore
|
|
{
|
|
public TaskCompletionSource FirstReadStarted { get; } = new(
|
|
TaskCreationOptions.RunContinuationsAsynchronously);
|
|
|
|
public TaskCompletionSource ReleaseFirstRead { get; } = new(
|
|
TaskCreationOptions.RunContinuationsAsynchronously);
|
|
|
|
public int ReadCount { get; private set; }
|
|
|
|
public async Task<byte[]?> ReadCp949Async(
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
ReadCount++;
|
|
if (ReadCount == 1)
|
|
{
|
|
FirstReadStarted.TrySetResult();
|
|
await ReleaseFirstRead.Task.WaitAsync(cancellationToken);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public Task WriteCp949Async(
|
|
IReadOnlyList<LegacyComparisonPairWriteRow> rows,
|
|
CancellationToken cancellationToken = default) => Task.CompletedTask;
|
|
}
|
|
|
|
private sealed class StaticOverseasIndustryService : IOverseasIndustryIndexSearchService
|
|
{
|
|
public Task<OverseasIndustryIndexSearchResult> SearchAsync(
|
|
string query,
|
|
int maximumResults = LegacyOverseasIndustryIndexSearchService.DefaultMaximumResults,
|
|
CancellationToken cancellationToken = default) => Task.FromResult(
|
|
new OverseasIndustryIndexSearchResult(
|
|
query.Trim(),
|
|
DateTimeOffset.UtcNow,
|
|
[new OverseasIndustryIndexItem("Semiconductor", "US Semiconductor", "NAS@SOX")],
|
|
false));
|
|
}
|
|
|
|
private sealed class StaticOverseasStockService : IOverseasStockSearchService
|
|
{
|
|
public Task<WorldStockSearchResult> SearchAsync(
|
|
string query,
|
|
int maximumResults = LegacyOverseasStockSearchService.DefaultMaximumResults,
|
|
CancellationToken cancellationToken = default) => Task.FromResult(
|
|
new WorldStockSearchResult(
|
|
query.Trim(),
|
|
DateTimeOffset.UtcNow,
|
|
[new WorldStockSearchItem("Apple", "NAS@AAPL", "US")],
|
|
false));
|
|
}
|
|
|
|
private sealed class DelayedOverseasIndustryService : IOverseasIndustryIndexSearchService
|
|
{
|
|
public TaskCompletionSource RequestStarted { get; } = new(
|
|
TaskCreationOptions.RunContinuationsAsynchronously);
|
|
|
|
public TaskCompletionSource ReleaseRequest { get; } = new(
|
|
TaskCreationOptions.RunContinuationsAsynchronously);
|
|
|
|
public async Task<OverseasIndustryIndexSearchResult> SearchAsync(
|
|
string query,
|
|
int maximumResults = LegacyOverseasIndustryIndexSearchService.DefaultMaximumResults,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
RequestStarted.TrySetResult();
|
|
await ReleaseRequest.Task.WaitAsync(cancellationToken);
|
|
return new OverseasIndustryIndexSearchResult(
|
|
query.Trim(),
|
|
DateTimeOffset.UtcNow,
|
|
[new OverseasIndustryIndexItem("Old", "Old result", "NAS@OLD")],
|
|
false);
|
|
}
|
|
}
|
|
|
|
private sealed class StaticTradingHaltService : ITradingHaltSelectionService
|
|
{
|
|
public Task<TradingHaltSelectionResult> SearchAsync(
|
|
string query = "",
|
|
int maximumResults = LegacyTradingHaltSelectionService.DefaultMaximumResults,
|
|
CancellationToken cancellationToken = default) => Task.FromResult(
|
|
new TradingHaltSelectionResult(
|
|
query.Trim(),
|
|
DateTimeOffset.UtcNow,
|
|
[new TradingHaltSelection(
|
|
TradingHaltMarket.Kospi,
|
|
"005930",
|
|
"Samsung Electronics")],
|
|
false));
|
|
}
|
|
}
|