Skip to content

Commit

Permalink
feat: add tests ids props for Calendar, CalendarRange, DateInputRange…
Browse files Browse the repository at this point in the history
…, DateInput (#7705) (#7911)

* feat: add tests ids props for Calendar, CalendarRange, DateInputRange, DateInput

* fix(CalendarRange): fix tests

* fix: fix tests after merge conflicts

(cherry picked from commit 12e1d2b)
  • Loading branch information
EldarMuhamethanov authored Nov 7, 2024
1 parent e975d9f commit e71de15
Show file tree
Hide file tree
Showing 15 changed files with 503 additions and 247 deletions.
64 changes: 45 additions & 19 deletions packages/vkui/src/components/Calendar/Calendar.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { render, screen } from '@testing-library/react';
import { fireEvent, render, screen } from '@testing-library/react';
import { format } from 'date-fns';
import { baselineComponent, userEvent } from '../../testing/utils';
import { Calendar } from './Calendar';

Expand All @@ -8,21 +9,23 @@ const lastDayDate = new Date('2023-09-30T07:40:00.000Z');
const minDate = new Date('2023-09-15T10:35:00.000Z');
const maxDate = new Date('2023-09-29T07:20:00.000Z');

const dayTestId = (day: Date) => format(day, 'dd.MM.yyyy');

describe('Calendar', () => {
baselineComponent(Calendar);

beforeEach(() => (process.env.NODE_ENV = 'development'));
afterEach(() => (process.env.NODE_ENV = 'test'));

it('fires onChange', async () => {
it('fires onChange', () => {
const onChange = jest.fn();

render(<Calendar value={targetDate} onChange={onChange} />);
await userEvent.click(screen.getByText(`${firstDayDate.getDate()}`));
render(<Calendar value={targetDate} onChange={onChange} dayTestId={dayTestId} />);
fireEvent.click(screen.getByTestId(dayTestId(firstDayDate)));
expect(onChange).toHaveBeenCalledWith(firstDayDate);
});

it('does not fire onChange with the value out of minDateTime/maxDateTime', async () => {
it('does not fire onChange with the value out of minDateTime/maxDateTime', () => {
const onChange = jest.fn();

render(
Expand All @@ -31,50 +34,73 @@ describe('Calendar', () => {
minDateTime={minDate}
maxDateTime={maxDate}
onChange={onChange}
dayTestId={dayTestId}
/>,
);
await userEvent.click(screen.getByText(`${firstDayDate.getDate()}`));
fireEvent.click(screen.getByTestId(dayTestId(firstDayDate)));
expect(onChange).not.toHaveBeenCalled();
await userEvent.click(screen.getByText(`${maxDate.getDate() + 1}`));
fireEvent.click(screen.getByTestId(dayTestId(firstDayDate)));
expect(onChange).not.toHaveBeenCalled();
});

it('onChange respects minDateTime', async () => {
it('onChange respects minDateTime', () => {
const onChange = jest.fn();

render(<Calendar value={targetDate} minDateTime={minDate} onChange={onChange} />);
await userEvent.click(screen.getByText(`${minDate.getDate()}`));
render(
<Calendar
value={targetDate}
minDateTime={minDate}
onChange={onChange}
dayTestId={dayTestId}
/>,
);
fireEvent.click(screen.getByTestId(dayTestId(minDate)));
expect(onChange).toHaveBeenCalledWith(minDate);
});

it('onChange respects maxDateTime', async () => {
it('onChange respects maxDateTime', () => {
const onChange = jest.fn();

render(<Calendar value={targetDate} maxDateTime={maxDate} onChange={onChange} />);
await userEvent.click(screen.getByText(`${maxDate.getDate()}`));
render(
<Calendar
value={targetDate}
maxDateTime={maxDate}
onChange={onChange}
dayTestId={dayTestId}
/>,
);
fireEvent.click(screen.getByTestId(dayTestId(maxDate)));
expect(onChange).toHaveBeenCalledWith(maxDate);
});

it('check navigation by keyboard between two months', async () => {
jest.useFakeTimers();

render(<Calendar value={lastDayDate} />);
await userEvent.click(screen.getByText(`${lastDayDate.getDate()}`));
const monthDropdownTestId = (monthIndex: number) => `month-picker-${monthIndex}`;

render(
<Calendar
value={lastDayDate}
dayTestId={dayTestId}
monthDropdownTestId={monthDropdownTestId}
/>,
);
fireEvent.click(screen.getByTestId(dayTestId(lastDayDate)));
await userEvent.keyboard('{ArrowRight}');

expect(screen.getByText('октябрь')).toBeInTheDocument();
expect(screen.getByTestId(monthDropdownTestId(9))).toBeInTheDocument();

await userEvent.keyboard('{ArrowLeft}');

expect(screen.getByText('сентябрь')).toBeInTheDocument();
expect(screen.getByTestId(monthDropdownTestId(8))).toBeInTheDocument();

await userEvent.keyboard('{ArrowDown}');

expect(screen.getByText('октябрь')).toBeInTheDocument();
expect(screen.getByTestId(monthDropdownTestId(9))).toBeInTheDocument();

await userEvent.keyboard('{ArrowUp}');

expect(screen.getByText('сентябрь')).toBeInTheDocument();
expect(screen.getByTestId(monthDropdownTestId(8))).toBeInTheDocument();
});

it('check calls Calendar DEV errors', () => {
Expand Down
35 changes: 31 additions & 4 deletions packages/vkui/src/components/Calendar/Calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,28 @@ import { clamp, isFirstDay, isLastDay, navigateDate, setTimeEqual } from '../../
import { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';
import { warnOnce } from '../../lib/warnOnce';
import type { HTMLAttributesWithRootRef } from '../../types';
import { CalendarDays, type CalendarDaysProps } from '../CalendarDays/CalendarDays';
import { CalendarHeader, type CalendarHeaderProps } from '../CalendarHeader/CalendarHeader';
import { CalendarTime, type CalendarTimeProps } from '../CalendarTime/CalendarTime';
import {
CalendarDays,
type CalendarDaysProps,
type CalendarDaysTestsProps,
} from '../CalendarDays/CalendarDays';
import {
CalendarHeader,
type CalendarHeaderProps,
type CalendarHeaderTestsProps,
} from '../CalendarHeader/CalendarHeader';
import {
CalendarTime,
type CalendarTimeProps,
type CalendarTimeTestsProps,
} from '../CalendarTime/CalendarTime';
import { RootComponent } from '../RootComponent/RootComponent';
import styles from './Calendar.module.css';

export type CalendarTestsProps = CalendarDaysTestsProps &
CalendarHeaderTestsProps &
CalendarTimeTestsProps;

export interface CalendarProps
extends Omit<HTMLAttributesWithRootRef<HTMLDivElement>, 'onChange'>,
Pick<
Expand All @@ -35,7 +51,8 @@ export interface CalendarProps
| 'prevMonthProps'
| 'nextMonthProps'
>,
Pick<CalendarDaysProps, 'dayProps' | 'listenDayChangesForUpdate' | 'renderDayContent'> {
Pick<CalendarDaysProps, 'dayProps' | 'listenDayChangesForUpdate' | 'renderDayContent'>,
CalendarTestsProps {
value?: Date;
/**
* Запрещает выбор даты в прошлом.
Expand Down Expand Up @@ -120,6 +137,11 @@ export const Calendar = ({
renderDayContent,
minDateTime,
maxDateTime,
prevMonthButtonTestId,
nextMonthButtonTestId,
monthDropdownTestId,
yearDropdownTestId,
dayTestId,
...props
}: CalendarProps): React.ReactNode => {
const {
Expand Down Expand Up @@ -214,6 +236,10 @@ export const Calendar = ({
nextMonthProps={nextMonthProps}
isMonthDisabled={isMonthDisabled}
isYearDisabled={isYearDisabled}
nextMonthButtonTestId={nextMonthButtonTestId}
prevMonthButtonTestId={prevMonthButtonTestId}
monthDropdownTestId={monthDropdownTestId}
yearDropdownTestId={yearDropdownTestId}
/>
<CalendarDays
viewDate={externalViewDate || viewDate}
Expand All @@ -234,6 +260,7 @@ export const Calendar = ({
dayProps={dayProps}
listenDayChangesForUpdate={listenDayChangesForUpdate}
renderDayContent={renderDayContent}
dayTestId={dayTestId}
/>
{enableTime && value && size !== 's' && (
<div className={styles['Calendar__time']}>
Expand Down
10 changes: 5 additions & 5 deletions packages/vkui/src/components/CalendarDay/CalendarDay.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { render, screen } from '@testing-library/react';
import { fakeTimers, userEvent } from '../../testing/utils';
import { fireEvent, render, screen } from '@testing-library/react';
import { fakeTimers } from '../../testing/utils';
import { CalendarDay, type CalendarDayProps } from './CalendarDay';
import styles from './CalendarDay.module.css';

Expand All @@ -13,9 +13,9 @@ const CalendarDayTest = (testProps: Omit<CalendarDayProps, 'day' | 'onChange'>)
describe('CalendarDay', () => {
fakeTimers();

it('calls callback with day on click', async () => {
it('calls callback with day on click', () => {
render(<CalendarDayTest />);
await userEvent.click(screen.getByText('1'));
fireEvent.click(screen.getByText('1'));

expect(onChange).toHaveBeenCalledWith(day);
});
Expand All @@ -25,7 +25,7 @@ describe('CalendarDay', () => {
expect(document.querySelector('.vkuiCalendarDay__hidden')).toBeInTheDocument();
});
it('check hinted className', () => {
render(<CalendarDayTest hinted data-testid="day" />);
render(<CalendarDayTest hinted testId="day" />);
const calendarDay = screen.getByTestId('day').firstElementChild!;
expect(calendarDay).toHaveClass(styles['CalendarDay__hinted--active']);
});
Expand Down
8 changes: 7 additions & 1 deletion packages/vkui/src/components/CalendarDay/CalendarDay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ export type CalendarDayElementProps = Omit<
'onChange' | 'size' | 'disabled' | 'selected'
>;

export interface CalendarDayProps extends CalendarDayElementProps {
export type CalendarDayTestsProps = {
testId?: string | ((day: Date) => string);
};

export interface CalendarDayProps extends CalendarDayElementProps, CalendarDayTestsProps {
day: Date;
today?: boolean;
selected?: boolean;
Expand Down Expand Up @@ -55,6 +59,7 @@ export const CalendarDay: React.FC<CalendarDayProps> = React.memo(
className,
children,
renderDayContent,
testId,
...restProps
}: CalendarDayProps) => {
const { locale } = useConfigProvider();
Expand Down Expand Up @@ -115,6 +120,7 @@ export const CalendarDay: React.FC<CalendarDayProps> = React.memo(
focusVisibleMode={active ? 'outside' : 'inside'}
onPointerEnter={handleEnter}
onPointerLeave={handleLeave}
data-testid={typeof testId === 'string' ? testId : testId?.(day)}
{...restProps}
>
<div
Expand Down
10 changes: 9 additions & 1 deletion packages/vkui/src/components/CalendarDays/CalendarDays.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,21 @@ import {
CalendarDay,
type CalendarDayElementProps,
type CalendarDayProps,
type CalendarDayTestsProps,
} from '../CalendarDay/CalendarDay';
import { useConfigProvider } from '../ConfigProvider/ConfigProviderContext';
import { RootComponent } from '../RootComponent/RootComponent';
import { Footnote } from '../Typography/Footnote/Footnote';
import styles from './CalendarDays.module.css';

export type CalendarDaysTestsProps = {
dayTestId?: CalendarDayTestsProps['testId'];
};

export interface CalendarDaysProps
extends Omit<HTMLAttributesWithRootRef<HTMLDivElement>, 'onChange'>,
Pick<CalendarDayProps, 'renderDayContent'> {
Pick<CalendarDayProps, 'renderDayContent'>,
CalendarDaysTestsProps {
value?: Date | Array<Date | null>;
viewDate: Date;
weekStartsOn: 0 | 1 | 2 | 3 | 4 | 5 | 6;
Expand Down Expand Up @@ -61,6 +67,7 @@ export const CalendarDays = ({
listenDayChangesForUpdate = false,
getRootRef,
renderDayContent,
dayTestId,
...props
}: CalendarDaysProps): React.ReactNode => {
const { locale } = useConfigProvider();
Expand Down Expand Up @@ -129,6 +136,7 @@ export const CalendarDays = ({
sameMonth={sameMonth}
size={size}
renderDayContent={renderDayContent}
testId={dayTestId}
{...dayProps}
/>
);
Expand Down
Loading

0 comments on commit e71de15

Please sign in to comment.