Skip to content

Commit

Permalink
chore(atomic): add tests + stories for atomic-commerce-product-list (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
fbeaudoincoveo authored Oct 31, 2024
1 parent 9442b98 commit 49638b9
Show file tree
Hide file tree
Showing 5 changed files with 345 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,50 @@ import {
} from '@coveo/atomic-storybook-utils/commerce/commerce-interface-wrapper';
import {parameters} from '@coveo/atomic-storybook-utils/common/common-meta-parameters';
import {renderComponent} from '@coveo/atomic-storybook-utils/common/render-component';
import {CommerceEngineConfiguration} from '@coveo/headless/dist/definitions/commerce.index';
import type {Meta, StoryObj as Story} from '@storybook/web-components';
import {html} from 'lit-html/static.js';

// TODO KIT-3640 - Add stories for table display

const {decorator, play} = wrapInCommerceInterface({skipFirstSearch: false});

const noResultsEngineConfig: Partial<CommerceEngineConfiguration> = {
preprocessRequest: (r) => {
const parsed = JSON.parse(r.body as string);
// eslint-disable-next-line @cspell/spellchecker
parsed.query = 'xqyzpqwlnftguscaqmzpbyuagloxhf';
r.body = JSON.stringify(parsed);
return r;
},
};
const {play: playNoFirstQuery} = wrapInCommerceInterface({
skipFirstSearch: true,
});

const {play: playNoresults} = wrapInCommerceInterface({
const {play: playNoProducts} = wrapInCommerceInterface({
skipFirstSearch: false,
engineConfig: noResultsEngineConfig,
engineConfig: {
preprocessRequest: (r) => {
const parsed = JSON.parse(r.body as string);
parsed.query = 'show me no products';
r.body = JSON.stringify(parsed);
return r;
},
},
});

const meta: Meta = {
argTypes: {
'attributes-display': {
options: ['grid', 'list', 'table'],
control: {type: 'radio'},
},
'attributes-density': {
options: ['compact', 'comfortable', 'normal'],
control: {type: 'radio'},
},
'attributes-image-size': {
options: ['small', 'large', 'icon', 'none'],
control: {type: 'radio'},
},
},
args: {
'attributes-number-of-placeholders': 24,
'attributes-display': 'grid',
'attributes-density': 'normal',
'attributes-image-size': 'small',
},
component: 'atomic-commerce-product-list',
title: 'Atomic-Commerce/ProductList',
id: 'atomic-commerce-product-list',
Expand All @@ -38,55 +60,126 @@ const meta: Meta = {
export default meta;

export const Default: Story = {
name: 'atomic-commerce-product-list',
name: 'Grid display',
play: async (context) => {
await play(context);
await playExecuteFirstSearch(context);
},
};

const {play: playNoFirstSearch} = wrapInCommerceInterface({
skipFirstSearch: true,
engineConfig: noResultsEngineConfig,
});
export const GridDisplayWithTemplate: Story = {
name: 'Grid display with template',
args: {
'slots-default': `<atomic-product-template>
<template>
<atomic-product-section-name>
<atomic-product-link class="font-bold"></atomic-product-link>
</atomic-product-section-name>
<atomic-product-section-visual>
<atomic-product-image></atomic-product-image>
</atomic-product-section-visual>
<atomic-product-section-metadata>
<atomic-product-field-condition if-defined="ec_brand">
<atomic-product-text field="ec_brand" class="text-neutral-dark block"></atomic-product-text>
</atomic-product-field-condition>
<atomic-product-rating></atomic-product-rating>
</atomic-product-section-metadata>
<atomic-product-section-emphasized>
<atomic-product-price></atomic-product-price>
</atomic-product-section-emphasized>
<atomic-product-section-children>
<atomic-product-children></atomic-product-children>
</atomic-product-section-children>
</template>
</atomic-product-template>`,
},
};

export const NoFirstSearch: Story = {
name: 'atomic-commerce-product-list',
export const GridDisplayBeforeQuery: Story = {
name: 'Grid display before query',
play: async (context) => {
await playNoFirstSearch(context);
await playNoFirstQuery(context);
},
};

export const OpenInNewTab: Story = {
name: 'Open Product in New Tab',
tags: ['test'],
args: {'attributes-grid-cell-link-target': '_blank'},
export const ListDisplay: Story = {
name: 'List display',
play: async (context) => {
await wrapInCommerceInterface({skipFirstSearch: true}).play(context);
await play(context);
await playExecuteFirstSearch(context);
},
args: {
'attributes-display': 'list',
},
};

export const ListDisplayWithTemplate: Story = {
name: 'List display with template',
args: {
'attributes-display': 'list',
'slots-default': `<atomic-product-template>
<template>
<atomic-product-section-name>
<atomic-product-link class="font-bold"></atomic-product-link>
</atomic-product-section-name>
<atomic-product-section-visual>
<atomic-product-image></atomic-product-image>
</atomic-product-section-visual>
<atomic-product-section-metadata>
<atomic-product-field-condition if-defined="ec_brand">
<atomic-product-text field="ec_brand" class="text-neutral-dark block"></atomic-product-text>
</atomic-product-field-condition>
<atomic-product-rating></atomic-product-rating>
</atomic-product-section-metadata>
<atomic-product-section-emphasized>
<atomic-product-price></atomic-product-price>
</atomic-product-section-emphasized>
<atomic-product-section-children>
<atomic-product-children></atomic-product-children>
</atomic-product-section-children>
</template>
</atomic-product-template>`,
},
};

export const NoResults: Story = {
name: 'No Results',
tags: ['test'],
export const ListDisplayBeforeQuery: Story = {
name: 'List display before query',
args: {
'attributes-display': 'list',
},
play: async (context) => {
await playNoFirstQuery(context);
},
};

export const NoProducts: Story = {
name: 'No products',
decorators: [(story) => story()],
play: async (context) => {
await playNoresults(context);
await playNoProducts(context);
await playExecuteFirstSearch(context);
},
};

export const InPage: Story = {
name: 'In a page',
tags: ['test'],
name: 'In page',
decorators: [
(story) =>
html` <atomic-commerce-layout>
<atomic-layout-section section="search">
<atomic-commerce-search-box></atomic-commerce-search-box>
</atomic-layout-section>
<atomic-layout-section section="facets"
><atomic-commerce-facets></atomic-commerce-facets
></atomic-layout-section>
<atomic-layout-section section="main">
<atomic-layout-section section="status">
<atomic-commerce-breadbox></atomic-commerce-breadbox>
<atomic-commerce-query-summary></atomic-commerce-query-summary>
<atomic-commerce-sort-dropdown></atomic-commerce-sort-dropdown>
<atomic-commerce-did-you-mean></atomic-commerce-did-you-mean>
<atomic-commerce-refine-toggle></atomic-commerce-refine-toggle>
</atomic-layout-section>
<atomic-layout-section section="products">
${story()}
<atomic-commerce-query-error></atomic-commerce-query-error>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ import {SelectChildProductEventArgs} from '../product-template-components/atomic
/**
* @alpha
* The `atomic-commerce-product-list` component is responsible for displaying products.
*
* @part result-list - The element containing the list of products.
*
* @slot default - The default slot where the product templates are defined.
*/
@Component({
tag: 'atomic-commerce-product-list',
Expand Down Expand Up @@ -94,7 +98,7 @@ export class AtomicCommerceProductList
/**
* The desired layout to use when displaying products. Layouts affect how many products to display per row and how visually distinct they are from each other.
*/
@Prop({reflect: true}) display: ItemDisplayLayout = 'grid';
@Prop({reflect: true}) display: ItemDisplayLayout = 'grid'; // TODO KIT-3640 - Support 'table', or use ItemDisplayBasicLayout type.

/**
* The spacing of various elements in the product list, including the gap between products, the gap between parts of a product, and the font sizes of different parts in a product.
Expand Down
Loading

0 comments on commit 49638b9

Please sign in to comment.