From 6d60e5b6b013c9a9cfadf0e7d004073d7e51d575 Mon Sep 17 00:00:00 2001 From: Nik Tverd <61203447+niktverd@users.noreply.github.com> Date: Thu, 21 Sep 2023 01:48:45 +0600 Subject: [PATCH] test(CardBase): test for CardBase added (#391) * test(CardBase): test for CardBase added --- src/components/CardBase/CardBase.tsx | 23 +- .../CardBase/__tests__/CardBase.test.tsx | 245 ++++++++++++++++++ test-utils/constants.ts | 2 + 3 files changed, 265 insertions(+), 5 deletions(-) create mode 100644 src/components/CardBase/__tests__/CardBase.test.tsx diff --git a/src/components/CardBase/CardBase.tsx b/src/components/CardBase/CardBase.tsx index 52d3b0e7e..5af8ae8bc 100644 --- a/src/components/CardBase/CardBase.tsx +++ b/src/components/CardBase/CardBase.tsx @@ -10,7 +10,7 @@ import { WithChildren, } from '../../models'; import {AnalyticsEventsBase, DefaultEventNames} from '../../models/common'; -import {block} from '../../utils'; +import {block, getQaAttrubutes} from '../../utils'; import BackgroundImage from '../BackgroundImage/BackgroundImage'; import RouterLink from '../RouterLink/RouterLink'; @@ -25,6 +25,7 @@ export interface CardBaseProps extends AnalyticsEventsBase, CardBaseParams { target?: HTMLAttributeAnchorTarget; metrikaGoals?: MetrikaGoal; pixelEvents?: ButtonPixel; + qa?: string; } export interface CardHeaderBaseProps { @@ -54,10 +55,12 @@ export const Layout = (props: CardBaseProps) => { url, target, border = 'shadow', + qa, } = props; const handleMetrika = useMetrika(); const handleAnalytics = useAnalytics(DefaultEventNames.CardBase, url); let header, content, footer, image, headerClass, footerClass; + const qaAttributes = getQaAttrubutes(qa, 'header', 'footer', 'body', 'content'); function handleChild(child: ReactElement) { switch (child.type) { @@ -88,13 +91,20 @@ export const Layout = (props: CardBaseProps) => {
{header}
)} -
-
{content}
- {footer &&
{footer}
} +
+
+ {content} +
+ {footer && ( +
+ {footer} +
+ )}
); @@ -116,12 +126,15 @@ export const Layout = (props: CardBaseProps) => { draggable={false} onDragStart={(e) => e.preventDefault()} onClick={onClick} + data-qa={qa} > {cardContent} ) : ( -
{cardContent}
+
+ {cardContent} +
); }; diff --git a/src/components/CardBase/__tests__/CardBase.test.tsx b/src/components/CardBase/__tests__/CardBase.test.tsx new file mode 100644 index 000000000..168bdf7a0 --- /dev/null +++ b/src/components/CardBase/__tests__/CardBase.test.tsx @@ -0,0 +1,245 @@ +import React from 'react'; + +import {render, screen} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import {TARGETS} from '../../../../test-utils/constants'; +import {testCustomClassName} from '../../../../test-utils/shared/common'; +import {PageConstructorProvider} from '../../../containers/PageConstructor'; +import {AnalyticsContextProps} from '../../../context/analyticsContext'; +import {MetrikaContextProps} from '../../../context/metrikaContext'; +import {CardBorder, PixelEventType} from '../../../models'; +import {getQaAttrubutes} from '../../../utils'; +import CardBase, {CardBaseProps} from '../CardBase'; + +const qaId = 'card-base-component'; +const qaAttributes = getQaAttrubutes(qaId, 'header', 'footer', 'body', 'content'); + +const url = '#'; + +const borders: CardBorder[] = ['shadow', 'line', 'none']; + +describe('CardBase', () => { + test('render CardBase by default', async () => { + render( + + Content + , + ); + const cardBase = screen.getByTestId(qaId); + + expect(cardBase).toBeInTheDocument(); + expect(cardBase).toBeVisible(); + expect(cardBase).not.toBeDisabled(); + + const aTag = screen.queryByRole('link'); + expect(aTag).not.toBeInTheDocument(); + }); + + test('render CardBase by default as a link', async () => { + render( + + Content + , + ); + const cardBase = screen.queryByRole('link'); + + expect(cardBase).toBeInTheDocument(); + expect(cardBase).toBeVisible(); + expect(cardBase).not.toBeDisabled(); + }); + + test.each(new Array(...TARGETS))( + 'render with given "%s" target', + (target) => { + render( + + Content + , + ); + const cardBase = screen.queryByRole('link'); + + expect(cardBase).toHaveAttribute('target', target); + }, + ); + + test('add className', () => { + const children = text; + testCustomClassName({ + component: CardBase, + props: {children, qa: qaId}, + }); + }); + + test('render CardBase with header', async () => { + render( + + Header + , + ); + const cardBaseHeader = screen.queryByTestId(qaAttributes.header); + + expect(cardBaseHeader).toBeInTheDocument(); + expect(cardBaseHeader).toBeVisible(); + expect(cardBaseHeader).not.toBeDisabled(); + }); + + test('render CardBase with content', async () => { + render( + + Content + , + ); + const cardBaseContent = screen.queryByTestId(qaAttributes.content); + + expect(cardBaseContent).toBeInTheDocument(); + expect(cardBaseContent).toBeVisible(); + expect(cardBaseContent).not.toBeDisabled(); + }); + + test('render CardBase with footer', async () => { + render( + + Footer + , + ); + const cardBaseFooter = screen.queryByTestId(qaAttributes.footer); + + expect(cardBaseFooter).toBeInTheDocument(); + expect(cardBaseFooter).toBeVisible(); + expect(cardBaseFooter).not.toBeDisabled(); + }); + + test('add bodyClassName', async () => { + const bodyClassName = 'body-class-name'; + + render( + + Content + , + ); + const cardBaseBody = screen.queryByTestId(qaAttributes.body); + + expect(cardBaseBody).toHaveClass(bodyClassName); + }); + + test('add contentClassName', async () => { + const contentClassName = 'content-class-name'; + + render( + + Content + , + ); + const cardBaseContent = screen.queryByTestId(qaAttributes.content); + + expect(cardBaseContent).toHaveClass(contentClassName); + }); + + test('add className to Header', async () => { + const className = 'body-class-name'; + + render( + + Header + , + ); + + const cardBaseHeader = screen.queryByTestId(qaAttributes.header); + + expect(cardBaseHeader).toHaveClass(className); + }); + + test('add className to Footer', async () => { + const className = 'footer-class-name'; + + render( + + Footer + , + ); + const cardBaseFooter = screen.getByTestId(qaAttributes.footer); + + expect(cardBaseFooter).toHaveClass(className); + }); + + test.each(new Array(...borders))('render with given "%s" border', (border) => { + render( + + Content + , + ); + const button = screen.getByTestId(qaId); + + expect(button).toHaveClass(`pc-card-base-block_border_${border}`); + }); + + test('add metrikaEvent', async () => { + const metrikaContext: MetrikaContextProps = { + metrika: { + reachGoal: jest.fn(), + reachGoals: jest.fn(), + }, + }; + const user = userEvent.setup(); + + render( + + + Content + + , + ); + const cardBase = screen.getByTestId(qaId); + + await user.click(cardBase); + expect(metrikaContext.metrika?.reachGoals).toHaveBeenCalledTimes(1); + }); + + test('add pixelEvent', async () => { + const metrikaContext: MetrikaContextProps = { + pixel: { + trackStandard: jest.fn(), + trackCustom: jest.fn(), + track: jest.fn(), + }, + }; + const user = userEvent.setup(); + + render( + + + Content + + , + ); + const cardBase = screen.getByTestId(qaId); + + await user.click(cardBase); + expect(metrikaContext.pixel?.track).toHaveBeenCalledTimes(1); + }); + + test('add analyticsEvent', async () => { + const analyticsContext: AnalyticsContextProps = { + sendEvents: jest.fn(), + }; + const user = userEvent.setup(); + + render( + + + Content + + , + ); + const cardBase = screen.getByTestId(qaId); + + await user.click(cardBase); + expect(analyticsContext.sendEvents).toHaveBeenCalledTimes(1); + }); +}); diff --git a/test-utils/constants.ts b/test-utils/constants.ts index f8d371ea6..c1bfc8fc5 100644 --- a/test-utils/constants.ts +++ b/test-utils/constants.ts @@ -1 +1,3 @@ +export const TARGETS: React.HTMLAttributeAnchorTarget[] = ['_blank', '_self', '_parent', '_top']; + export const ERROR_INPUT_DATA_MESSAGE = 'There are errors in input test data';