Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
fpbrault committed Oct 16, 2024
1 parent a417b6b commit 09f2b99
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {wrapInCommerceInterface} from '@coveo/atomic-storybook-utils/commerce/commerce-interface-wrapper';
import {wrapInCommerceProductList} from '@coveo/atomic-storybook-utils/commerce/commerce-product-list-wrapper';
import {wrapInProductTemplate} from '@coveo/atomic-storybook-utils/commerce/commerce-product-template-wrapper';
import {parameters} from '@coveo/atomic-storybook-utils/common/common-meta-parameters';
import {renderComponent} from '@coveo/atomic-storybook-utils/common/render-component';
import type {Meta, StoryObj as Story} from '@storybook/web-components';
import {updateQuery} from '../../../../../../headless/src/features/commerce/query/query-actions';

const {
decorator: commerceInterfaceDecorator,
play: initializeCommerceInterface,
} = wrapInCommerceInterface({
skipFirstSearch: true,
});

const {decorator: commerceProductListDecorator} = wrapInCommerceProductList();
const {decorator: productTemplateDecorator} = wrapInProductTemplate();

const meta: Meta = {
component: 'atomic-product-description',
title: 'Atomic-Commerce/Product Template Components/ProductDescription',
id: 'atomic-product-description',
render: renderComponent,
parameters,
argTypes: {
'attributes-truncate-after': {
name: 'truncate-after',
type: 'string',
},
'attributes-field': {
name: 'field',
type: 'string',
},
},
};

export default meta;

export const Default: Story = {
name: 'atomic-product-description',
parameters: {
viewport: {
defaultViewport: 'mobile1',
},
},
decorators: [
productTemplateDecorator,
commerceProductListDecorator,
commerceInterfaceDecorator,
],
play: async (context) => {
await initializeCommerceInterface(context);

const searchInterface = context.canvasElement.querySelector(
'atomic-commerce-interface'
);
searchInterface?.engine?.dispatch(updateQuery({query: 'kayak'}));

await searchInterface!.executeFirstRequest();
},
args: {
'attributes-field': 'ec_description',
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import {test, expect} from './fixture';

test.describe('atomic-product-description', async () => {
test.beforeEach(async ({page, productDescription}) => {
await page.setViewportSize({width: 375, height: 667});
await productDescription.load();
await productDescription.hydrated.first().waitFor();
});

test('should be accessible', async ({makeAxeBuilder}) => {
const accessibilityResults = await makeAxeBuilder().analyze();
expect(accessibilityResults.violations.length).toEqual(0);
});

const fields: Array<'ec_description' | 'ec_shortdesc' | 'excerpt'> = [
'ec_description',
'ec_shortdesc',
'excerpt',
];

fields.forEach((field) => {
test(`should render description for ${field} field`, async ({
productDescription,
}) => {
await productDescription.load({args: {field}});
await productDescription.hydrated.first().waitFor();

expect(productDescription.textContent.first()).toBeVisible();
});
});

test.describe('when description is truncated', async () => {
const truncateValues: Array<{
value: '1' | '2' | '3' | '4';
expectedClass: RegExp;
}> = [
{value: '1', expectedClass: /line-clamp-1/},
{value: '2', expectedClass: /line-clamp-2/},
{value: '3', expectedClass: /line-clamp-3/},
{value: '4', expectedClass: /line-clamp-4/},
];

truncateValues.forEach(({value, expectedClass}) => {
test.describe(`when truncateAfter is set to ${value}`, async () => {
test(`should truncate description after ${value} lines`, async ({
productDescription,
}) => {
await productDescription.load({
args: {truncateAfter: value},
});
await productDescription.hydrated.first().waitFor();

const descriptionText = productDescription.textContent.first();
expect(descriptionText).toHaveClass(expectedClass);
});

test('should show "Show More" button', async ({productDescription}) => {
const showMoreButton = productDescription.showMoreButton.first();
expect(showMoreButton).toBeVisible();
});

test('should expand description', async ({productDescription}) => {
await productDescription.showMoreButton.first().click();
const descriptionText = productDescription.textContent.first();
expect(descriptionText).not.toHaveClass(/line-clamp-2/);
});
});
});
});

test.describe('when description is not truncated', async () => {
test('should hide "Show More" button ', async ({productDescription}) => {
await productDescription.load({
args: {truncateAfter: 'none'},
});
await productDescription.hydrated.first().waitFor();

expect(productDescription.showMoreButton).not.toBeVisible();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {test as base} from '@playwright/test';
import {
makeAxeBuilder,
AxeFixture,
} from '../../../../../../playwright-utils/base-fixture';
import {ProductDescriptionPageObject as ProductDescription} from './page-object';

type MyFixtures = {
productDescription: ProductDescription;
};

export const test = base.extend<MyFixtures & AxeFixture>({
makeAxeBuilder,
productDescription: async ({page}, use) => {
await use(new ProductDescription(page));
},
});

export {expect} from '@playwright/test';
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import {Page} from '@playwright/test';
import {BasePageObject} from '../../../../../../playwright-utils/base-page-object';

export class ProductDescriptionPageObject extends BasePageObject<'atomic-product-description'> {
constructor(page: Page) {
super(page, 'atomic-product-description');
}

get textContent() {
return this.page.locator('atomic-product-text');
}

get highlightedText() {
return this.page.locator('atomic-product-text b');
}

get showMoreButton() {
return this.page.getByRole('button', {name: 'Show more'});
}
}

0 comments on commit 09f2b99

Please sign in to comment.