Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

patch: pr7705 in v6 #7912

Merged
merged 1 commit into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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