From c17cca2b6f5804069d62a35d19d961b6fcb2b7f2 Mon Sep 17 00:00:00 2001 From: Sergey Krylov Date: Thu, 23 May 2024 05:49:58 +0300 Subject: [PATCH] refactor(test): add queries and expects --- .eslintrc | 7 + __spec__/custom-expects/toHaveDataDate.ts | 20 ++ __spec__/custom-queries/byDataDate.ts | 32 +++ __spec__/helpers.ts | 18 ++ __spec__/utils.js | 15 ++ configs/jest/global.d.ts | 10 + configs/jest/setupTests.ts | 7 + jest.config.ts | 1 + src/shared/utils/spec-helpers/date/index.ts | 18 -- .../components/DateCell/ui/DateCell.spec.tsx | 2 +- .../MonthSelect/ui/MonthSelect.spec.jsx | 7 +- .../ui/NextMonthButton.spec.tsx | 7 +- .../ui/PrevMonthButton.spec.tsx | 8 +- .../TodayButton/ui/TodayButton.spec.tsx | 8 +- .../YearSelect/ui/YearSelect.spec.tsx | 8 +- src/widgets/DatePicker/ui/DatePicker.spec.tsx | 208 +++++++++++------- tsconfig.json | 4 +- 17 files changed, 244 insertions(+), 136 deletions(-) create mode 100644 __spec__/custom-expects/toHaveDataDate.ts create mode 100644 __spec__/custom-queries/byDataDate.ts create mode 100644 __spec__/helpers.ts create mode 100644 __spec__/utils.js create mode 100644 configs/jest/global.d.ts delete mode 100644 src/shared/utils/spec-helpers/date/index.ts diff --git a/.eslintrc b/.eslintrc index 006b831..cbbd6c3 100644 --- a/.eslintrc +++ b/.eslintrc @@ -8,6 +8,11 @@ "import/order": [ "error", { "pathGroups": [ + { + "pattern": "__spec__/**", + "group": "builtin", + "position": "before" + }, { "pattern": "apps/**", "group": "internal", @@ -69,6 +74,8 @@ "spec/**", "**/__tests__/**", "**/__mocks__/**", + "**/__spec__/**", + "**/configs/**", "test.{[j|t]sx,[j|t]sx}", "test-*.{[j|t]sx,[j|t]sx}", "**/*{.,_}{test,spec}.{[j|t]sx,[j|t]sx}", diff --git a/__spec__/custom-expects/toHaveDataDate.ts b/__spec__/custom-expects/toHaveDataDate.ts new file mode 100644 index 0000000..bb3debe --- /dev/null +++ b/__spec__/custom-expects/toHaveDataDate.ts @@ -0,0 +1,20 @@ +import type { MatcherFunction } from 'expect'; + +// eslint-disable-next-line func-names +export const toHaveDataDate: MatcherFunction<[dataDate: unknown]> = function (actual, dataDate) { + if (!(actual instanceof HTMLElement)) { + throw new TypeError('These must be HTMLElement!'); + } + + const actualDataDate = actual.getAttribute('data-date'); + const pass = this.equals(actualDataDate, dataDate); + + const message = () => `${this.utils.matcherHint('toHaveDataDate', 'element')}\n\n` + + `Expected element to have data-date attribute:\n ${this.utils.printExpected(dataDate)}\n` + + `Received:\n ${this.utils.printReceived(actualDataDate)}`; + + return { + message, + pass, + }; +}; diff --git a/__spec__/custom-queries/byDataDate.ts b/__spec__/custom-queries/byDataDate.ts new file mode 100644 index 0000000..fc5e3d8 --- /dev/null +++ b/__spec__/custom-queries/byDataDate.ts @@ -0,0 +1,32 @@ +import { queryHelpers, buildQueries } from '@testing-library/react'; + +import type { DataDateString } from 'shared/types/date'; + +import type { GetErrorFunction } from '@testing-library/dom/types/query-helpers'; +import type { Matcher, MatcherOptions } from '@testing-library/react'; + +const queryAllByDataDate = ( + container: HTMLElement, + id: Matcher, + options?: MatcherOptions | undefined, +) => queryHelpers.queryAllByAttribute('data-date', container, id, options); + +const getMultipleError: GetErrorFunction<[id: DataDateString, options?: MatcherOptions | undefined]> = (_, dataDateValue) => `Found multiple elements with the data-date attribute of: ${dataDateValue}`; +const getMissingError: GetErrorFunction<[id: DataDateString, options?: MatcherOptions | undefined]> = (_, dataDateValue: string) => `Unable to find an element with the data-date attribute of: ${dataDateValue}`; + +const [ + queryByDataDate, + getAllByDataDate, + getByDataDate, + findAllByDataDate, + findByDataDate, +] = buildQueries(queryAllByDataDate, getMultipleError, getMissingError); + +export { + queryByDataDate, + queryAllByDataDate, + getByDataDate, + getAllByDataDate, + findAllByDataDate, + findByDataDate, +}; diff --git a/__spec__/helpers.ts b/__spec__/helpers.ts new file mode 100644 index 0000000..8ec956f --- /dev/null +++ b/__spec__/helpers.ts @@ -0,0 +1,18 @@ +import { fireEvent } from '@testing-library/react'; + +import type { DataDateString } from 'shared/types/date'; + +import { screen } from './utils'; + +export const pickCellByDataDate = (dataDate: DataDateString) => { + const cellElem = screen.getByDataDate(dataDate); + fireEvent.click(cellElem); +}; + +export const dragAndDropCellByDataDate = (dragDataDate: DataDateString, dropDataDate: DataDateString) => { + const oldLastDateElem = screen.getByDataDate(dragDataDate); + const dropTarget = screen.getByDataDate(dropDataDate); + + fireEvent.dragStart(oldLastDateElem); + fireEvent.drop(dropTarget); +}; diff --git a/__spec__/utils.js b/__spec__/utils.js new file mode 100644 index 0000000..c3f60f4 --- /dev/null +++ b/__spec__/utils.js @@ -0,0 +1,15 @@ +import { render, queries, within } from '@testing-library/react'; + +import * as customQueries from './custom-queries/byDataDate'; + +const allQueries = { + ...queries, + ...customQueries, +}; + +const customScreen = within(document.body, allQueries); +const customWithin = (element) => within(element, allQueries); +const customRender = (ui, options) => render(ui, { queries: allQueries, ...options }); + +// override render method +export { customScreen as screen, customWithin as within, customRender as render }; diff --git a/configs/jest/global.d.ts b/configs/jest/global.d.ts new file mode 100644 index 0000000..de06351 --- /dev/null +++ b/configs/jest/global.d.ts @@ -0,0 +1,10 @@ +declare global { + namespace jest { + // eslint-disable-next-line @typescript-eslint/consistent-type-definitions + interface Matchers { + toHaveDataDate: (dataDate: string) => R; + } + } +} + +export {}; diff --git a/configs/jest/setupTests.ts b/configs/jest/setupTests.ts index 7b0828b..499620e 100644 --- a/configs/jest/setupTests.ts +++ b/configs/jest/setupTests.ts @@ -1 +1,8 @@ import '@testing-library/jest-dom'; +import { expect } from '@jest/globals'; + +import { toHaveDataDate } from '../../__spec__/custom-expects/toHaveDataDate'; + +expect.extend({ + toHaveDataDate, +}); diff --git a/jest.config.ts b/jest.config.ts index 99cfb5d..84ef5f3 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -7,6 +7,7 @@ const config: Config = { setupFilesAfterEnv: ['./configs/jest/setupTests.ts'], modulePaths: [ 'src', + '', ], verbose: true, preset: 'ts-jest/presets/js-with-ts', diff --git a/src/shared/utils/spec-helpers/date/index.ts b/src/shared/utils/spec-helpers/date/index.ts deleted file mode 100644 index 4953ffe..0000000 --- a/src/shared/utils/spec-helpers/date/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -// eslint-disable-next-line import/no-extraneous-dependencies -import { fireEvent } from '@testing-library/react'; - -import type { DataDateString } from 'shared/types/date'; - -// todo fix -// eslint-disable-next-line @stylistic/no-extra-parens -export const getDateCellByDataDate = (container: HTMLElement, dataDate: DataDateString) => ( - container.querySelector(`[data-date="${dataDate}"]`) -); - -export const pickCellByDataDate = (...params: Parameters) => { - const cellElem = getDateCellByDataDate(...params); - if (!cellElem) { - throw new Error('first cell not found'); - } - fireEvent.click(cellElem); -}; diff --git a/src/widgets/CalendarWidget/ui/components/DateCell/ui/DateCell.spec.tsx b/src/widgets/CalendarWidget/ui/components/DateCell/ui/DateCell.spec.tsx index 20cd412..1323b1b 100644 --- a/src/widgets/CalendarWidget/ui/components/DateCell/ui/DateCell.spec.tsx +++ b/src/widgets/CalendarWidget/ui/components/DateCell/ui/DateCell.spec.tsx @@ -32,6 +32,6 @@ describe('Base Render', () => { setup(new Date(2024, 3, 15)); const dateCellElem = screen.getByTestId('date-cell'); - expect(dateCellElem).toHaveAttribute('data-date', '04/15/2024'); + expect(dateCellElem).toHaveDataDate('04/15/2024'); }); }); diff --git a/src/widgets/CalendarWidget/ui/components/MonthSelect/ui/MonthSelect.spec.jsx b/src/widgets/CalendarWidget/ui/components/MonthSelect/ui/MonthSelect.spec.jsx index e9bdaca..32fdd82 100644 --- a/src/widgets/CalendarWidget/ui/components/MonthSelect/ui/MonthSelect.spec.jsx +++ b/src/widgets/CalendarWidget/ui/components/MonthSelect/ui/MonthSelect.spec.jsx @@ -9,12 +9,7 @@ import { CalendarWidgetProvider } from '../../../CalendarWidgetContext'; import MonthSelect from './MonthSelect.ui'; describe('Test MonthSelect', () => { - let user; - - beforeEach(() => { - user = userEvent.setup(); - }); - + const user = userEvent.setup(); const setup = (props, providerProps) => { const MonthSelectComponent = () => ( diff --git a/src/widgets/CalendarWidget/ui/components/NextMonthButton/ui/NextMonthButton.spec.tsx b/src/widgets/CalendarWidget/ui/components/NextMonthButton/ui/NextMonthButton.spec.tsx index 6e9ad7f..a2e475e 100644 --- a/src/widgets/CalendarWidget/ui/components/NextMonthButton/ui/NextMonthButton.spec.tsx +++ b/src/widgets/CalendarWidget/ui/components/NextMonthButton/ui/NextMonthButton.spec.tsx @@ -9,14 +9,9 @@ import NextMonthButton from './NextMonthButton.ui'; import type { NextMonthButtonProps } from './NextMonthButton.ui'; import type { CalendarWidgetProviderProps } from '../../../CalendarWidgetContext'; -import type { UserEvent } from '@testing-library/user-event'; describe('Test NextMonthButton', () => { - let user: UserEvent; - - beforeEach(() => { - user = userEvent.setup(); - }); + const user = userEvent.setup(); const setup = (props?: NextMonthButtonProps, providerProps?: CalendarWidgetProviderProps) => { const NextMonthButtonComponent = () => ( diff --git a/src/widgets/CalendarWidget/ui/components/PrevMonthButton/ui/PrevMonthButton.spec.tsx b/src/widgets/CalendarWidget/ui/components/PrevMonthButton/ui/PrevMonthButton.spec.tsx index bbde7f1..2028067 100644 --- a/src/widgets/CalendarWidget/ui/components/PrevMonthButton/ui/PrevMonthButton.spec.tsx +++ b/src/widgets/CalendarWidget/ui/components/PrevMonthButton/ui/PrevMonthButton.spec.tsx @@ -8,15 +8,9 @@ import { CalendarWidgetProvider, type CalendarWidgetProviderProps } from '../../ import PrevMonthButton from './PrevMonthButton.ui'; import type { PrevMonthButtonProps } from './PrevMonthButton.ui'; -import type { UserEvent } from '@testing-library/user-event'; describe('Test NextMonthButton', () => { - let user: UserEvent; - - beforeEach(() => { - user = userEvent.setup(); - }); - + const user = userEvent.setup(); const setup = (props?: PrevMonthButtonProps, providerProps?: CalendarWidgetProviderProps) => { const PrevMonthButtonComponent = () => ( diff --git a/src/widgets/CalendarWidget/ui/components/TodayButton/ui/TodayButton.spec.tsx b/src/widgets/CalendarWidget/ui/components/TodayButton/ui/TodayButton.spec.tsx index bfeb961..7fa0039 100644 --- a/src/widgets/CalendarWidget/ui/components/TodayButton/ui/TodayButton.spec.tsx +++ b/src/widgets/CalendarWidget/ui/components/TodayButton/ui/TodayButton.spec.tsx @@ -8,15 +8,9 @@ import { CalendarWidgetProvider } from '../../../CalendarWidgetContext'; import TodayButton from './TodayButton.ui'; import type { TodayButtonProps } from './TodayButton.ui'; -import type { UserEvent } from '@testing-library/user-event'; describe('Test NextMonthButton', () => { - let user: UserEvent; - - beforeEach(() => { - user = userEvent.setup(); - }); - + const user = userEvent.setup(); const setup = (props?: TodayButtonProps) => { const TodayButtonComponent = () => ( diff --git a/src/widgets/CalendarWidget/ui/components/YearSelect/ui/YearSelect.spec.tsx b/src/widgets/CalendarWidget/ui/components/YearSelect/ui/YearSelect.spec.tsx index 7371a6c..fdca1aa 100644 --- a/src/widgets/CalendarWidget/ui/components/YearSelect/ui/YearSelect.spec.tsx +++ b/src/widgets/CalendarWidget/ui/components/YearSelect/ui/YearSelect.spec.tsx @@ -8,15 +8,9 @@ import { CalendarWidgetProvider } from '../../../CalendarWidgetContext'; import YearSelect from './YearSelect.ui'; import type { YearSelectProps } from './YearSelect.ui'; -import type { UserEvent } from '@testing-library/user-event'; describe('Test YearSelect', () => { - let user: UserEvent; - - beforeEach(() => { - user = userEvent.setup(); - }); - + const user = userEvent.setup(); const setup = (props?: YearSelectProps) => { const YearSelectComponent = () => ( diff --git a/src/widgets/DatePicker/ui/DatePicker.spec.tsx b/src/widgets/DatePicker/ui/DatePicker.spec.tsx index 56c189f..4dc89a7 100644 --- a/src/widgets/DatePicker/ui/DatePicker.spec.tsx +++ b/src/widgets/DatePicker/ui/DatePicker.spec.tsx @@ -1,6 +1,5 @@ -import { render, screen } from '@testing-library/react'; - -import { getDateCellByDataDate, pickCellByDataDate } from 'shared/utils/spec-helpers/date'; +import { dragAndDropCellByDataDate, pickCellByDataDate } from '__spec__/helpers'; +import { render, screen } from '__spec__/utils'; import DatePicker from './DatePicker.ui'; @@ -27,7 +26,7 @@ describe('Test DatePicker', () => { const firstPickedCellElem = screen.queryByTestId('first-selected-cell'); expect(firstPickedCellElem).toBeVisible(); - expect(firstPickedCellElem).toHaveAttribute('data-date', '10/11/2024'); + expect(firstPickedCellElem).toHaveDataDate('10/11/2024'); const lastPickedCellElem = screen.queryByTestId('last-selected-cell'); expect(lastPickedCellElem).not.toBeInTheDocument(); @@ -41,7 +40,7 @@ describe('Test DatePicker', () => { const lastPickedCellElem = screen.queryByTestId('last-selected-cell'); expect(lastPickedCellElem).toBeVisible(); - expect(lastPickedCellElem).toHaveAttribute('data-date', '10/18/2024'); + expect(lastPickedCellElem).toHaveDataDate('10/18/2024'); const firstPickedCellElem = screen.queryByTestId('first-selected-cell'); expect(firstPickedCellElem).not.toBeInTheDocument(); @@ -50,13 +49,12 @@ describe('Test DatePicker', () => { describe('onSelect handler', () => { test('No default picked', () => { const onSelect = jest.fn(); - - const { container } = setup({ + setup({ onSelect, value: new Date(2024, 9, 15), }); - pickCellByDataDate(container, '10/18/2024'); + pickCellByDataDate('10/18/2024'); expect(onSelect).toHaveBeenCalled(); expect(onSelect).toHaveBeenCalledWith({ @@ -68,14 +66,13 @@ describe('Test DatePicker', () => { test('Picked first date', () => { const onSelect = jest.fn(); - - const { container } = setup({ + setup({ onSelect, value: new Date(2024, 9, 15), firstDate: new Date(2024, 9, 15), }); - pickCellByDataDate(container, '10/18/2024'); + pickCellByDataDate('10/18/2024'); expect(onSelect).toHaveBeenCalled(); expect(onSelect).toHaveBeenCalledWith({ @@ -87,14 +84,13 @@ describe('Test DatePicker', () => { test('Picked last date', () => { const onSelect = jest.fn(); - - const { container } = setup({ + setup({ onSelect, value: new Date(2024, 9, 15), lastDate: new Date(2024, 9, 15), }); - pickCellByDataDate(container, '10/11/2024'); + pickCellByDataDate('10/11/2024'); expect(onSelect).toHaveBeenCalled(); expect(onSelect).toHaveBeenCalledWith({ @@ -108,15 +104,14 @@ describe('Test DatePicker', () => { describe('onUnselect handler', () => { test('Unpick first date', () => { const onUnselect = jest.fn(); - - const { container } = setup({ + setup({ onUnselect, value: new Date(2024, 9, 15), firstDate: new Date(2024, 9, 15), lastDate: new Date(2024, 9, 18), }); - pickCellByDataDate(container, '10/15/2024'); + pickCellByDataDate('10/15/2024'); expect(onUnselect).toHaveBeenCalled(); expect(onUnselect).toHaveBeenCalledWith({ @@ -128,15 +123,14 @@ describe('Test DatePicker', () => { test('Unpick last date', () => { const onUnselect = jest.fn(); - - const { container } = setup({ + setup({ onUnselect, value: new Date(2024, 9, 15), firstDate: new Date(2024, 9, 15), lastDate: new Date(2024, 9, 18), }); - pickCellByDataDate(container, '10/18/2024'); + pickCellByDataDate('10/18/2024'); expect(onUnselect).toHaveBeenCalled(); expect(onUnselect).toHaveBeenCalledWith({ @@ -150,211 +144,259 @@ describe('Test DatePicker', () => { describe('Test pick date', () => { test('No picked date, select first', () => { - const { container } = setup({ + setup({ value: new Date(2024, 9, 15), }); - - const cellElem = getDateCellByDataDate(container, '10/11/2024'); - pickCellByDataDate(container, '10/11/2024'); + const cellElem = screen.getByDataDate('10/11/2024'); + pickCellByDataDate('10/11/2024'); const firstSelectedCellElem = screen.queryByTestId('first-selected-cell'); expect(firstSelectedCellElem).toBe(cellElem); }); test('Picked first date, pick before first date', () => { - const { container } = setup({ + setup({ value: new Date(2024, 9, 15), firstDate: new Date(2024, 9, 15), }); - - pickCellByDataDate(container, '10/11/2024'); + pickCellByDataDate('10/11/2024'); const firstPickedCellElem = screen.queryByTestId('first-selected-cell'); - expect(firstPickedCellElem).toHaveAttribute('data-date', '10/11/2024'); + expect(firstPickedCellElem).toHaveDataDate('10/11/2024'); const lastPickedCellElem = screen.queryByTestId('last-selected-cell'); - expect(lastPickedCellElem).toHaveAttribute('data-date', '10/15/2024'); + expect(lastPickedCellElem).toHaveDataDate('10/15/2024'); }); test('Picked first date, pick after first date', () => { - const { container } = setup({ + setup({ value: new Date(2024, 9, 15), firstDate: new Date(2024, 9, 15), }); - - pickCellByDataDate(container, '10/18/2024'); + pickCellByDataDate('10/18/2024'); const firstPickedCellElem = screen.queryByTestId('first-selected-cell'); - expect(firstPickedCellElem).toHaveAttribute('data-date', '10/15/2024'); + expect(firstPickedCellElem).toHaveDataDate('10/15/2024'); const lastPickedCellElem = screen.queryByTestId('last-selected-cell'); - expect(lastPickedCellElem).toHaveAttribute('data-date', '10/18/2024'); + expect(lastPickedCellElem).toHaveDataDate('10/18/2024'); }); test('Picked first date, pick this date', () => { - const { container } = setup({ + setup({ value: new Date(2024, 9, 15), firstDate: new Date(2024, 9, 15), }); - - pickCellByDataDate(container, '10/15/2024'); + pickCellByDataDate('10/15/2024'); const firstPickedCellElem = screen.queryByTestId('first-selected-cell'); expect(firstPickedCellElem).not.toBeInTheDocument(); }); test('Picked last date, pick before last date', () => { - const { container } = setup({ + setup({ value: new Date(2024, 9, 15), lastDate: new Date(2024, 9, 15), }); - - pickCellByDataDate(container, '10/11/2024'); + pickCellByDataDate('10/11/2024'); const firstPickedCellElem = screen.queryByTestId('first-selected-cell'); - expect(firstPickedCellElem).toHaveAttribute('data-date', '10/11/2024'); + expect(firstPickedCellElem).toHaveDataDate('10/11/2024'); const lastPickedCellElem = screen.queryByTestId('last-selected-cell'); - expect(lastPickedCellElem).toHaveAttribute('data-date', '10/15/2024'); + expect(lastPickedCellElem).toHaveDataDate('10/15/2024'); }); test('Picked last date, pick after last date', () => { - const { container } = setup({ + setup({ value: new Date(2024, 9, 15), lastDate: new Date(2024, 9, 15), }); - - pickCellByDataDate(container, '10/18/2024'); + pickCellByDataDate('10/18/2024'); const firstPickedCellElem = screen.queryByTestId('first-selected-cell'); - expect(firstPickedCellElem).toHaveAttribute('data-date', '10/15/2024'); + expect(firstPickedCellElem).toHaveDataDate('10/15/2024'); const lastPickedCellElem = screen.queryByTestId('last-selected-cell'); - expect(lastPickedCellElem).toHaveAttribute('data-date', '10/18/2024'); + expect(lastPickedCellElem).toHaveDataDate('10/18/2024'); }); test('Picked last date, pick this date', () => { - const { container } = setup({ + setup({ value: new Date(2024, 9, 15), lastDate: new Date(2024, 9, 15), }); - - pickCellByDataDate(container, '10/15/2024'); + pickCellByDataDate('10/15/2024'); const lastPickedCellElem = screen.queryByTestId('last-selected-cell'); expect(lastPickedCellElem).not.toBeInTheDocument(); }); test('Picked first & last date, pick date before first', () => { - const { container } = setup({ + setup({ value: new Date(2024, 9, 15), firstDate: new Date(2024, 9, 15), lastDate: new Date(2024, 9, 18), }); - - pickCellByDataDate(container, '10/11/2024'); + pickCellByDataDate('10/11/2024'); const firstPickedCellElem = screen.queryByTestId('first-selected-cell'); - expect(firstPickedCellElem).toHaveAttribute('data-date', '10/11/2024'); + expect(firstPickedCellElem).toHaveDataDate('10/11/2024'); const lastPickedCellElem = screen.queryByTestId('last-selected-cell'); - expect(lastPickedCellElem).toHaveAttribute('data-date', '10/18/2024'); + expect(lastPickedCellElem).toHaveDataDate('10/18/2024'); }); test('Picked first & last date, pick date after last', () => { - const { container } = setup({ + setup({ value: new Date(2024, 9, 15), firstDate: new Date(2024, 9, 15), lastDate: new Date(2024, 9, 18), }); - - pickCellByDataDate(container, '10/21/2024'); + pickCellByDataDate('10/21/2024'); const firstPickedCellElem = screen.queryByTestId('first-selected-cell'); - expect(firstPickedCellElem).toHaveAttribute('data-date', '10/15/2024'); + expect(firstPickedCellElem).toHaveDataDate('10/15/2024'); const lastPickedCellElem = screen.queryByTestId('last-selected-cell'); - expect(lastPickedCellElem).toHaveAttribute('data-date', '10/21/2024'); + expect(lastPickedCellElem).toHaveDataDate('10/21/2024'); }); test('Picked first & last date, pick fist date', () => { - const { container } = setup({ + setup({ value: new Date(2024, 9, 15), firstDate: new Date(2024, 9, 15), lastDate: new Date(2024, 9, 18), }); - - pickCellByDataDate(container, '10/15/2024'); + pickCellByDataDate('10/15/2024'); const firstPickedCellElem = screen.queryByTestId('first-selected-cell'); expect(firstPickedCellElem).not.toBeInTheDocument(); const lastPickedCellElem = screen.queryByTestId('last-selected-cell'); - expect(lastPickedCellElem).toHaveAttribute('data-date', '10/18/2024'); + expect(lastPickedCellElem).toHaveDataDate('10/18/2024'); }); test('Picked first & last date, pick last date', () => { - const { container } = setup({ + setup({ value: new Date(2024, 9, 15), firstDate: new Date(2024, 9, 15), lastDate: new Date(2024, 9, 18), }); - - pickCellByDataDate(container, '10/18/2024'); + pickCellByDataDate('10/18/2024'); const firstPickedCellElem = screen.queryByTestId('first-selected-cell'); - expect(firstPickedCellElem).toHaveAttribute('data-date', '10/15/2024'); + expect(firstPickedCellElem).toHaveDataDate('10/15/2024'); const lastPickedCellElem = screen.queryByTestId('last-selected-cell'); expect(lastPickedCellElem).not.toBeInTheDocument(); }); test('Picked first & last date, pick the date closer to first date', () => { - const { container } = setup({ + setup({ value: new Date(2024, 9, 15), firstDate: new Date(2024, 9, 15), lastDate: new Date(2024, 9, 18), }); - - pickCellByDataDate(container, '10/16/2024'); + pickCellByDataDate('10/16/2024'); const firstPickedCellElem = screen.queryByTestId('first-selected-cell'); - expect(firstPickedCellElem).toHaveAttribute('data-date', '10/16/2024'); + expect(firstPickedCellElem).toHaveDataDate('10/16/2024'); const lastPickedCellElem = screen.queryByTestId('last-selected-cell'); - expect(lastPickedCellElem).toHaveAttribute('data-date', '10/18/2024'); + expect(lastPickedCellElem).toHaveDataDate('10/18/2024'); }); test('Picked first & last date, pick the date closer to last date', () => { - const { container } = setup({ + setup({ value: new Date(2024, 9, 15), firstDate: new Date(2024, 9, 15), lastDate: new Date(2024, 9, 18), }); - - pickCellByDataDate(container, '10/17/2024'); + pickCellByDataDate('10/17/2024'); const firstPickedCellElem = screen.queryByTestId('first-selected-cell'); - expect(firstPickedCellElem).toHaveAttribute('data-date', '10/15/2024'); + expect(firstPickedCellElem).toHaveDataDate('10/15/2024'); const lastPickedCellElem = screen.queryByTestId('last-selected-cell'); - expect(lastPickedCellElem).toHaveAttribute('data-date', '10/17/2024'); + expect(lastPickedCellElem).toHaveDataDate('10/17/2024'); }); test('Picked first & last date, pick the equidistant date', () => { - const { container } = setup({ + setup({ value: new Date(2024, 9, 15), firstDate: new Date(2024, 9, 15), lastDate: new Date(2024, 9, 19), }); - - pickCellByDataDate(container, '10/17/2024'); + pickCellByDataDate('10/17/2024'); const firstPickedCellElem = screen.queryByTestId('first-selected-cell'); - expect(firstPickedCellElem).toHaveAttribute('data-date', '10/17/2024'); + expect(firstPickedCellElem).toHaveDataDate('10/17/2024'); const lastPickedCellElem = screen.queryByTestId('last-selected-cell'); - expect(lastPickedCellElem).toHaveAttribute('data-date', '10/19/2024'); + expect(lastPickedCellElem).toHaveDataDate('10/19/2024'); + }); + }); + + describe('Test dragging', () => { + test('Drag first cell and drop earlier end date', () => { + setup({ + firstDate: new Date(2024, 9, 15), + lastDate: new Date(2024, 9, 18), + value: new Date(2024, 9, 15), + }); + dragAndDropCellByDataDate('10/15/2024', '10/11/2024'); + + const newFirstDateElem = screen.getByTestId('first-selected-cell'); + expect(newFirstDateElem).toHaveDataDate('10/11/2024'); + + const lastDateElem = screen.getByTestId('last-selected-cell'); + expect(lastDateElem).toHaveDataDate('10/18/2024'); + }); + + test('Drag last cell and drop later start date', () => { + setup({ + firstDate: new Date(2024, 9, 15), + lastDate: new Date(2024, 9, 18), + value: new Date(2024, 9, 15), + }); + dragAndDropCellByDataDate('10/18/2024', '10/16/2024'); + + const newFirstDateElem = screen.getByTestId('first-selected-cell'); + expect(newFirstDateElem).toHaveDataDate('10/15/2024'); + + const lastDateElem = screen.getByTestId('last-selected-cell'); + expect(lastDateElem).toHaveDataDate('10/16/2024'); + }); + + test('Drag first cell and drop later end date', () => { + setup({ + firstDate: new Date(2024, 9, 15), + lastDate: new Date(2024, 9, 18), + value: new Date(2024, 9, 15), + }); + dragAndDropCellByDataDate('10/15/2024', '10/20/2024'); + + const newFirstDateElem = screen.getByTestId('first-selected-cell'); + expect(newFirstDateElem).toHaveDataDate('10/18/2024'); + + const lastDateElem = screen.getByTestId('last-selected-cell'); + expect(lastDateElem).toHaveDataDate('10/20/2024'); + }); + + test('Drag last cell and drop earlier start date', () => { + setup({ + firstDate: new Date(2024, 9, 15), + lastDate: new Date(2024, 9, 18), + value: new Date(2024, 9, 15), + }); + dragAndDropCellByDataDate('10/18/2024', '10/11/2024'); + + const newFirstDateElem = screen.getByTestId('first-selected-cell'); + expect(newFirstDateElem).toHaveDataDate('10/11/2024'); + + const lastDateElem = screen.getByTestId('last-selected-cell'); + expect(lastDateElem).toHaveDataDate('10/15/2024'); }); }); }); diff --git a/tsconfig.json b/tsconfig.json index 27e1d1e..5ee0f5f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,8 @@ "include": [ "./src", "./configs", - "./jest.config.ts" + "./jest.config.ts", + "./__spec__", ], "compilerOptions": { "allowUnreachableCode": false, @@ -30,6 +31,7 @@ "module": "ESNext", "moduleResolution": "Node", "paths": { + "__spec__/*": ["./__spec__/*"], "*": ["./src/*"] },