Skip to content

Commit

Permalink
Merge branch 'CDX-1590' into CDX-1588
Browse files Browse the repository at this point in the history
  • Loading branch information
fpbrault authored Aug 26, 2024
2 parents 7210f71 + 324136e commit a3b0197
Show file tree
Hide file tree
Showing 50 changed files with 1,190 additions and 340 deletions.
2 changes: 1 addition & 1 deletion packages/atomic/cypress/e2e/breadbox.cypress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ describe('Breadbox Test Suites', () => {
});

describe('when excluding from a standard facet', () => {
const selectionIndex = 2;
const selectionIndex = 1;

function setupFacetWithMultipleExcludedValues() {
new TestFixture()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,22 +203,46 @@ export class AtomicCommerceSearchBox

@AriaLiveRegion('search-suggestions', true)
protected suggestionsAriaMessage!: string;
public disconnectedCallback = () => {};

private isStandaloneSearchBox(
searchBox: SearchBox | StandaloneSearchBox
): searchBox is StandaloneSearchBox {
return 'redirectTo' in searchBox;
}

public initialize() {
this.id = randomID('atomic-commerce-search-box-');
this.id ??= randomID('atomic-commerce-search-box-');

this.initializeSearchboxController();
this.initializeSuggestionManager();
}

private updateRedirectionUrl() {
if (this.isStandaloneSearchBox(this.searchBox) && this.redirectionUrl) {
this.searchBox.updateRedirectUrl(this.redirectionUrl);
} else {
this.registerNewSearchBoxController();
}
}

private registerNewSearchBoxController() {
this.disconnectedCallback();
this.initialize();
}

private initializeSearchboxController() {
this.searchBox = this.redirectionUrl
? buildStandaloneSearchBox(this.bindings.engine, {
options: {
...this.searchBoxOptions,
redirectionUrl: this.redirectionUrl,
overwrite: true,
},
})
: buildSearchBox(this.bindings.engine, {
options: this.searchBoxOptions,
});

this.initializeSuggestionManager();
}

public componentWillUpdate() {
Expand Down Expand Up @@ -271,7 +295,7 @@ export class AtomicCommerceSearchBox
this.suggestionManager.forceUpdate();
}

public componentWillRender() {
private registerSearchboxSuggestionEvents() {
this.searchBoxSuggestionEventsQueue.forEach((evt) => {
this.suggestionManager.registerSuggestionsFromEvent(
evt,
Expand All @@ -283,7 +307,7 @@ export class AtomicCommerceSearchBox

@Watch('redirectionUrl')
watchRedirectionUrl() {
this.initialize();
this.updateRedirectionUrl();
}

private initializeSuggestionManager() {
Expand Down Expand Up @@ -324,8 +348,8 @@ export class AtomicCommerceSearchBox
return {
...this.bindings,
id: this.id,
isStandalone: !!this.redirectionUrl,
searchBoxController: this.searchBox,
isStandalone: () => !!this.redirectionUrl,
searchBoxController: () => this.searchBox,
numberOfQueries: this.numberOfQueries,
clearFilters: this.clearFilters,
};
Expand Down Expand Up @@ -675,6 +699,9 @@ export class AtomicCommerceSearchBox
const isDisabled = this.isSearchDisabledForEndUser(
this.searchBoxState.value
);
if (!this.suggestionManager.suggestions.length) {
this.registerSearchboxSuggestionEvents();
}

return (
<Host>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,35 @@ test.describe('with instant results & query suggestions', () => {
await expect(searchBox.searchInput).toHaveValue('surf');
});
});

test.describe('after updating the redirect-url attribute', () => {
test.beforeEach(async ({searchBox}) => {
await searchBox.component.evaluate((node) =>
node.setAttribute(
'redirection-url',
'./iframe.html?id=atomic-commerce-search-box--in-page&viewMode=story&args=enable-query-syntax:!true;suggestion-timeout:5000'
)
);
});

test('should redirect to the specified url after selecting a suggestion', async ({
page,
searchBox,
}) => {
const suggestionText = await searchBox
.searchSuggestions()
.first()
.textContent();

expect(suggestionText).not.toBeNull();

await searchBox.searchSuggestions().first().click();
await page.waitForURL(
'**/iframe.html?id=atomic-commerce-search-box--in-page*'
);
await expect(searchBox.searchInput).toHaveValue(suggestionText ?? '');
});
});
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ export class SearchBoxPageObject extends BasePageObject<'atomic-commerce-search-
super(page, 'atomic-commerce-search-box');
}

get component() {
return this.page.locator('atomic-commerce-search-box');
}

get submitButton() {
return this.page.getByLabel('Search', {exact: true});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// import {test, expect} from './fixture';

// test.describe('default', async () => {
// test.describe('when clicking on the next button', async ({productImage}) => {
// test.fixme('should navigate to the next image', () => {});
// test.fixme('should not open the product', () => {});
// });
// test.describe('when clicking on the previous button', async ({productImage}) => {
// test.fixme('should navigate to the previous image', () => {});
// test.fixme('should not open the product', () => {});
// });
// });
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {test as base} from '@playwright/test';
import {
AxeFixture,
makeAxeBuilder,
} from '../../../../../../playwright-utils/base-fixture';
import {ProductImageObject} from './page-object';

interface TestFixture {
productImage: ProductImageObject;
}

export const test = base.extend<TestFixture & AxeFixture>({
makeAxeBuilder,
productImage: async ({page}, use) => {
await use(new ProductImageObject(page));
},
});
export {expect} from '@playwright/test';
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type {Page} from '@playwright/test';
import {BasePageObject} from '../../../../../../playwright-utils/base-page-object';

export class ProductImageObject extends BasePageObject<'atomic-product-image'> {
constructor(page: Page) {
super(page, 'atomic-product-image');
}
// TODO tests
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export const InASearchBoxInstantProducts: Story = {
commerceInterfaceDecorator,
],
play: async (context) => {
initializeCommerceInterface(context);
await initializeCommerceInterface(context);
const {canvasElement, step} = context;
const canvas = within(canvasElement);
await step('Click Searchbox', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,10 @@ export class AtomicCommerceSearchBoxInstantProducts
content: <InstantItemShowAllButton i18n={this.bindings.i18n} />,
onSelect: () => {
this.bindings.clearSuggestions();
this.bindings.searchBoxController.updateText(
this.instantProducts.state.query
);
this.bindings.searchBoxController.submit();
this.bindings
.searchBoxController()
.updateText(this.instantProducts.state.query);
this.bindings.searchBoxController().submit();
},
});
}
Expand Down Expand Up @@ -226,7 +226,7 @@ export class AtomicCommerceSearchBoxInstantProducts
private onSuggestedQueryChange() {
if (
!this.bindings.getSuggestionElements().length &&
!this.bindings.searchBoxController.state.value
!this.bindings.searchBoxController().state.value
) {
console.warn(
"There doesn't seem to be any query suggestions configured. Make sure to include either an atomic-commerce-search-box-query-suggestions or atomic-commerce-search-box-recent-queries in your search box in order to see some instant products."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,16 @@ export class AtomicCommerceSearchBoxQuerySuggestions {
}

private renderItems(): SearchBoxSuggestionElement[] {
const hasQuery = this.bindings.searchBoxController.state.value !== '';
const hasQuery = this.bindings.searchBoxController().state.value !== '';
const max = hasQuery ? this.maxWithQuery : this.maxWithoutQuery;
return this.bindings.searchBoxController.state.suggestions
.slice(0, max)
return this.bindings
.searchBoxController()
.state.suggestions.slice(0, max)
.map((suggestion) => this.renderItem(suggestion));
}

private renderItem(suggestion: Suggestion) {
const hasQuery = this.bindings.searchBoxController.state.value !== '';
const hasQuery = this.bindings.searchBoxController().state.value !== '';
const partialItem = getPartialSearchBoxSuggestionElement(
suggestion,
this.bindings.i18n
Expand All @@ -114,7 +115,9 @@ export class AtomicCommerceSearchBoxQuerySuggestions {
</QuerySuggestionContainer>
),
onSelect: () => {
this.bindings.searchBoxController.selectSuggestion(suggestion.rawValue);
this.bindings
.searchBoxController()
.selectSuggestion(suggestion.rawValue);
},
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export class AtomicCommerceSearchBoxRecentQueries {
return [];
}

const query = this.bindings.searchBoxController.state.value;
const query = this.bindings.searchBoxController().state.value;
const hasQuery = query !== '';
const max = hasQuery ? this.maxWithQuery : this.maxWithoutQuery;
const filteredQueries = this.recentQueriesList.state.queries
Expand Down Expand Up @@ -157,7 +157,7 @@ export class AtomicCommerceSearchBoxRecentQueries {
}

private renderItem(value: string): SearchBoxSuggestionElement {
const query = this.bindings.searchBoxController.state.value;
const query = this.bindings.searchBoxController().state.value;
const partialItem = getPartialRecentQueryElement(value, this.bindings.i18n);
return {
...partialItem,
Expand All @@ -169,9 +169,9 @@ export class AtomicCommerceSearchBoxRecentQueries {
),

onSelect: () => {
if (this.bindings.isStandalone) {
this.bindings.searchBoxController.updateText(value);
this.bindings.searchBoxController.submit();
if (this.bindings.isStandalone()) {
this.bindings.searchBoxController().updateText(value);
this.bindings.searchBoxController().submit();
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ export const ImageCarousel: FunctionalComponent<
<Button
style="text-primary"
ariaLabel={props.bindings.i18n.t('previous')}
onClick={() => props.previousImage()}
onClick={(event) => {
event?.stopPropagation();
props.previousImage();
}}
part="previous-button"
class={`${commonPaginationClasses} left-0 ml-1`}
>
Expand All @@ -44,7 +47,10 @@ export const ImageCarousel: FunctionalComponent<
<Button
style="text-primary"
ariaLabel={props.bindings.i18n.t('next')}
onClick={() => props.nextImage()}
onClick={(event) => {
event?.stopPropagation();
props.nextImage();
}}
part="next-button"
class={`${commonPaginationClasses} right-0 mr-1`}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,11 @@ export type SearchBoxSuggestionsBindings<
/**
* Whether the search box is [standalone](https://docs.coveo.com/en/atomic/latest/usage/ssb/).
*/
isStandalone: boolean;
isStandalone(): boolean;
/**
* The search box headless controller.
*/
searchBoxController: SearchBoxController;
searchBoxController(): SearchBoxController;
/**
* The number of queries to display when the user interacts with the search box.
*/
Expand Down
Loading

0 comments on commit a3b0197

Please sign in to comment.