217 lines
8.2 KiB
C#
217 lines
8.2 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());
|
|
Assert.Single(first.Theme!.SearchResults);
|
|
|
|
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);
|
|
}
|
|
|
|
[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);
|
|
}
|
|
|
|
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));
|
|
}
|
|
}
|