mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-25 00:07:47 +01:00
feat: test filter date item (#5576)
This commit is contained in:
parent
879e4c98e5
commit
5d80f5fa4d
@ -0,0 +1,81 @@
|
|||||||
|
import { screen } from '@testing-library/react';
|
||||||
|
import { render } from 'utils/testRenderer';
|
||||||
|
import { vi } from 'vitest';
|
||||||
|
import { FilterItemParams } from '../FilterItem/FilterItem';
|
||||||
|
import { FilterDateItem, IFilterDateItemProps } from './FilterDateItem';
|
||||||
|
|
||||||
|
const getDate = (option: string) => screen.getByText(option);
|
||||||
|
|
||||||
|
const setup = (initialState: FilterItemParams) => {
|
||||||
|
const recordedChanges: FilterItemParams[] = [];
|
||||||
|
const mockProps: IFilterDateItemProps = {
|
||||||
|
label: 'Test Label',
|
||||||
|
onChange: (value: FilterItemParams) => {
|
||||||
|
recordedChanges.push(value);
|
||||||
|
},
|
||||||
|
onChipClose: () => {},
|
||||||
|
operators: ['IS_ON_OR_AFTER', 'IS_BEFORE'],
|
||||||
|
state: initialState,
|
||||||
|
};
|
||||||
|
|
||||||
|
render(<FilterDateItem {...mockProps} />);
|
||||||
|
|
||||||
|
return recordedChanges;
|
||||||
|
};
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vi.restoreAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('FilterDateItem Component', () => {
|
||||||
|
it('renders initial state correctly', async () => {
|
||||||
|
const mockState = {
|
||||||
|
operator: 'IS_ON_OR_AFTER',
|
||||||
|
values: ['2015-01-21'],
|
||||||
|
};
|
||||||
|
|
||||||
|
const recordedChanges = setup(mockState);
|
||||||
|
|
||||||
|
const valuesElement = await screen.findByText('01/21/2015');
|
||||||
|
await screen.findByText('is on or after');
|
||||||
|
expect(valuesElement).toBeInTheDocument();
|
||||||
|
|
||||||
|
valuesElement.click();
|
||||||
|
|
||||||
|
const selectedDate = getDate('21');
|
||||||
|
|
||||||
|
expect(selectedDate).toHaveAttribute('aria-selected', 'true');
|
||||||
|
|
||||||
|
getDate('22').click();
|
||||||
|
|
||||||
|
expect(recordedChanges).toEqual([
|
||||||
|
{
|
||||||
|
operator: 'IS_ON_OR_AFTER',
|
||||||
|
values: ['2015-01-22'],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('switches operator', async () => {
|
||||||
|
const mockState = {
|
||||||
|
operator: 'IS_ON_OR_AFTER',
|
||||||
|
values: ['2020-01-01'],
|
||||||
|
};
|
||||||
|
|
||||||
|
const recordedChanges = setup(mockState);
|
||||||
|
|
||||||
|
const operatorsElement = await screen.findByText('is on or after');
|
||||||
|
|
||||||
|
operatorsElement.click();
|
||||||
|
const newOperator = await screen.findByText('is before');
|
||||||
|
|
||||||
|
newOperator.click();
|
||||||
|
|
||||||
|
expect(recordedChanges).toEqual([
|
||||||
|
{
|
||||||
|
operator: 'IS_BEFORE',
|
||||||
|
values: ['2020-01-01'],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
@ -2,18 +2,18 @@ import { Box } from '@mui/material';
|
|||||||
import React, { FC, useEffect, useRef, useState } from 'react';
|
import React, { FC, useEffect, useRef, useState } from 'react';
|
||||||
import { StyledPopover } from '../FilterItem/FilterItem.styles';
|
import { StyledPopover } from '../FilterItem/FilterItem.styles';
|
||||||
import { FilterItemChip } from '../FilterItem/FilterItemChip/FilterItemChip';
|
import { FilterItemChip } from '../FilterItem/FilterItemChip/FilterItemChip';
|
||||||
import { FilterItem } from '../FilterItem/FilterItem';
|
|
||||||
import { DateCalendar, LocalizationProvider } from '@mui/x-date-pickers';
|
import { DateCalendar, LocalizationProvider } from '@mui/x-date-pickers';
|
||||||
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
|
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
|
||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
import { useLocationSettings } from 'hooks/useLocationSettings';
|
import { useLocationSettings } from 'hooks/useLocationSettings';
|
||||||
import { getLocalizedDateString } from '../util';
|
import { getLocalizedDateString } from '../util';
|
||||||
|
import { FilterItemParams } from '../FilterItem/FilterItem';
|
||||||
|
|
||||||
interface IFilterDateItemProps {
|
export interface IFilterDateItemProps {
|
||||||
label: string;
|
label: string;
|
||||||
onChange: (value: FilterItem | undefined) => void;
|
onChange: (value: FilterItemParams) => void;
|
||||||
onChipClose: () => void;
|
onChipClose: () => void;
|
||||||
state: FilterItem | null | undefined;
|
state: FilterItemParams | null | undefined;
|
||||||
operators: [string, ...string[]];
|
operators: [string, ...string[]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,16 +47,11 @@ export const FilterDateItem: FC<IFilterDateItemProps> = ({
|
|||||||
const selectedDate = state ? new Date(state.values[0]) : null;
|
const selectedDate = state ? new Date(state.values[0]) : null;
|
||||||
const currentOperator = state ? state.operator : operators[0];
|
const currentOperator = state ? state.operator : operators[0];
|
||||||
const onDelete = () => {
|
const onDelete = () => {
|
||||||
onChange(undefined);
|
onChange({ operator: operators[0], values: [] });
|
||||||
onClose();
|
onClose();
|
||||||
onChipClose();
|
onChipClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
const setValue = (value: Date | null) => {
|
|
||||||
const formattedValue = value ? format(value, 'yyyy-MM-dd') : '';
|
|
||||||
onChange({ operator: currentOperator, values: [formattedValue] });
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (state && !operators.includes(state.operator)) {
|
if (state && !operators.includes(state.operator)) {
|
||||||
onChange({
|
onChange({
|
||||||
@ -77,7 +72,10 @@ export const FilterDateItem: FC<IFilterDateItemProps> = ({
|
|||||||
operator={currentOperator}
|
operator={currentOperator}
|
||||||
operatorOptions={operators}
|
operatorOptions={operators}
|
||||||
onChangeOperator={(operator) => {
|
onChangeOperator={(operator) => {
|
||||||
onChange({ operator, values: selectedOptions ?? [] });
|
const formattedValue = selectedDate
|
||||||
|
? format(selectedDate, 'yyyy-MM-dd')
|
||||||
|
: '';
|
||||||
|
onChange({ operator, values: [formattedValue] ?? [] });
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
@ -98,7 +96,15 @@ export const FilterDateItem: FC<IFilterDateItemProps> = ({
|
|||||||
<DateCalendar
|
<DateCalendar
|
||||||
displayWeekNumber
|
displayWeekNumber
|
||||||
value={selectedDate}
|
value={selectedDate}
|
||||||
onChange={(newValue) => setValue(newValue)}
|
onChange={(value) => {
|
||||||
|
const formattedValue = value
|
||||||
|
? format(value, 'yyyy-MM-dd')
|
||||||
|
: '';
|
||||||
|
onChange({
|
||||||
|
operator: currentOperator,
|
||||||
|
values: [formattedValue],
|
||||||
|
});
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</LocalizationProvider>
|
</LocalizationProvider>
|
||||||
</StyledPopover>
|
</StyledPopover>
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
import { render } from 'utils/testRenderer';
|
import { render } from 'utils/testRenderer';
|
||||||
import { FilterItem, IFilterItemProps } from './FilterItem';
|
import { FilterItem, FilterItemParams, IFilterItemProps } from './FilterItem';
|
||||||
|
|
||||||
const getOption = (option: string) =>
|
const getOption = (option: string) =>
|
||||||
screen.getByText(option).closest('li')!.querySelector('input')!;
|
screen.getByText(option).closest('li')!.querySelector('input')!;
|
||||||
|
|
||||||
const setup = (initialState: FilterItem) => {
|
const setup = (initialState: FilterItemParams) => {
|
||||||
const recordedChanges: FilterItem[] = [];
|
const recordedChanges: FilterItemParams[] = [];
|
||||||
const mockProps: IFilterItemProps = {
|
const mockProps: IFilterItemProps = {
|
||||||
label: 'Test Label',
|
label: 'Test Label',
|
||||||
options: [
|
options: [
|
||||||
@ -23,7 +23,7 @@ const setup = (initialState: FilterItem) => {
|
|||||||
value: '3',
|
value: '3',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
onChange: (value: FilterItem) => {
|
onChange: (value: FilterItemParams) => {
|
||||||
recordedChanges.push(value);
|
recordedChanges.push(value);
|
||||||
},
|
},
|
||||||
onChipClose: () => {},
|
onChipClose: () => {},
|
||||||
|
@ -13,14 +13,14 @@ import { FilterItemChip } from './FilterItemChip/FilterItemChip';
|
|||||||
export interface IFilterItemProps {
|
export interface IFilterItemProps {
|
||||||
label: string;
|
label: string;
|
||||||
options: Array<{ label: string; value: string }>;
|
options: Array<{ label: string; value: string }>;
|
||||||
onChange: (value: FilterItem) => void;
|
onChange: (value: FilterItemParams) => void;
|
||||||
onChipClose: () => void;
|
onChipClose: () => void;
|
||||||
state: FilterItem | null | undefined;
|
state: FilterItemParams | null | undefined;
|
||||||
singularOperators: [string, ...string[]];
|
singularOperators: [string, ...string[]];
|
||||||
pluralOperators: [string, ...string[]];
|
pluralOperators: [string, ...string[]];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FilterItem = {
|
export type FilterItemParams = {
|
||||||
operator: string;
|
operator: string;
|
||||||
values: string[];
|
values: string[];
|
||||||
};
|
};
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
import { useEffect, useState, VFC } from 'react';
|
import { useEffect, useState, VFC } from 'react';
|
||||||
import { Box, styled } from '@mui/material';
|
import { Box, styled } from '@mui/material';
|
||||||
import { FilterItem } from 'component/common/FilterItem/FilterItem';
|
|
||||||
import useProjects from 'hooks/api/getters/useProjects/useProjects';
|
import useProjects from 'hooks/api/getters/useProjects/useProjects';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import AddFilterButton from './AddFilterButton';
|
import AddFilterButton from './AddFilterButton';
|
||||||
import { useSegments } from 'hooks/api/getters/useSegments/useSegments';
|
import { useSegments } from 'hooks/api/getters/useSegments/useSegments';
|
||||||
import { FilterDateItem } from '../../../common/FilterDateItem/FilterDateItem';
|
import { FilterDateItem } from 'component/common/FilterDateItem/FilterDateItem';
|
||||||
|
import {
|
||||||
|
FilterItem,
|
||||||
|
FilterItemParams,
|
||||||
|
} from 'component/common/FilterItem/FilterItem';
|
||||||
|
|
||||||
const StyledBox = styled(Box)(({ theme }) => ({
|
const StyledBox = styled(Box)(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@ -14,10 +17,10 @@ const StyledBox = styled(Box)(({ theme }) => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
export type FeatureTogglesListFilters = {
|
export type FeatureTogglesListFilters = {
|
||||||
project?: FilterItem | null | undefined;
|
project?: FilterItemParams | null | undefined;
|
||||||
state?: FilterItem | null | undefined;
|
state?: FilterItemParams | null | undefined;
|
||||||
segment?: FilterItem | null | undefined;
|
segment?: FilterItemParams | null | undefined;
|
||||||
createdAt?: FilterItem | null | undefined;
|
createdAt?: FilterItemParams | null | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
interface IFeatureToggleFiltersProps {
|
interface IFeatureToggleFiltersProps {
|
||||||
|
Loading…
Reference in New Issue
Block a user