Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(quantic): Exposed the options to be be passed in Did You Mean controller in the QuanticDidYouMean component #4682

Merged
merged 21 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
EnableDidYouMeanParam,
FacetsParam,
FieldsToIncludeParam,
QueryCorrectionParam,
FirstResultParam,
PipelineRuleParams,
QueryParam,
Expand All @@ -33,6 +34,7 @@ export type InsightQueryRequest = InsightParam &
SortCriteriaParam &
FieldsToIncludeParam &
EnableDidYouMeanParam &
QueryCorrectionParam &
ConstantQueryParam &
TabParam &
FoldingParam &
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,39 @@ import {
buildCoreDidYouMean,
DidYouMean,
DidYouMeanState,
DidYouMeanProps,
DidYouMeanOptions,
} from '../../core/did-you-mean/headless-core-did-you-mean.js';

export type {QueryCorrection, WordCorrection, DidYouMean, DidYouMeanState};
export type {
QueryCorrection,
WordCorrection,
DidYouMean,
DidYouMeanState,
DidYouMeanProps,
DidYouMeanOptions,
};

/**
* The insight DidYouMean controller is responsible for handling query corrections.
* When a query returns no result but finds a possible query correction, the controller either suggests the correction or
* automatically triggers a new query with the suggested term.
*
* @param engine - The insight engine.
* @param engine - The headless engine.
* @param props - The configurable `DidYouMean` properties.
*
* @group Controllers
* @category DidYouMean
*/
export function buildDidYouMean(engine: InsightEngine): DidYouMean {
const controller = buildCoreDidYouMean(engine, {
options: {queryCorrectionMode: 'legacy'},
});
export function buildDidYouMean(
engine: InsightEngine,
props: DidYouMeanProps = {
options: {
queryCorrectionMode: 'legacy',
},
}
): DidYouMean {
const controller = buildCoreDidYouMean(engine, props);
SimonMilord marked this conversation as resolved.
Show resolved Hide resolved
const {dispatch} = engine;

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,53 +115,161 @@ describe('AsyncInsightSearchThunkProcessor', () => {
expect(logQueryError).toHaveBeenCalledWith(theError);
});

it('process properly when there are no results returned and there is a did you mean correction', async () => {
const processor = new AsyncInsightSearchThunkProcessor<{}>(config);
const mappedRequest: MappedSearchRequest<InsightQueryRequest> = {
request: buildMockInsightQueryRequest(),
mappings: initialSearchMappings(),
};
describe('query correction processing', () => {
it('process properly when there are no results returned and there is a did you mean correction', async () => {
const processor = new AsyncInsightSearchThunkProcessor<{}>(config);
const mappedRequest: MappedSearchRequest<InsightQueryRequest> = {
request: buildMockInsightQueryRequest(),
mappings: initialSearchMappings(),
};

const originalResponseWithNoResultsAndCorrection = buildMockSearchResponse({
results: [],
queryCorrections: [
{
correctedQuery: 'bar',
wordCorrections: [
{correctedWord: 'foo', length: 3, offset: 0, originalWord: 'foo'},
const originalResponseWithNoResultsAndCorrection =
buildMockSearchResponse({
results: [],
queryCorrections: [
{
correctedQuery: 'bar',
wordCorrections: [
{
correctedWord: 'foo',
length: 3,
offset: 0,
originalWord: 'foo',
},
],
},
],
});

const responseAfterCorrection = buildMockSearchResponse({
results: [buildMockResult({uniqueId: '123'})],
});

(config.extra.apiClient.query as Mock).mockReturnValue(
Promise.resolve({success: responseAfterCorrection})
);

const fetched = {
response: {
success: originalResponseWithNoResultsAndCorrection,
},
],
duration: 123,
queryExecuted: 'foo',
requestExecuted: mappedRequest.request,
};

const processed = (await processor.process(
fetched
)) as ExecuteSearchThunkReturn;

expect(config.dispatch).toHaveBeenCalledWith(updateQuery({q: 'bar'}));
expect(config.extra.apiClient.query).toHaveBeenCalled();
expect(processed.response).toEqual({
...responseAfterCorrection,
queryCorrections:
originalResponseWithNoResultsAndCorrection.queryCorrections,
});
expect(processed.automaticallyCorrected).toBe(true);
});

const responseAfterCorrection = buildMockSearchResponse({
results: [buildMockResult({uniqueId: '123'})],
describe('legacy query correction processing', () => {
it('should automatically correct the query by triggering a second search request', async () => {
const processor = new AsyncInsightSearchThunkProcessor<{}>(config);
const mappedRequest: MappedSearchRequest<InsightQueryRequest> = {
request: buildMockInsightQueryRequest(),
mappings: initialSearchMappings(),
};

const originalResponseWithNoResultsAndCorrection =
buildMockSearchResponse({
results: [],
queryCorrections: [
{
correctedQuery: 'bar',
wordCorrections: [
{
correctedWord: 'foo',
length: 3,
offset: 0,
originalWord: 'foo',
},
],
},
],
});

const responseAfterCorrection = buildMockSearchResponse({
results: [buildMockResult({uniqueId: '123'})],
});

(config.extra.apiClient.query as Mock).mockReturnValue(
Promise.resolve({success: responseAfterCorrection})
);

const fetched = {
response: {
success: originalResponseWithNoResultsAndCorrection,
},
duration: 123,
queryExecuted: 'foo',
requestExecuted: mappedRequest.request,
};

const processed = (await processor.process(
fetched
)) as ExecuteSearchThunkReturn;

expect(config.dispatch).toHaveBeenCalledWith(updateQuery({q: 'bar'}));
expect(config.extra.apiClient.query).toHaveBeenCalled();
expect(processed.response).toEqual({
...responseAfterCorrection,
queryCorrections:
originalResponseWithNoResultsAndCorrection.queryCorrections,
});
expect(processed.automaticallyCorrected).toBe(true);
});
});

(config.extra.apiClient.query as Mock).mockReturnValue(
Promise.resolve({success: responseAfterCorrection})
);
describe('next query correction processing', () => {
it('should automatically correct the query without triggering a second search request', async () => {
const processor = new AsyncInsightSearchThunkProcessor<{}>(config);
const mappedRequest: MappedSearchRequest<InsightQueryRequest> = {
request: buildMockInsightQueryRequest(),
mappings: initialSearchMappings(),
};

const fetched = {
response: {
success: originalResponseWithNoResultsAndCorrection,
},
duration: 123,
queryExecuted: 'foo',
requestExecuted: mappedRequest.request,
};
const originalResponseWithResultsAndChangedQuery =
buildMockSearchResponse({
results: [buildMockResult()],
queryCorrection: {
correctedQuery: 'bar',
originalQuery: 'foo',
corrections: [],
},
});

const processed = (await processor.process(
fetched
)) as ExecuteSearchThunkReturn;
const fetched = {
response: {
success: originalResponseWithResultsAndChangedQuery,
},
duration: 123,
queryExecuted: 'foo',
requestExecuted: mappedRequest.request,
};

const processed = (await processor.process(
fetched
)) as ExecuteSearchThunkReturn;

expect(config.dispatch).toHaveBeenCalledWith(updateQuery({q: 'bar'}));
expect(config.extra.apiClient.query).toHaveBeenCalled();
expect(processed.response).toEqual({
...responseAfterCorrection,
queryCorrections:
originalResponseWithNoResultsAndCorrection.queryCorrections,
expect(config.dispatch).toHaveBeenCalledWith(updateQuery({q: 'bar'}));
expect(config.extra.apiClient.query).not.toHaveBeenCalled();
expect(processed.response).toMatchObject(
originalResponseWithResultsAndChangedQuery
);
expect(processed.automaticallyCorrected).toBe(true);
expect(processed.originalQuery).toBe('foo');
expect(processed.queryExecuted).toBe('bar');
});
});
expect(processed.automaticallyCorrected).toBe(true);
});
});
Loading
Loading