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

Adm-909[frontend] sort time range #1394

Merged
merged 34 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
8f5133d
ADM-909:[frontend]add sort button
pfpatrick Apr 9, 2024
2f364ba
ADM-909:[frontend]should not show sort button in three situation
pfpatrick Apr 9, 2024
7dc7d4d
[kai.zhou]: refact date range event handle part
Apr 10, 2024
edbefce
[kai.zhou]: demo about sortby type
Apr 10, 2024
b85ac4c
ADM-909:[frontend]sort time range
pfpatrick Apr 10, 2024
c0a45e0
ADM-909:[frontend]compatible with import & save
pfpatrick Apr 11, 2024
94f97bf
[front][feat]: set sort button shown about date range valid
Apr 11, 2024
8cc368f
[front][feat]: fix issue about data range can not to success status
Apr 11, 2024
edd2442
[frontend][kai.zhou]: replace event name onError to onChange
Apr 11, 2024
884a085
[frontend][kai.zhou]: refactor error check function to parent container
Apr 11, 2024
52d2abd
ADM-909:[frontend]add test for configSlice
pfpatrick Apr 12, 2024
39cfcce
ADM-909:[frontend]debug handle error
pfpatrick Apr 12, 2024
8785b14
[frontend]: reactor onchange event
Apr 12, 2024
6457f75
[frontend]: fix error status
Apr 12, 2024
2453f7f
[frontend]: fix unhandle error
Apr 12, 2024
e342999
[forntend]: replace redux data to state
Apr 12, 2024
507a2d7
ADM-909:[frontend]fix change end date according to test
pfpatrick Apr 14, 2024
2f73289
ADM-909:[frontend]fix change end date when input year the date plus one
pfpatrick Apr 14, 2024
705802d
ADM-909:[frontend]add test
pfpatrick Apr 15, 2024
1fa18bc
[frontend]: fix issue about unit test
Apr 15, 2024
cb16613
ADM-909:[frontend]add test for dateRangePickerSection
pfpatrick Apr 15, 2024
8a30638
ADM-909:[frontend]fix type
pfpatrick Apr 15, 2024
526b107
ADM-909:[frontend]fix test
pfpatrick Apr 15, 2024
958c8a4
ADM-909:[frontend]fix comments
pfpatrick Apr 16, 2024
8b0fee6
ADM-909:[frontend]change with comments
pfpatrick Apr 16, 2024
04b42fc
ADM-909:[frontend]change SortType to ISortType
pfpatrick Apr 16, 2024
ac90516
ADM-909:[frontend]fix test
pfpatrick Apr 16, 2024
84ca073
ADM-909:[frontend]changes according to comments
pfpatrick Apr 16, 2024
086549d
ADM-909:[frontend]rename SortDateRange to SortingDateRange
pfpatrick Apr 16, 2024
fe5843e
ADM-909:[frontend]fix lint
pfpatrick Apr 16, 2024
9456531
ADM-909:[frontend]change ISortedDateRangeType to SortedDateRangeType
pfpatrick Apr 16, 2024
124d18e
ADM-909:[frontend]change to SORTING_DATE_RANGE_TEXT
pfpatrick Apr 17, 2024
62acc3d
ADM-909:[frontend]fix e2e test
pfpatrick Apr 19, 2024
6ea8d05
Merge branch 'main' into ADM-909-sort-time-range
pfpatrick Apr 19, 2024
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
2 changes: 2 additions & 0 deletions frontend/__tests__/constants/fileConfig/fileConfig.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import {
CHINA_CALENDAR,
DEFAULT_REWORK_SETTINGS,
} from '../../fixtures';
import { SortType } from '@src/containers/ConfigStep/DateRangePicker/DateRangePickerGroup';
import { convertToNewFileConfig } from '@src/constants/fileConfig';

