Skip to content

Commit

Permalink
feat(quantic): quantic search box improvements (#4120)
Browse files Browse the repository at this point in the history
## [SFINT-5576](https://coveord.atlassian.net/browse/SFINT-5576)

In this PR:

- Search box recent queries feature added to the Quantic Search Box.
- Several bugs fixed with the Quantic Search Box.
- A11y of the Quantic Search Box improved.
- Cleaned the Quantic Search Box component and all of its internal
components for a more simplicity.

Quantic Search Box autopsy:
https://coveord.atlassian.net/wiki/spaces/~60c8f25b2bd2140069e4cdbc/pages/4208459786/Quantic+Search+Box+Autopsy

[SFINT-5576]:
https://coveord.atlassian.net/browse/SFINT-5576?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

---------

Co-authored-by: Sylvie Allain <[email protected]>
Co-authored-by: Simon Milord <[email protected]>
  • Loading branch information
3 people authored Jul 22, 2024
1 parent b52953e commit f2363fa
Show file tree
Hide file tree
Showing 29 changed files with 1,870 additions and 247 deletions.
2 changes: 1 addition & 1 deletion packages/quantic/cypress/e2e/default-1/examples/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const insightInterfaceComponent = 'c-quantic-insight-interface';
function actions(selector: Selector) {
return {
typeInSearchbox: (text: string) => selector.searchbox().type(text),
submitQuery: () => selector.searchbox().trigger('keyup', {key: 'Enter'}),
submitQuery: () => selector.searchbox().trigger('keydown', {key: 'Enter'}),
selectFacetValue: (value: string) =>
selector.facetValue(value).check({force: true}),
selectPagerButton: (index: number) => selector.pagerButton(index).click(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {SearchBoxSelector, SearchBoxSelectors} from './search-box-selectors';

const standaloneSearchBoxActions = (selector: SearchBoxSelector) => {
return {
typeInSearchBox: (query: string, textarea = false) => {
selector
.input(textarea)
.type(query)
.logAction(`when typing "${query}" in search box`);
},
pressDownArrowOnSearchBox: (textarea = false) => {
selector.input(textarea).type('{downarrow}');
},
pressEnterOnSearchBox: (textarea = false) => {
selector.input(textarea).type('{enter}');
},
clickQuerySuggestion: (index: number) => {
selector.querySuggestionByIndex(index).click();
},
clickClearRecentQueriesButton: () => {
selector.clearRecentQueriesButton().click();
},
focusSearchBox: (textarea = false) => {
selector.input(textarea).then((searchbox) => {
cy.wrap(searchbox).focus();
});
},
blurSearchBox: (textarea = false) => {
selector.input(textarea).blur({force: true});
},
};
};

export const SearchBoxActions = {
...standaloneSearchBoxActions(SearchBoxSelectors),
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import {InterceptAliases} from '../../../page-objects/search';
import {should} from '../../common-selectors';
import {AriaLiveExpectations} from '../../default-1/aria-live/aria-live-expectations';
import {SearchBoxSelectors, SearchBoxSelector} from './search-box-selectors';

function searchBoxExpectations(selector: SearchBoxSelector) {
return {
displayClearRecentQueriesButton: (display: boolean) => {
selector
.clearRecentQueriesButton()
.should(display ? 'exist' : 'not.exist')
.logDetail(
`${should(display)} display the 'clear recent queries' button`
);
},
querySuggestionsEquals: (querySuggestions: String[]) => {
querySuggestions.forEach((querySuggestion, index) => {
selector
.querySuggestionContentByIndex(index)
.then(([suggestion]) => {
expect(suggestion.innerText).to.eq(querySuggestion);
})
.logDetail(
'should display the query suggestions properly and in the correct order'
);
});
},
searchWithQuery: (
expectedQuery: string,
expectedRecentQueriesInLocalStorage?: {LSkey: string; queries: string[]}
) => {
cy.wait(InterceptAliases.Search)
.then((interception) => {
const requestBody = interception.request.body;
expect(requestBody).to.have.property('q', expectedQuery);
if (expectedRecentQueriesInLocalStorage) {
const {LSkey, queries} = expectedRecentQueriesInLocalStorage;
const recentQueries = window.localStorage.getItem(LSkey);
expect(recentQueries).to.equal(JSON.stringify(queries));
}
})
.logDetail(
`should make a search request with the query ${expectedQuery} ${expectedRecentQueriesInLocalStorage ? 'and should add it the local storage' : ''}`
);
},
displaySearchBoxInput: (display: boolean, textarea = false) => {
selector
.input(textarea)
.should(display ? 'exist' : 'not.exist')
.logDetail(`${should(display)} display the input search box`);
},
displaySearchButton: (display: boolean) => {
selector
.searchButton()
.should(display ? 'exist' : 'not.exist')
.logDetail(`${should(display)} display the search button`);
},
displaySuggestionList: (display: boolean) => {
selector
.suggestionList()
.should(display ? 'exist' : 'not.exist')
.logDetail(`${should(display)} display the query suggestions list`);
},
numberOfQuerySuggestions: (value: number) => {
selector
.querySuggestions()
.should('have.length', value)
.logDetail(`should display ${value} query suggestions`);
},
logClearRecentQueries: () => {
cy.wait(InterceptAliases.UA.RecentQueries.ClearRecentQueries)
.then((interception) => {
const analyticsBody = interception.request.body;
expect(analyticsBody).to.have.property('eventType', 'recentQueries');
})
.logDetail("should log the 'clearRecentQueries' UA event");
},
logClickRecentQueries: (queryText: string) => {
cy.wait(InterceptAliases.UA.RecentQueries.ClickRecentQueries)
.then((interception) => {
const analyticsBody = interception.request.body;
expect(analyticsBody).to.have.property('queryText', queryText);
})
.logDetail(
`should log the 'recentQueriesClick' UA event with the correct value: ${queryText}`
);
},
logClickSuggestion: (queryText: string) => {
cy.wait(InterceptAliases.UA.OmniboxAnalytics)
.then((interception) => {
const analyticsBody = interception.request.body;
expect(analyticsBody).to.have.property('queryText', queryText);
})
.logDetail("should log the 'omniboxAnalytics' UA event");
},
};
}

export const SearchBoxExpectations = {
...searchBoxExpectations(SearchBoxSelectors),
ariaLive: {
...AriaLiveExpectations,
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {ComponentSelector, CypressSelector} from '../../common-selectors';

export const standaloneSearchBoxComponent = 'c-quantic-search-box';

export interface SearchBoxSelector extends ComponentSelector {
input: (textarea?: boolean) => CypressSelector;
quanticSearchBoxInput: () => CypressSelector;
suggestionList: () => CypressSelector;
searchButton: () => CypressSelector;
clearRecentQueriesButton: () => CypressSelector;
querySuggestions: () => CypressSelector;
querySuggestionByIndex: (index: number) => CypressSelector;
querySuggestionContentByIndex: (index: number) => CypressSelector;
}

export const SearchBoxSelectors: SearchBoxSelector = {
get: () => cy.get(standaloneSearchBoxComponent),
quanticSearchBoxInput: () =>
SearchBoxSelectors.get().find('[data-cy="quantic-search-box-input"]'),
input: (textarea = false) =>
SearchBoxSelectors.get().find(
`c-quantic-search-box-input [data-cy="${textarea ? 'search-box-textarea' : 'search-box-input'}"]`
),
suggestionList: () =>
SearchBoxSelectors.get().find(
'c-quantic-search-box-suggestions-list [data-cy="suggestion-list"]'
),
searchButton: () =>
SearchBoxSelectors.get().find(
'c-quantic-search-box-input [data-cy="search-box-submit-button"]'
),
clearRecentQueriesButton: () =>
SearchBoxSelectors.get().find(
'c-quantic-search-box-input [data-cy="clear-recent-queries"]'
),
querySuggestions: () =>
SearchBoxSelectors.get().find(
'c-quantic-search-box-input [data-cy="suggestions-option"]'
),
querySuggestionByIndex: (index: number) =>
SearchBoxSelectors.querySuggestions().eq(index),
querySuggestionContentByIndex: (index: number) =>
SearchBoxSelectors.get()
.find(
'c-quantic-search-box-input [data-cy="suggestions-option"] lightning-formatted-rich-text'
)
.eq(index),
};
Loading

0 comments on commit f2363fa

Please sign in to comment.