Skip to content

Commit

Permalink
test(CardBase): test for CardBase added (#391)
Browse files Browse the repository at this point in the history
* test(CardBase): test for CardBase added
  • Loading branch information
niktverd authored Sep 20, 2023
1 parent d1ecf3e commit 6d60e5b
Show file tree
Hide file tree
Showing 3 changed files with 265 additions and 5 deletions.
23 changes: 18 additions & 5 deletions src/components/CardBase/CardBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -25,6 +25,7 @@ export interface CardBaseProps extends AnalyticsEventsBase, CardBaseParams {
target?: HTMLAttributeAnchorTarget;
metrikaGoals?: MetrikaGoal;
pixelEvents?: ButtonPixel;
qa?: string;
}

export interface CardHeaderBaseProps {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -88,13 +91,20 @@ export const Layout = (props: CardBaseProps) => {
<BackgroundImage
className={b('header', headerClass)}
{...(typeof image === 'string' ? {src: image} : image)}
qa={qaAttributes.header}
>
<div className={b('header-content')}>{header}</div>
</BackgroundImage>
)}
<div className={b('body', bodyClassName)}>
<div className={b('content', contentClassName)}>{content}</div>
{footer && <div className={b('footer', footerClass)}>{footer}</div>}
<div className={b('body', bodyClassName)} data-qa={qaAttributes.body}>
<div className={b('content', contentClassName)} data-qa={qaAttributes.content}>
{content}
</div>
{footer && (
<div className={b('footer', footerClass)} data-qa={qaAttributes.footer}>
{footer}
</div>
)}
</div>
</Fragment>
);
Expand All @@ -116,12 +126,15 @@ export const Layout = (props: CardBaseProps) => {
draggable={false}
onDragStart={(e) => e.preventDefault()}
onClick={onClick}
data-qa={qa}
>
{cardContent}
</a>
</RouterLink>
) : (
<div className={fullClassName}>{cardContent}</div>
<div className={fullClassName} data-qa={qa}>
{cardContent}
</div>
);
};

Expand Down
245 changes: 245 additions & 0 deletions src/components/CardBase/__tests__/CardBase.test.tsx
Original file line number Diff line number Diff line change
@@ -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(
<CardBase qa={qaId}>
<CardBase.Content>Content</CardBase.Content>
</CardBase>,
);
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(
<CardBase qa={qaId} url={url}>
<CardBase.Content>Content</CardBase.Content>
</CardBase>,
);
const cardBase = screen.queryByRole('link');

expect(cardBase).toBeInTheDocument();
expect(cardBase).toBeVisible();
expect(cardBase).not.toBeDisabled();
});

test.each(new Array<React.HTMLAttributeAnchorTarget>(...TARGETS))(
'render with given "%s" target',
(target) => {
render(
<CardBase qa={qaId} url={url} target={target}>
<CardBase.Content>Content</CardBase.Content>
</CardBase>,
);
const cardBase = screen.queryByRole('link');

expect(cardBase).toHaveAttribute('target', target);
},
);

test('add className', () => {
const children = <CardBase.Content>text</CardBase.Content>;
testCustomClassName<CardBaseProps>({
component: CardBase,
props: {children, qa: qaId},
});
});

test('render CardBase with header', async () => {
render(
<CardBase qa={qaId}>
<CardBase.Header>Header</CardBase.Header>
</CardBase>,
);
const cardBaseHeader = screen.queryByTestId(qaAttributes.header);

expect(cardBaseHeader).toBeInTheDocument();
expect(cardBaseHeader).toBeVisible();
expect(cardBaseHeader).not.toBeDisabled();
});

test('render CardBase with content', async () => {
render(
<CardBase qa={qaId}>
<CardBase.Content>Content</CardBase.Content>
</CardBase>,
);
const cardBaseContent = screen.queryByTestId(qaAttributes.content);

expect(cardBaseContent).toBeInTheDocument();
expect(cardBaseContent).toBeVisible();
expect(cardBaseContent).not.toBeDisabled();
});

test('render CardBase with footer', async () => {
render(
<CardBase qa={qaId}>
<CardBase.Footer>Footer</CardBase.Footer>
</CardBase>,
);
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(
<CardBase bodyClassName={bodyClassName} qa={qaId}>
<CardBase.Content>Content</CardBase.Content>
</CardBase>,
);
const cardBaseBody = screen.queryByTestId(qaAttributes.body);

expect(cardBaseBody).toHaveClass(bodyClassName);
});

test('add contentClassName', async () => {
const contentClassName = 'content-class-name';

render(
<CardBase contentClassName={contentClassName} qa={qaId}>
<CardBase.Content>Content</CardBase.Content>
</CardBase>,
);
const cardBaseContent = screen.queryByTestId(qaAttributes.content);

expect(cardBaseContent).toHaveClass(contentClassName);
});

test('add className to Header', async () => {
const className = 'body-class-name';

render(
<CardBase qa={qaId}>
<CardBase.Header className={className}>Header</CardBase.Header>
</CardBase>,
);

const cardBaseHeader = screen.queryByTestId(qaAttributes.header);

expect(cardBaseHeader).toHaveClass(className);
});

test('add className to Footer', async () => {
const className = 'footer-class-name';

render(
<CardBase qa={qaId}>
<CardBase.Footer className={className}>Footer</CardBase.Footer>
</CardBase>,
);
const cardBaseFooter = screen.getByTestId(qaAttributes.footer);

expect(cardBaseFooter).toHaveClass(className);
});

test.each(new Array<CardBorder>(...borders))('render with given "%s" border', (border) => {
render(
<CardBase border={border} qa={qaId}>
<CardBase.Content>Content</CardBase.Content>
</CardBase>,
);
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(
<PageConstructorProvider metrika={metrikaContext}>
<CardBase url={url} target={'_blank'} qa={qaId} metrikaGoals={'metrika-goal'}>
<CardBase.Content>Content</CardBase.Content>
</CardBase>
</PageConstructorProvider>,
);
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(
<PageConstructorProvider metrika={metrikaContext}>
<CardBase
url={url}
target={'_blank'}
qa={qaId}
pixelEvents={[{name: PixelEventType.AddToCart}]}
>
<CardBase.Content>Content</CardBase.Content>
</CardBase>
</PageConstructorProvider>,
);
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(
<PageConstructorProvider analytics={analyticsContext}>
<CardBase url={url} target={'_blank'} qa={qaId} analyticsEvents={[{name: 'click'}]}>
<CardBase.Content>Content</CardBase.Content>
</CardBase>
</PageConstructorProvider>,
);
const cardBase = screen.getByTestId(qaId);

await user.click(cardBase);
expect(analyticsContext.sendEvents).toHaveBeenCalledTimes(1);
});
});
2 changes: 2 additions & 0 deletions test-utils/constants.ts
Original file line number Diff line number Diff line change
@@ -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';

0 comments on commit 6d60e5b

Please sign in to comment.