feat: enable initial-consonant search everywhere
This commit is contained in:
@@ -54,6 +54,36 @@ public sealed class LegacyExpertWorkflowTests
|
||||
() => controller.MaterializeSelectedAction("5074-caller-override"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Search_AcceptsConservativeTruncationAfterInitialFiltering()
|
||||
{
|
||||
var service = new DelegateExpertService
|
||||
{
|
||||
Search = (query, _, _) => Task.FromResult(
|
||||
SearchResult(query, Alpha) with { IsTruncated = true })
|
||||
};
|
||||
var controller = new LegacyExpertWorkflowController(service);
|
||||
|
||||
var searched = await controller.SearchAsync("ㄱㅈㅁ");
|
||||
|
||||
Assert.Equal(Alpha.ExpertName, Assert.Single(searched.Search.Results).ExpertName);
|
||||
Assert.True(searched.Search.IsTruncated);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Search_StillRejectsImpossiblePartialTruncationForOrdinaryText()
|
||||
{
|
||||
var service = new DelegateExpertService
|
||||
{
|
||||
Search = (query, _, _) => Task.FromResult(
|
||||
SearchResult(query, Alpha) with { IsTruncated = true })
|
||||
};
|
||||
var controller = new LegacyExpertWorkflowController(service);
|
||||
|
||||
await Assert.ThrowsAsync<ExpertSelectionDataException>(
|
||||
() => controller.SearchAsync("Expert"));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(1, false, 1)]
|
||||
[InlineData(5, false, 1)]
|
||||
|
||||
@@ -366,6 +366,62 @@ public sealed class LegacyThemeWorkflowTests
|
||||
Assert.Equal("theme-result-5000", snapshot.SearchResults[^1].ResultId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SearchAsync_AcceptsConservativeTruncationAfterInitialFiltering()
|
||||
{
|
||||
var service = new FakeThemeSelectionService
|
||||
{
|
||||
SearchHandler = (query, session) => new ThemeSearchResult(
|
||||
query,
|
||||
session,
|
||||
DateTimeOffset.UtcNow,
|
||||
[
|
||||
Selector(
|
||||
ThemeMarket.Krx,
|
||||
ThemeSession.NotApplicable,
|
||||
"삼성 테마",
|
||||
"00000001")
|
||||
],
|
||||
IsTruncated: true)
|
||||
};
|
||||
var workflow = new LegacyThemeWorkflow(service);
|
||||
|
||||
var snapshot = await workflow.SearchAsync(
|
||||
workflow.CreateInitial(),
|
||||
"ㅅㅅ",
|
||||
ThemeSession.PreMarket);
|
||||
|
||||
Assert.Equal("삼성 테마", Assert.Single(snapshot.SearchResults).DisplayTitle);
|
||||
Assert.True(snapshot.SearchIsTruncated);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SearchAsync_StillRejectsImpossiblePartialTruncationForOrdinaryText()
|
||||
{
|
||||
var service = new FakeThemeSelectionService
|
||||
{
|
||||
SearchHandler = (query, session) => new ThemeSearchResult(
|
||||
query,
|
||||
session,
|
||||
DateTimeOffset.UtcNow,
|
||||
[
|
||||
Selector(
|
||||
ThemeMarket.Krx,
|
||||
ThemeSession.NotApplicable,
|
||||
"AI",
|
||||
"00000001")
|
||||
],
|
||||
IsTruncated: true)
|
||||
};
|
||||
var workflow = new LegacyThemeWorkflow(service);
|
||||
|
||||
await Assert.ThrowsAsync<LegacyThemeWorkflowDataException>(() =>
|
||||
workflow.SearchAsync(
|
||||
workflow.CreateInitial(),
|
||||
"AI",
|
||||
ThemeSession.PreMarket));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SelectAsync_UsesOpaqueResultIdAndCopiesValidatedPreview()
|
||||
{
|
||||
|
||||
@@ -286,6 +286,78 @@ public sealed class LegacyManualFinancialWorkflowTests
|
||||
workflow.ToggleNameSort(state, staleGeneration));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Directional_find_matches_Hangul_initial_consonants()
|
||||
{
|
||||
var service = new FakeManualFinancialService(
|
||||
Snapshot(Record(ManualFinancialScreenKind.Sales, "가나다"), 1),
|
||||
Snapshot(Record(ManualFinancialScreenKind.Sales, "삼성전자"), 2),
|
||||
Snapshot(Record(ManualFinancialScreenKind.Sales, "현대차"), 3));
|
||||
var workflow = Workflow(service);
|
||||
var state = await workflow.SearchAsync(
|
||||
workflow.CreateInitial(ManualFinancialScreenKind.Sales));
|
||||
|
||||
state = workflow.FindByName(
|
||||
state,
|
||||
" ㅅㅅㅈ ",
|
||||
LegacyManualFinancialFindDirection.Down,
|
||||
state.Revision);
|
||||
|
||||
Assert.Equal("ㅅㅅㅈ", state.FindQuery);
|
||||
Assert.Equal(
|
||||
"삼성전자",
|
||||
state.Rows.Single(row => row.ResultId == state.SelectedRowId).StockName);
|
||||
|
||||
state = workflow.FindByName(
|
||||
state,
|
||||
"ㄱㄴㄷ",
|
||||
LegacyManualFinancialFindDirection.Up,
|
||||
state.Revision);
|
||||
|
||||
Assert.Equal(
|
||||
"가나다",
|
||||
state.Rows.Single(row => row.ResultId == state.SelectedRowId).StockName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Create_keeps_a_matching_row_inside_an_initial_consonant_filter()
|
||||
{
|
||||
const string stockName = "삼성전자";
|
||||
var service = new FakeManualFinancialService
|
||||
{
|
||||
SearchOverride = (screen, query) => new ManualFinancialSearchResult(
|
||||
screen,
|
||||
query,
|
||||
DateTimeOffset.UtcNow,
|
||||
Array.Empty<ManualFinancialSnapshot>(),
|
||||
IsTruncated: false)
|
||||
};
|
||||
var workflow = new LegacyManualFinancialWorkflow(
|
||||
service,
|
||||
new FakeStockSearchService(new StockSearchItem(
|
||||
StockMarket.Kospi,
|
||||
DataSourceKind.Oracle,
|
||||
stockName,
|
||||
"005930")),
|
||||
new LegacyManualFinancialWriteSafetyState());
|
||||
var state = await workflow.SearchAsync(
|
||||
workflow.CreateInitial(ManualFinancialScreenKind.Sales),
|
||||
"ㅅㅅㅈ");
|
||||
state = await workflow.SearchStocksAsync(state, stockName);
|
||||
state = workflow.SelectStock(
|
||||
state,
|
||||
Assert.Single(state.StockCandidates).ResultId);
|
||||
|
||||
state = await workflow.ExecuteAsync(
|
||||
state,
|
||||
workflow.CreateCreateRequest(
|
||||
state,
|
||||
Record(ManualFinancialScreenKind.Sales, stockName)));
|
||||
|
||||
Assert.Equal("ㅅㅅㅈ", state.Query);
|
||||
Assert.Equal(stockName, Assert.Single(state.Rows).StockName);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(Screens))]
|
||||
public async Task Create_save_readback_and_action_id_only_draft_work_for_all_modes(
|
||||
|
||||
@@ -34,6 +34,36 @@ public sealed class LegacyTradingHaltWorkflowTests
|
||||
Assert.Equal("가온전자", current.DisplayName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Search_AcceptsConservativeTruncationAfterInitialFiltering()
|
||||
{
|
||||
var service = new DelegateTradingHaltService
|
||||
{
|
||||
Search = (query, _, _) => Task.FromResult(
|
||||
SearchResult(query, KospiAlpha) with { IsTruncated = true })
|
||||
};
|
||||
var controller = new LegacyTradingHaltWorkflowController(service);
|
||||
|
||||
var searched = await controller.SearchAsync("ㄱㅈ");
|
||||
|
||||
Assert.Equal(KospiAlpha.DisplayName, Assert.Single(searched.Results).DisplayName);
|
||||
Assert.True(searched.IsTruncated);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Search_StillRejectsImpossiblePartialTruncationForOrdinaryText()
|
||||
{
|
||||
var service = new DelegateTradingHaltService
|
||||
{
|
||||
Search = (query, _, _) => Task.FromResult(
|
||||
SearchResult(query, KospiAlpha) with { IsTruncated = true })
|
||||
};
|
||||
var controller = new LegacyTradingHaltWorkflowController(service);
|
||||
|
||||
await Assert.ThrowsAsync<TradingHaltSelectionDataException>(
|
||||
() => controller.SearchAsync("Alpha"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SearchSelect_MaterializesClosedCurrentAndCandleDraftsFromActionIdOnly()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user