Re-write test with storybook testing library (#150)

* Re-write test with storybook testing library

* Update CI
This commit is contained in:
Charles Bochet
2023-05-29 11:02:38 +02:00
committed by GitHub
parent 8f88605f32
commit f935a6b723
65 changed files with 8085 additions and 5164 deletions
@@ -1,102 +0,0 @@
import { ThemeProvider } from '@emotion/react';
import { lightTheme } from '../../../../layout/styles/themes';
import { FilterDropdownButton } from '../FilterDropdownButton';
import styled from '@emotion/styled';
import { useCallback, useState } from 'react';
import { SEARCH_COMPANY_QUERY } from '../../../../services/api/search/search';
import { MockedProvider } from '@apollo/client/testing';
import { availableFilters } from '../../../../pages/people/people-filters';
import { Person } from '../../../../interfaces/entities/person.interface';
import {
FilterableFieldsType,
SelectedFilterType,
} from '../../../../interfaces/filters/interface';
import { mockCompaniesData } from '../../../../pages/companies/__tests__/__data__/mock-data';
import { QueryMode } from '../../../../generated/graphql';
const component = {
title: 'FilterDropdownButton',
component: FilterDropdownButton,
};
export default component;
type OwnProps<FilterProperties extends FilterableFieldsType> = {
setFilter: (filters: SelectedFilterType<FilterProperties>) => void;
};
const mocks = [
{
request: {
query: SEARCH_COMPANY_QUERY,
variables: {
where: { name: { contains: '%%', mode: QueryMode.Insensitive } },
limit: 5,
},
},
result: {
data: {
searchResults: mockCompaniesData,
},
},
},
{
request: {
query: SEARCH_COMPANY_QUERY,
variables: {
where: { name: { contains: '%Airc%', mode: QueryMode.Insensitive } },
limit: 5,
},
},
result: {
data: {
searchResults: mockCompaniesData.filter(
(company) => company.name === 'Aircall',
),
},
},
},
];
const StyleDiv = styled.div`
height: 200px;
width: 200px;
`;
const InnerRegularFilterDropdownButton = ({
setFilter: setFilters,
}: OwnProps<Person>) => {
const [, innerSetFilters] = useState<SelectedFilterType<Person>>();
const outerSetFilters = useCallback(
(filter: SelectedFilterType<Person>) => {
innerSetFilters(filter);
setFilters(filter);
},
[setFilters],
);
return (
<StyleDiv>
<FilterDropdownButton<Person>
availableFilters={availableFilters}
isFilterSelected={true}
onFilterSelect={outerSetFilters}
onFilterRemove={(filterId) => {
console.log(filterId);
}}
/>
</StyleDiv>
);
};
export const RegularFilterDropdownButton = ({
setFilter: setFilters,
}: OwnProps<Person>) => {
return (
<MockedProvider mocks={mocks}>
<ThemeProvider theme={lightTheme}>
<InnerRegularFilterDropdownButton setFilter={setFilters} />
</ThemeProvider>
</MockedProvider>
);
};
@@ -1,75 +0,0 @@
import SortAndFilterBar from '../SortAndFilterBar';
import { ThemeProvider } from '@emotion/react';
import { lightTheme } from '../../../../layout/styles/themes';
import { FaArrowDown } from 'react-icons/fa';
import { Person } from '../../../../interfaces/entities/person.interface';
import { SelectedFilterType } from '../../../../interfaces/filters/interface';
const component = {
title: 'SortAndFilterBar',
component: SortAndFilterBar,
};
export default component;
type OwnProps = {
removeFunction: () => void;
cancelFunction: () => void;
};
export const RegularSortAndFilterBar = ({
removeFunction,
cancelFunction,
}: OwnProps) => {
const personFilter = {
label: 'People',
operand: {
label: 'Is',
id: 'is',
whereTemplate: (person: Person) => {
return { email: { equals: person.email } };
},
},
key: 'test_filter',
icon: <FaArrowDown />,
displayValue: 'john@doedoe.com',
value: {
__typename: 'people',
id: 'test',
email: 'john@doedoe.com',
firstname: 'John',
lastname: 'Doe',
phone: '123456789',
company: null,
creationDate: new Date(),
pipes: null,
city: 'Paris',
},
} satisfies SelectedFilterType<Person, Person>;
return (
<ThemeProvider theme={lightTheme}>
<SortAndFilterBar
sorts={[
{
label: 'Test sort',
order: 'asc',
key: 'test_sort',
icon: <FaArrowDown />,
_type: 'default_sort',
},
{
label: 'Test sort 2',
order: 'desc',
key: 'test_sort_2',
icon: <FaArrowDown />,
_type: 'default_sort',
},
]}
onRemoveSort={removeFunction}
onRemoveFilter={removeFunction}
onCancelClick={cancelFunction}
filters={[personFilter] as SelectedFilterType<Person>[]}
/>
</ThemeProvider>
);
};
@@ -1,88 +0,0 @@
import { ThemeProvider } from '@emotion/react';
import { lightTheme } from '../../../../layout/styles/themes';
import { SortDropdownButton } from '../SortDropdownButton';
import styled from '@emotion/styled';
import {
SortOrder as Order_By,
PersonOrderByWithRelationInput as People_Order_By,
} from '../../../../generated/graphql';
import { SortType } from '../../../../interfaces/sorts/interface';
import {
TbBuilding,
TbCalendar,
TbMail,
TbMapPin,
TbPhone,
TbUser,
} from 'react-icons/tb';
const component = {
title: 'SortDropdownButton',
component: SortDropdownButton,
};
export default component;
type OwnProps = {
setSorts: () => void;
};
const availableSorts = [
{
key: 'fullname',
label: 'People',
icon: <TbUser size={16} />,
_type: 'custom_sort',
orderByTemplates: [() => ({ email: Order_By.Asc })],
},
{
key: 'company_name',
label: 'Company',
icon: <TbBuilding size={16} />,
_type: 'custom_sort',
orderByTemplates: [() => ({ email: Order_By.Asc })],
},
{
key: 'email',
label: 'Email',
icon: <TbMail size={16} />,
_type: 'default_sort',
},
{
key: 'phone',
label: 'Phone',
icon: <TbPhone size={16} />,
_type: 'default_sort',
},
{
key: 'createdAt',
label: 'Created at',
icon: <TbCalendar size={16} />,
_type: 'default_sort',
},
{
key: 'city',
label: 'City',
icon: <TbMapPin size={16} />,
_type: 'default_sort',
},
] satisfies SortType<People_Order_By>[];
const StyleDiv = styled.div`
height: 200px;
width: 200px;
`;
export const RegularSortDropdownButton = ({ setSorts }: OwnProps) => {
return (
<ThemeProvider theme={lightTheme}>
<StyleDiv>
<SortDropdownButton<People_Order_By>
isSortSelected={true}
availableSorts={availableSorts}
onSortSelect={setSorts}
/>
</StyleDiv>
</ThemeProvider>
);
};
@@ -1,43 +0,0 @@
import SortOrFilterChip from '../SortOrFilterChip';
import { ThemeProvider } from '@emotion/react';
import { lightTheme } from '../../../../layout/styles/themes';
import { FaArrowDown } from 'react-icons/fa';
import { TbUser } from 'react-icons/tb';
const component = {
title: 'SortOrFilterChip',
component: SortOrFilterChip,
};
export default component;
type OwnProps = {
removeFunction: () => void;
};
export const RegularFilterChip = ({ removeFunction }: OwnProps) => {
return (
<ThemeProvider theme={lightTheme}>
<SortOrFilterChip
id="test_sort"
icon={<TbUser size={16} />}
labelKey="Account owner"
labelValue="is Charles"
onRemove={removeFunction}
/>
</ThemeProvider>
);
};
export const RegularSortChip = ({ removeFunction }: OwnProps) => {
return (
<ThemeProvider theme={lightTheme}>
<SortOrFilterChip
id="test_sort"
icon={<FaArrowDown />}
labelValue="Created at"
onRemove={removeFunction}
/>
</ThemeProvider>
);
};
@@ -1,51 +0,0 @@
import TableHeader from '../TableHeader';
import { ThemeProvider } from '@emotion/react';
import { lightTheme } from '../../../../layout/styles/themes';
import { SortType } from '../../../../interfaces/sorts/interface';
import { MockedProvider } from '@apollo/client/testing';
import { EMPTY_QUERY } from '../../../../services/api/search/search';
import { TbBuilding, TbCalendar } from 'react-icons/tb';
const component = {
title: 'TableHeader',
component: TableHeader,
};
const mocks = [
{
request: {
query: EMPTY_QUERY,
variables: {
where: undefined,
},
},
result: {
data: {
searchResults: [],
},
},
},
];
export default component;
export const RegularTableHeader = () => {
const availableSorts: Array<SortType<Record<'created_at', 'asc'>>> = [
{
key: 'created_at',
label: 'Created at',
icon: <TbCalendar size={16} />,
_type: 'default_sort',
},
];
return (
<MockedProvider mocks={mocks}>
<ThemeProvider theme={lightTheme}>
<TableHeader
viewName="Test"
viewIcon={<TbBuilding size={16} />}
availableSorts={availableSorts}
/>
</ThemeProvider>
</MockedProvider>
);
};
@@ -1,117 +0,0 @@
import { fireEvent, render, waitFor } from '@testing-library/react';
import { RegularFilterDropdownButton } from '../__stories__/FilterDropdownButton.stories';
it('Checks the default top option is Is', async () => {
const setFilters = jest.fn();
const { getByText } = render(
<RegularFilterDropdownButton setFilter={setFilters} />,
);
const sortDropdownButton = getByText('Filter');
fireEvent.click(sortDropdownButton);
const filterByCompany = getByText('Company');
fireEvent.click(filterByCompany);
await waitFor(() => {
const firstSearchResult = getByText('Airbnb');
expect(firstSearchResult).toBeDefined();
});
const filterByAirbnb = getByText('Airbnb');
fireEvent.click(filterByAirbnb);
expect(setFilters).toHaveBeenCalledWith(
expect.objectContaining({
displayValue: 'Airbnb',
key: 'company_name',
label: 'Company',
}),
);
});
it('Checks the selection of top option for Is Not', async () => {
const setFilters = jest.fn();
const { getByText } = render(
<RegularFilterDropdownButton setFilter={setFilters} />,
);
const sortDropdownButton = getByText('Filter');
fireEvent.click(sortDropdownButton);
const filterByCompany = getByText('Company');
fireEvent.click(filterByCompany);
const openOperandOptions = getByText('Is');
fireEvent.click(openOperandOptions);
const selectOperand = getByText('Is not');
fireEvent.click(selectOperand);
await waitFor(() => {
const firstSearchResult = getByText('Airbnb');
expect(firstSearchResult).toBeDefined();
});
const filterByAirbnb = getByText('Airbnb');
fireEvent.click(filterByAirbnb);
expect(setFilters).toHaveBeenCalledWith(
expect.objectContaining({
displayValue: 'Airbnb',
key: 'company_name',
label: 'Company',
}),
);
const blueSortDropdownButton = getByText('Filter');
await waitFor(() => {
expect(blueSortDropdownButton).toHaveAttribute('aria-selected', 'true');
});
});
it('Calls the filters when typing a new name', async () => {
const setFilters = jest.fn();
const { getByText, getByPlaceholderText, queryByText, getByTestId } = render(
<RegularFilterDropdownButton setFilter={setFilters} />,
);
const sortDropdownButton = getByText('Filter');
fireEvent.click(sortDropdownButton);
const filterByCompany = getByText('Company');
fireEvent.click(filterByCompany);
const filterSearch = getByPlaceholderText('Company');
fireEvent.click(filterSearch);
fireEvent.change(filterSearch, { target: { value: 'Airc' } });
await waitFor(() => {
const loadingDiv = getByTestId('loading-search-results');
expect(loadingDiv).toBeDefined();
});
await waitFor(() => {
const firstSearchResult = getByText('Aircall');
expect(firstSearchResult).toBeDefined();
const airbnbResult = queryByText('Airbnb');
expect(airbnbResult).not.toBeInTheDocument();
});
const filterByAircall = getByText('Aircall');
fireEvent.click(filterByAircall);
expect(setFilters).toHaveBeenCalledWith(
expect.objectContaining({
key: 'company_name',
displayValue: 'Aircall',
label: 'Company',
}),
);
const blueSortDropdownButton = getByText('Filter');
await waitFor(() => {
expect(blueSortDropdownButton).toHaveAttribute('aria-selected', 'true');
});
});
@@ -1,36 +0,0 @@
import { fireEvent, render } from '@testing-library/react';
import { RegularSortAndFilterBar } from '../__stories__/SortAndFilterBar.stories';
it('Checks the SortAndFilterBar renders', async () => {
const removeFunction = jest.fn();
const cancelFunction = jest.fn();
const { getByText, getByTestId } = render(
<RegularSortAndFilterBar
removeFunction={removeFunction}
cancelFunction={cancelFunction}
/>,
);
expect(getByText('Test sort')).toBeDefined();
const removeIcon = getByTestId('remove-icon-test_sort');
fireEvent.click(removeIcon);
expect(removeFunction).toHaveBeenCalled();
});
it('Removes sorts when cancel is pressed', async () => {
const removeFunction = jest.fn();
const cancelFunction = jest.fn();
const { getByTestId } = render(
<RegularSortAndFilterBar
removeFunction={removeFunction}
cancelFunction={cancelFunction}
/>,
);
const cancel = getByTestId('cancel-button');
fireEvent.click(cancel);
expect(cancelFunction).toHaveBeenCalled();
});
@@ -1,74 +0,0 @@
import { fireEvent, render } from '@testing-library/react';
import { RegularSortDropdownButton } from '../__stories__/SortDropdownButton.stories';
import { TbBuilding, TbMail } from 'react-icons/tb';
it('Checks the default top option is Ascending', async () => {
const setSorts = jest.fn();
const { getByText } = render(
<RegularSortDropdownButton setSorts={setSorts} />,
);
const sortDropdownButton = getByText('Sort');
fireEvent.click(sortDropdownButton);
const sortByEmail = getByText('Email');
fireEvent.click(sortByEmail);
expect(setSorts).toHaveBeenCalledWith({
label: 'Email',
key: 'email',
icon: <TbMail size={16} />,
order: 'asc',
_type: 'default_sort',
});
});
it('Checks the selection of Descending', async () => {
const setSorts = jest.fn();
const { getByText } = render(
<RegularSortDropdownButton setSorts={setSorts} />,
);
const sortDropdownButton = getByText('Sort');
fireEvent.click(sortDropdownButton);
const openTopOption = getByText('Ascending');
fireEvent.click(openTopOption);
const selectDescending = getByText('Descending');
fireEvent.click(selectDescending);
const sortByEmail = getByText('Email');
fireEvent.click(sortByEmail);
expect(setSorts).toHaveBeenCalledWith({
label: 'Email',
key: 'email',
icon: <TbMail size={16} />,
order: 'desc',
_type: 'default_sort',
});
});
it('Checks custom_sort is working', async () => {
const setSorts = jest.fn();
const { getByText } = render(
<RegularSortDropdownButton setSorts={setSorts} />,
);
const sortDropdownButton = getByText('Sort');
fireEvent.click(sortDropdownButton);
const sortByCompany = getByText('Company');
fireEvent.click(sortByCompany);
expect(setSorts).toHaveBeenCalledWith(
expect.objectContaining({
key: 'company_name',
label: 'Company',
icon: <TbBuilding size={16} />,
_type: 'custom_sort',
order: 'asc',
}),
);
});
@@ -1,32 +0,0 @@
import { fireEvent, render } from '@testing-library/react';
import {
RegularFilterChip,
RegularSortChip,
} from '../__stories__/SortOrFilterChip.stories';
const removeFunction = jest.fn();
it('Checks the filter chip renders', async () => {
const { getByText, getByTestId } = render(
<RegularFilterChip removeFunction={removeFunction} />,
);
expect(getByText('Account owner:')).toBeDefined();
const removeIcon = getByTestId('remove-icon-test_sort');
fireEvent.click(removeIcon);
expect(removeFunction).toHaveBeenCalled();
});
it('Checks the sort chip renders', async () => {
const { getByText, getByTestId } = render(
<RegularSortChip removeFunction={removeFunction} />,
);
expect(getByText('Created at')).toBeDefined();
const removeIcon = getByTestId('remove-icon-test_sort');
fireEvent.click(removeIcon);
expect(removeFunction).toHaveBeenCalled();
});
@@ -1,20 +0,0 @@
import { fireEvent, render } from '@testing-library/react';
import { RegularTableHeader } from '../__stories__/TableHeader.stories';
it('Checks the TableHeader renders', async () => {
const { getByText, queryByText } = render(<RegularTableHeader />);
const sortDropdownButton = getByText('Sort');
fireEvent.click(sortDropdownButton);
const sortByCreatedAt = getByText('Created at');
fireEvent.click(sortByCreatedAt);
expect(getByText('Created at')).toBeDefined();
const cancelButton = getByText('Cancel');
fireEvent.click(cancelButton);
expect(queryByText('Created at')).toBeNull();
});