diff --git a/packages/atomic/src/components.d.ts b/packages/atomic/src/components.d.ts index 64b5dab630d..83a06e716a5 100644 --- a/packages/atomic/src/components.d.ts +++ b/packages/atomic/src/components.d.ts @@ -2082,6 +2082,7 @@ export namespace Components { "maxValueInIndex": number; /** * The field whose value you want to display next to the rating. This field can be used to display the number of reviews or the numerical value of the rating, for example. + * @type {string} */ "ratingDetailsField"?: string; } @@ -7913,6 +7914,7 @@ declare namespace LocalJSX { "maxValueInIndex"?: number; /** * The field whose value you want to display next to the rating. This field can be used to display the number of reviews or the numerical value of the rating, for example. + * @type {string} */ "ratingDetailsField"?: string; } diff --git a/packages/atomic/src/components/commerce/product-template-components/atomic-product-rating/atomic-product-rating.new.stories.tsx b/packages/atomic/src/components/commerce/product-template-components/atomic-product-rating/atomic-product-rating.new.stories.tsx new file mode 100644 index 00000000000..389ae29b469 --- /dev/null +++ b/packages/atomic/src/components/commerce/product-template-components/atomic-product-rating/atomic-product-rating.new.stories.tsx @@ -0,0 +1,65 @@ +import type {Meta, StoryObj as Story} from '@storybook/web-components'; +import {wrapInCommerceInterface} from '../../../../../storybookUtils/commerce/commerce-interface-wrapper'; +import {wrapInCommerceProductList} from '../../../../../storybookUtils/commerce/commerce-product-list-wrapper'; +import {wrapInProductTemplate} from '../../../../../storybookUtils/commerce/commerce-product-template-wrapper'; +import {parameters} from '../../../../../storybookUtils/common/common-meta-parameters'; +import {renderComponent} from '../../../../../storybookUtils/common/render-component'; + +const { + decorator: commerceInterfaceDecorator, + play: initializeCommerceInterface, +} = wrapInCommerceInterface({ + skipFirstSearch: false, + type: 'product-listing', + engineConfig: { + context: { + view: { + url: 'https://sports.barca.group/browse/promotions/ui-kit-testing', + }, + language: 'en', + country: 'US', + currency: 'USD', + }, + }, +}); +const {decorator: commerceProductListDecorator} = wrapInCommerceProductList(); +const {decorator: productTemplateDecorator} = wrapInProductTemplate(); + +const meta: Meta = { + component: 'atomic-product-rating', + title: 'Atomic-Commerce/Product Template Components/ProductRating', + id: 'atomic-product-rating', + render: renderComponent, + decorators: [ + productTemplateDecorator, + commerceProductListDecorator, + commerceInterfaceDecorator, + ], + parameters, + play: initializeCommerceInterface, +}; + +export default meta; + +export const Default: Story = { + name: 'atomic-product-rating', +}; + +export const WithARatingDetailsField: Story = { + args: { + 'attributes-rating-details-field': 'ec_rating', + }, +}; + +export const WithAMaxValueInIndex: Story = { + args: { + 'attributes-max-value-in-index': 10, + }, +}; + +export const WithADifferentIcon: Story = { + args: { + 'attributes-icon': + 'https://raw.githubusercontent.com/Rush/Font-Awesome-SVG-PNG/master/black/svg/circle.svg', + }, +}; diff --git a/packages/atomic/src/components/commerce/product-template-components/atomic-product-rating/atomic-product-rating.tsx b/packages/atomic/src/components/commerce/product-template-components/atomic-product-rating/atomic-product-rating.tsx index b8dde9ffd48..9a34fa7ca0a 100644 --- a/packages/atomic/src/components/commerce/product-template-components/atomic-product-rating/atomic-product-rating.tsx +++ b/packages/atomic/src/components/commerce/product-template-components/atomic-product-rating/atomic-product-rating.tsx @@ -40,6 +40,7 @@ export class AtomicProductRating /** * The field whose value you want to display next to the rating. This field can be used to display the number of reviews or the numerical value of the rating, for example. + * @type {string} */ @Prop({reflect: true}) public ratingDetailsField?: string; diff --git a/packages/atomic/src/components/commerce/product-template-components/atomic-product-rating/e2e/atomic-product-rating.e2e.ts b/packages/atomic/src/components/commerce/product-template-components/atomic-product-rating/e2e/atomic-product-rating.e2e.ts new file mode 100644 index 00000000000..41a991a724d --- /dev/null +++ b/packages/atomic/src/components/commerce/product-template-components/atomic-product-rating/e2e/atomic-product-rating.e2e.ts @@ -0,0 +1,82 @@ +import {test, expect} from './fixture'; + +test.describe('default', () => { + test.beforeEach(async ({productRating}) => { + await productRating.load(); + }); + + test('should be accessible', async ({productRating, makeAxeBuilder}) => { + await expect(productRating.hydrated.first()).toBeVisible(); + + expect((await makeAxeBuilder().analyze()).violations.length).toBe(0); + }); + + test('should have the right number of yellow icons', async ({ + productRating, + }) => { + await expect(productRating.blueLagoonYellowIcons).toHaveAttribute( + 'style', + 'width: 80%;' + ); + }); +}); + +test.describe('with a rating details field', () => { + test.beforeEach(async ({productRating}) => { + await productRating.load({story: 'with-a-rating-details-field'}); + }); + + test('should be accessible', async ({productRating, makeAxeBuilder}) => { + await expect(productRating.hydrated.first()).toBeVisible(); + + expect((await makeAxeBuilder().analyze()).violations.length).toBe(0); + }); + + test('should show the rating details next to the rating', async ({ + productRating, + }) => { + await expect(productRating.hydrated.first().getByText('4')).toBeVisible(); + }); +}); + +test.describe('with a max value in index of 10', () => { + test.beforeEach(async ({productRating}) => { + await productRating.load({story: 'with-a-max-value-in-index'}); + }); + + test('should be accessible', async ({productRating, makeAxeBuilder}) => { + await expect(productRating.hydrated.first()).toBeVisible(); + + expect((await makeAxeBuilder().analyze()).violations.length).toBe(0); + }); + + test('should have the right number of yellow icons', async ({ + productRating, + }) => { + await expect(productRating.blueLagoonYellowIcons).toHaveAttribute( + 'style', + 'width: 40%;' + ); + }); +}); + +test.describe('with a different icon', () => { + test.beforeEach(async ({productRating}) => { + await productRating.load({story: 'with-a-different-icon'}); + }); + + test('should be accessible', async ({productRating, makeAxeBuilder}) => { + await expect(productRating.hydrated.first()).toBeVisible(); + + expect((await makeAxeBuilder().analyze()).violations.length).toBe(0); + }); + + test('should have the right number of yellow icons', async ({ + productRating, + }) => { + await expect(productRating.blueLagoonYellowIcons).toHaveAttribute( + 'style', + 'width: 80%;' + ); + }); +}); diff --git a/packages/atomic/src/components/commerce/product-template-components/atomic-product-rating/e2e/fixture.ts b/packages/atomic/src/components/commerce/product-template-components/atomic-product-rating/e2e/fixture.ts new file mode 100644 index 00000000000..0d4b561145d --- /dev/null +++ b/packages/atomic/src/components/commerce/product-template-components/atomic-product-rating/e2e/fixture.ts @@ -0,0 +1,19 @@ +import {test as base} from '@playwright/test'; +import { + makeAxeBuilder, + AxeFixture, +} from '../../../../../../playwright-utils/base-fixture'; +import {ProductRatingPageObject} from './page-object'; + +type MyFixtures = { + productRating: ProductRatingPageObject; +}; + +export const test = base.extend({ + makeAxeBuilder, + productRating: async ({page}, use) => { + await use(new ProductRatingPageObject(page)); + }, +}); + +export {expect} from '@playwright/test'; diff --git a/packages/atomic/src/components/commerce/product-template-components/atomic-product-rating/e2e/page-object.ts b/packages/atomic/src/components/commerce/product-template-components/atomic-product-rating/e2e/page-object.ts new file mode 100644 index 00000000000..a8c88fdcb98 --- /dev/null +++ b/packages/atomic/src/components/commerce/product-template-components/atomic-product-rating/e2e/page-object.ts @@ -0,0 +1,15 @@ +import {Page} from '@playwright/test'; +import {BasePageObject} from '../../../../../../playwright-utils/base-page-object'; + +export class ProductRatingPageObject extends BasePageObject<'atomic-product-rating'> { + constructor(page: Page) { + super(page, 'atomic-product-rating'); + } + + get blueLagoonYellowIcons() { + return this.page + .getByLabel('4 stars out of', {exact: false}) + .locator('div') + .nth(1); + } +}