describe('#fileConfig', () => {
const BASIC_NEW_CONFIG = {
projectName: 'ConfigFileForImporting',
sortType: SortType.DEFAULT,
dateRange: [
{
startDate: '2023-03-16T00:00:00.000+08:00',
Expand Down
105 changes: 77 additions & 28 deletions frontend/__tests__/containers/ConfigStep/DateRangePicker.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ const setup = () => {
};

describe('DateRangePickerSection', () => {
beforeEach(() => {
setup();
});
describe('Single range behaviors', () => {
const expectDate = (inputDate: HTMLInputElement) => {
expect(inputDate.value).toEqual(expect.stringContaining(TODAY.date().toString()));
Expand All @@ -44,33 +47,25 @@ describe('DateRangePickerSection', () => {
};

it('should render DateRangePicker', () => {
setup();

expect(screen.queryAllByText(START_DATE_LABEL)).toHaveLength(1);
expect(screen.queryAllByText(END_DATE_LABEL)).toHaveLength(1);
});

it('should show right start date when input a valid date given init start date is null ', async () => {
setup();

const startDateInput = screen.getByRole('textbox', { name: START_DATE_LABEL }) as HTMLInputElement;
await userEvent.type(startDateInput, INPUT_DATE_VALUE);

expectDate(startDateInput);
});

it('should show right end date when input a valid date given init end date is null ', async () => {
setup();

const endDateInput = screen.getByRole('textbox', { name: END_DATE_LABEL }) as HTMLInputElement;

await userEvent.type(endDateInput, INPUT_DATE_VALUE);
expectDate(endDateInput);
});

it('should Auto-fill endDate which is after startDate 13 days when fill right startDate ', async () => {
setup();

const endDate = TODAY.add(13, 'day');
const startDateInput = screen.getByRole('textbox', { name: START_DATE_LABEL }) as HTMLInputElement;
const endDateInput = screen.getByRole('textbox', { name: END_DATE_LABEL }) as HTMLInputElement;
Expand All @@ -82,8 +77,6 @@ describe('DateRangePickerSection', () => {
});

it('should Auto-clear endDate when its corresponding startDate is cleared ', async () => {
setup();

const addButton = screen.getByLabelText('Button for adding date range');
await userEvent.click(addButton);
const rangeDate1 = ['03/01/2024', '03/10/2024'];
Expand All @@ -98,8 +91,6 @@ describe('DateRangePickerSection', () => {
});

it('should not auto change startDate when its corresponding endDate changes ', async () => {
setup();

const startDateInput = screen.getByRole('textbox', { name: START_DATE_LABEL }) as HTMLInputElement;
const endDateInput = screen.getByRole('textbox', { name: END_DATE_LABEL }) as HTMLInputElement;
const startDate = dayjs('2024-03-20').format('MM/DD/YYYY');
Expand All @@ -113,8 +104,6 @@ describe('DateRangePickerSection', () => {
});

it('should not Auto-fill endDate which is after startDate 14 days when fill wrong format startDate ', async () => {
setup();

const startDateInput = screen.getByRole('textbox', { name: START_DATE_LABEL }) as HTMLInputElement;
const endDateInput = screen.getByRole('textbox', { name: END_DATE_LABEL }) as HTMLInputElement;
await userEvent.type(startDateInput, ERROR_DATE);
Expand All @@ -124,8 +113,6 @@ describe('DateRangePickerSection', () => {
});

it('should dispatch update configuration when change startDate', async () => {
setup();

const startDateInput = screen.getByRole('textbox', { name: START_DATE_LABEL }) as HTMLInputElement;
await userEvent.type(startDateInput, INPUT_DATE_VALUE);

Expand All @@ -135,8 +122,6 @@ describe('DateRangePickerSection', () => {
});

it('should dispatch update configuration when change endDate', async () => {
setup();

const endDateInput = screen.getByRole('textbox', { name: END_DATE_LABEL }) as HTMLInputElement;
await userEvent.type(endDateInput, INPUT_DATE_VALUE);

Expand All @@ -148,8 +133,6 @@ describe('DateRangePickerSection', () => {

describe('Multiple range amount behaviors', () => {
it('should not show remove button given there is only one range by default', () => {
setup();

const removeButton = screen.queryByRole('button', { name: 'Remove' });
const ranges = screen.getAllByLabelText('Range picker row');

Expand All @@ -158,8 +141,6 @@ describe('DateRangePickerSection', () => {
});

it('should allow user to add up to 6 ranges', async () => {
setup();

const addButton = screen.getByLabelText('Button for adding date range');
const defaultRanges = screen.getAllByLabelText('Range picker row');

Expand All @@ -173,8 +154,6 @@ describe('DateRangePickerSection', () => {
});

it('should show remove button when ranges are more than 1 and user is able to remove the range itself by clicking the remove button within that row', async () => {
setup();

const addButton = screen.getByLabelText('Button for adding date range');
await userEvent.click(addButton);
const ranges = screen.getAllByLabelText('Range picker row');
Expand All @@ -194,8 +173,6 @@ describe('DateRangePickerSection', () => {
});

it('should dispatch update configuration when remove the range', async () => {
setup();

const addButton = screen.getByLabelText('Button for adding date range');
await userEvent.click(addButton);
const ranges = screen.getAllByLabelText('Range picker row');
Expand All @@ -216,7 +193,6 @@ describe('DateRangePickerSection', () => {

describe('Multiple ranges date interactions', () => {
it('should auto fill end date when change star date by cloeset earliest date of other ranges', async () => {
setup();
const rangeDate1 = ['03/12/2024', '03/25/2024'];
const rangeDate2 = ['03/08/2024'];

Expand All @@ -237,7 +213,6 @@ describe('DateRangePickerSection', () => {
});

it('should display error message for start-date and end-date respectively when time ranges conflict', async () => {
setup();
const rangeDate1 = ['03/12/2024', '03/25/2024'];
const rangeDate2 = ['03/08/2024', '03/26/2024'];

Expand All @@ -258,4 +233,78 @@ describe('DateRangePickerSection', () => {
expect(screen.getByText(TIME_RANGE_ERROR_MESSAGE.END_DATE_INVALID_TEXT)).toBeVisible();
});
});

describe('Sort date range behaviors', () => {
it('should not show sort button given only one date range', async () => {
const rangeDate1 = ['03/15/2024', '03/25/2024'];
const ranges = screen.getAllByLabelText('Range picker row');
const startDate1Input = within(ranges[0]).getByRole('textbox', { name: START_DATE_LABEL }) as HTMLInputElement;
const endDate1Input = within(ranges[0]).getByRole('textbox', { name: END_DATE_LABEL }) as HTMLInputElement;
await userEvent.type(startDate1Input, rangeDate1[0]);
await userEvent.type(endDate1Input, rangeDate1[1]);
const sortButtonContainer = screen.queryByLabelText('Sorting date range');
expect(sortButtonContainer).toBeNull();
});
});

it('should show sort button given more than one time range', async () => {
const rangeDate1 = ['03/15/2024', '03/25/2024'];
const rangeDate2 = ['03/08/2024', '03/11/2024'];

const addButton = screen.getByLabelText('Button for adding date range');
await userEvent.click(addButton);
const ranges = screen.getAllByLabelText('Range picker row');
const startDate1Input = within(ranges[0]).getByRole('textbox', { name: START_DATE_LABEL }) as HTMLInputElement;
const endDate1Input = within(ranges[0]).getByRole('textbox', { name: END_DATE_LABEL }) as HTMLInputElement;
const startDate2Input = within(ranges[1]).getByRole('textbox', { name: START_DATE_LABEL }) as HTMLInputElement;
const endDate12nput = within(ranges[1]).getByRole('textbox', { name: END_DATE_LABEL }) as HTMLInputElement;
await userEvent.type(startDate1Input, rangeDate1[0]);
await userEvent.type(endDate1Input, rangeDate1[1]);
await userEvent.type(startDate2Input, rangeDate2[0]);
await userEvent.type(endDate12nput, rangeDate2[1]);
const sortButton = screen.getByLabelText('Sorting date range');
expect(sortButton).toBeInTheDocument();
});

it('should not show sort button given exist errors in date range', async () => {
const rangeDate1 = ['03/12/2024', '03/25/2024'];
const rangeDate2 = ['03/08/2024', '03/26/2024'];

const addButton = screen.getByLabelText('Button for adding date range');
await userEvent.click(addButton);
await userEvent.click(addButton);
const ranges = screen.getAllByLabelText('Range picker row');
const startDate1Input = within(ranges[0]).getByRole('textbox', { name: START_DATE_LABEL }) as HTMLInputElement;
const endDate1Input = within(ranges[0]).getByRole('textbox', { name: END_DATE_LABEL }) as HTMLInputElement;
const startDate2Input = within(ranges[1]).getByRole('textbox', { name: START_DATE_LABEL }) as HTMLInputElement;
const endDate12nput = within(ranges[1]).getByRole('textbox', { name: END_DATE_LABEL }) as HTMLInputElement;
await userEvent.type(startDate1Input, rangeDate1[0]);
await userEvent.type(endDate1Input, rangeDate1[1]);
await userEvent.type(startDate2Input, rangeDate2[0]);
await userEvent.type(endDate12nput, rangeDate2[1]);
const sortButtonContainer = screen.queryByLabelText('Sorting date range');
expect(sortButtonContainer).toBeNull();
});

it('should update sort status when handleSortTypeChange is called', async () => {
const rangeDate1 = ['03/15/2024', '03/25/2024'];
const rangeDate2 = ['03/08/2024', '03/11/2024'];

const addButton = screen.getByLabelText('Button for adding date range');
await userEvent.click(addButton);
const ranges = screen.getAllByLabelText('Range picker row');
const startDate1Input = within(ranges[0]).getByRole('textbox', { name: START_DATE_LABEL }) as HTMLInputElement;
const endDate1Input = within(ranges[0]).getByRole('textbox', { name: END_DATE_LABEL }) as HTMLInputElement;
const startDate2Input = within(ranges[1]).getByRole('textbox', { name: START_DATE_LABEL }) as HTMLInputElement;
const endDate12nput = within(ranges[1]).getByRole('textbox', { name: END_DATE_LABEL }) as HTMLInputElement;
await userEvent.type(startDate1Input, rangeDate1[0]);
await userEvent.type(endDate1Input, rangeDate1[1]);
await userEvent.type(startDate2Input, rangeDate2[0]);
await userEvent.type(endDate12nput, rangeDate2[1]);
const sortButton = screen.getByLabelText('sort button');
await userEvent.click(sortButton);
expect(screen.getByRole('button', { name: 'Descending' })).toBeInTheDocument();
await userEvent.click(sortButton);
expect(screen.getByRole('button', { name: 'Ascending' })).toBeInTheDocument();
});
});
63 changes: 63 additions & 0 deletions frontend/__tests__/containers/ConfigStep/SortingDateRange.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { SortingDateRange } from '@src/containers/ConfigStep/DateRangePicker/SortingDateRange';
import { SortType } from '@src/containers/ConfigStep/DateRangePicker/DateRangePickerGroup';
import { updateDateRangeSortType } from '@src/context/config/configSlice';
import { setupStore } from '@test/utils/setupStoreUtil';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Provider } from 'react-redux';
import React from 'react';

let store = setupStore();
const setup = () => {
store = setupStore();
return render(
<Provider store={store}>
<SortingDateRange onChange={() => {}} sortType={SortType.DEFAULT} />
</Provider>,
);
};
jest.mock('@src/context/config/configSlice', () => ({
...jest.requireActual('@src/context/config/configSlice'),
updateDateRangeSortType: jest.fn().mockReturnValue({ type: 'SHOULD_UPDATE_SORT_STATUS' }),
}));

describe('SortDateRange button behaviors', () => {
it('should show sort time rang button', () => {
setup();
const sortButtonContainer = screen.getByLabelText('Sorting date range');
expect(sortButtonContainer).toBeInTheDocument();

const sortTextButton = screen.getByText('Default sort');
expect(sortTextButton).toBeInTheDocument();

const sortButton = screen.getByLabelText('sort button');
expect(sortButton).toBeInTheDocument();
});

it('should change sort order given SortButton is clicked', async () => {
setup();
const sortButtonContainer = screen.getByLabelText('Sorting date range');
expect(sortButtonContainer).toBeInTheDocument();

const sortTextButton = screen.getByText('Default sort');

expect(sortTextButton).toBeInTheDocument();

const sortButton = screen.getByLabelText('sort button');
await userEvent.click(sortButton);

expect(updateDateRangeSortType).toHaveBeenCalledTimes(1);
expect(updateDateRangeSortType).toHaveBeenCalledWith(SortType.DESCENDING);
});

it('should render right icon with sort status', async () => {
setup();
const sortButton = screen.getByLabelText('sort button');
await userEvent.click(sortButton);
const arrowDropDown = screen.getByRole('button', { name: 'Descending' });
expect(arrowDropDown).toBeInTheDocument();
await userEvent.click(sortButton);
const arrowDropUp = screen.getByRole('button', { name: 'Ascending' });
expect(arrowDropUp).toBeInTheDocument();
});
});
9 changes: 9 additions & 0 deletions frontend/__tests__/context/configSlice.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import configReducer, {
selectSteps,
updateCalendarType,
updateDateRange,
updateDateRangeSortType,
updateMetrics,
updateProjectCreatedState,
updateProjectName,
} from '@src/context/config/configSlice';
import { CHINA_CALENDAR, CONFIG_PAGE_VERIFY_IMPORT_ERROR_MESSAGE, REGULAR_CALENDAR, VELOCITY } from '../fixtures';
import { SortType } from '@src/containers/ConfigStep/DateRangePicker/DateRangePickerGroup';
import { setupStore } from '@test/utils/setupStoreUtil';
import initialConfigState from '../initialConfigState';

Expand Down Expand Up @@ -50,6 +52,13 @@ describe('config reducer', () => {
expect(config.dateRange[0].endDate).toEqual('');
});

it('should update date range sort type with given sort type', () => {
const newSortType = SortType.DEFAULT;
const config = configReducer(initialConfigState, updateDateRangeSortType(newSortType)).basic;

expect(config.sortType).toEqual(newSortType);
});

it('should isProjectCreated is false when import file', () => {
const config = configReducer(initialConfigState, updateProjectCreatedState(false));

Expand Down
2 changes: 2 additions & 0 deletions frontend/__tests__/fixtures.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SortType } from '@src/containers/ConfigStep/DateRangePicker/DateRangePickerGroup';
import { CSVReportRequestDTO, ReportRequestDTO } from '@src/clients/report/dto/request';
import { ReportResponseDTO } from '@src/clients/report/dto/response';
import { SOURCE_CONTROL_TYPES } from '@src/constants/resources';
Expand Down Expand Up @@ -224,6 +225,7 @@ export const MOCK_GENERATE_REPORT_REQUEST_PARAMS: ReportRequestDTO = {
export const IMPORTED_NEW_CONFIG_FIXTURE = {
projectName: 'ConfigFileForImporting',
metrics: ['Velocity', 'Cycle time', 'Classification', 'Lead time for changes'],
sortType: SortType.DEFAULT,
dateRange: [
{
startDate: '2023-03-16T00:00:00.000+08:00',
Expand Down
2 changes: 2 additions & 0 deletions frontend/__tests__/initialConfigState.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SortType } from '@src/containers/ConfigStep/DateRangePicker/DateRangePickerGroup';
import { BOARD_TYPES, PIPELINE_TOOL_TYPES, REGULAR_CALENDAR } from './fixtures';
import { BasicConfigState } from '@src/context/config/configSlice';
import { SOURCE_CONTROL_TYPES } from '@src/constants/resources';
Expand All @@ -13,6 +14,7 @@ const initialConfigState: BasicConfigState = {
endDate: null,
},
],
sortType: SortType.DEFAULT,
metrics: [],
},
board: {
Expand Down
2 changes: 2 additions & 0 deletions frontend/e2e/fixtures/create-new/config-step.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const config = {
endDate: '2024-01-19T23:59:59.999+08:00',
},
],
sortType: 'DEFAULT',
calendarType: 'Calendar with Chinese Holiday',
metrics: [
'Velocity',
Expand Down Expand Up @@ -42,6 +43,7 @@ export const configWithoutBlockColumn = {
endDate: '2024-04-08T23:59:59.999+08:00',
},
],
sortType: 'DEFAULT',
calendarType: 'Calendar with Chinese Holiday',
metrics: ['Cycle time'],
board: {
Expand Down
2 changes: 2 additions & 0 deletions frontend/e2e/fixtures/create-new/metrics-step.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const config = {
endDate: '2024-01-19T23:59:59.999+08:00',
},
],
sortType: 'DEFAULT',
calendarType: 'Calendar with Chinese Holiday',
metrics: [
'Velocity',
Expand Down Expand Up @@ -112,6 +113,7 @@ export const modifiedConfig = {
startDate: '2024-01-15T00:00:00.000+08:00',
endDate: '2024-01-19T23:59:59.999+08:00',
},
sortType: 'DEFAULT',
calendarType: 'Calendar with Chinese Holiday',
metrics: [
'Velocity',
Expand Down
Loading
Loading