Fix tests and upgrade node_modules (#1227)

* Fix tests

* Fix tests

* Fix 0 in SortandFilterBar
This commit is contained in:
Charles Bochet
2023-08-16 04:38:50 +02:00
committed by GitHub
parent 38c420aab0
commit b503b53062
12 changed files with 2062 additions and 4124 deletions

View File

@ -25,11 +25,11 @@ module.exports = {
},
jest: {
configure: {
"moduleNameMapper": {
moduleNameMapper: {
'~/(.+)': "<rootDir>/src/$1",
'@/(.+)': "<rootDir>/src/modules/$1",
'@testing/(.+)': "<rootDir>/src/testing/$1",
},
}
},
},
};

View File

@ -1,834 +0,0 @@
import selectEvent from 'react-select-event';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { ModalWrapper } from '@/spreadsheet-import/components/core/ModalWrapper';
import { Providers } from '@/spreadsheet-import/components/core/Providers';
import { SpreadsheetImport } from '@/spreadsheet-import/components/SpreadsheetImport';
import { MatchColumnsStep } from '@/spreadsheet-import/components/steps/MatchColumnsStep/MatchColumnsStep';
import { StepType } from '@/spreadsheet-import/components/steps/UploadFlow';
import { mockRsiValues } from '@/spreadsheet-import/tests/mockRsiValues';
import type { Fields } from '@/spreadsheet-import/types';
import '@testing-library/jest-dom';
// TODO: fix this test
const SELECT_DROPDOWN_ID = 'select-dropdown';
const fields: Fields<any> = [
{
icon: null,
label: 'Name',
key: 'name',
fieldType: {
type: 'input',
},
example: 'Stephanie',
},
{
icon: null,
label: 'Mobile Phone',
key: 'mobile',
fieldType: {
type: 'input',
},
example: '+12323423',
},
{
icon: null,
label: 'Is cool',
key: 'is_cool',
fieldType: {
type: 'checkbox',
},
example: 'No',
},
];
const CONTINUE_BUTTON = 'Next';
const MUTATED_ENTRY = 'mutated entry';
const ERROR_MESSAGE = 'Something happened';
describe('Match Columns automatic matching', () => {
test('AutoMatch column and click next', async () => {
const header = ['namezz', 'Phone', 'Email'];
const data = [
['John', '123', 'j@j.com'],
['Dane', '333', 'dane@bane.com'],
['Kane', '534', 'kane@linch.com'],
];
// finds only names with automatic matching
const result = [
{ name: data[0][0] },
{ name: data[1][0] },
{ name: data[2][0] },
];
const onContinue = jest.fn();
render(
<Providers rsiValues={{ ...mockRsiValues, fields }}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<MatchColumnsStep
headerValues={header}
data={data}
onContinue={onContinue}
/>
</ModalWrapper>
</Providers>,
);
const nextButton = screen.getByRole('button', {
name: 'Next',
});
await userEvent.click(nextButton);
await waitFor(() => {
expect(onContinue).toBeCalled();
});
expect(onContinue.mock.calls[0][0]).toEqual(result);
});
test('AutoMatching disabled does not match any columns', async () => {
const header = ['Name', 'Phone', 'Email'];
const data = [
['John', '123', 'j@j.com'],
['Dane', '333', 'dane@bane.com'],
['Kane', '534', 'kane@linch.com'],
];
// finds only names with automatic matching
const result = [{}, {}, {}];
const onContinue = jest.fn();
render(
<Providers
rsiValues={{ ...mockRsiValues, fields, autoMapHeaders: false }}
>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<MatchColumnsStep
headerValues={header}
data={data}
onContinue={onContinue}
/>
</ModalWrapper>
</Providers>,
);
const nextButton = screen.getByRole('button', {
name: 'Next',
});
await userEvent.click(nextButton);
await waitFor(() => {
expect(onContinue).toBeCalled();
});
expect(onContinue.mock.calls[0][0]).toEqual(result);
});
test('AutoMatching exact values', async () => {
const header = ['Name', 'Phone', 'Email'];
const data = [
['John', '123', 'j@j.com'],
['Dane', '333', 'dane@bane.com'],
['Kane', '534', 'kane@linch.com'],
];
// finds only names with automatic matching
const result = [
{ name: data[0][0] },
{ name: data[1][0] },
{ name: data[2][0] },
];
const onContinue = jest.fn();
render(
<Providers rsiValues={{ ...mockRsiValues, fields, autoMapDistance: 1 }}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<MatchColumnsStep
headerValues={header}
data={data}
onContinue={onContinue}
/>
</ModalWrapper>
</Providers>,
);
const nextButton = screen.getByRole('button', {
name: 'Next',
});
await userEvent.click(nextButton);
await waitFor(() => {
expect(onContinue).toBeCalled();
});
expect(onContinue.mock.calls[0][0]).toEqual(result);
});
test('AutoMatches only one value', async () => {
const header = ['first name', 'name', 'Email'];
const data = [
['John', '123', 'j@j.com'],
['Dane', '333', 'dane@bane.com'],
['Kane', '534', 'kane@linch.com'],
];
// finds only names with automatic matching
const result = [
{ name: data[0][1] },
{ name: data[1][1] },
{ name: data[2][1] },
];
const alternativeFields = [
{
icon: null,
label: 'Name',
key: 'name',
alternateMatches: ['first name'],
fieldType: {
type: 'input',
},
example: 'Stephanie',
},
] as const;
const onContinue = jest.fn();
render(
<Providers rsiValues={{ ...mockRsiValues, fields: alternativeFields }}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<MatchColumnsStep
headerValues={header}
data={data}
onContinue={onContinue}
/>
</ModalWrapper>
</Providers>,
);
const nextButton = screen.getByRole('button', {
name: 'Next',
});
await userEvent.click(nextButton);
await waitFor(() => {
expect(onContinue).toBeCalled();
});
expect(onContinue.mock.calls[0][0]).toEqual(result);
});
test('Boolean-like values are returned as Booleans', async () => {
const header = ['namezz', 'is_cool', 'Email'];
const data = [
['John', 'yes', 'j@j.com'],
['Dane', 'TRUE', 'dane@bane.com'],
['Kane', 'false', 'kane@linch.com'],
['Kaney', 'no', 'kane@linch.com'],
['Kanye', 'maybe', 'kane@linch.com'],
];
const result = [
{ name: data[0][0], is_cool: true },
{ name: data[1][0], is_cool: true },
{ name: data[2][0], is_cool: false },
{ name: data[3][0], is_cool: false },
{ name: data[4][0], is_cool: false },
];
const onContinue = jest.fn();
render(
<Providers rsiValues={{ ...mockRsiValues, fields }}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<MatchColumnsStep
headerValues={header}
data={data}
onContinue={onContinue}
/>
</ModalWrapper>
</Providers>,
);
const nextButton = screen.getByRole('button', {
name: 'Next',
});
await userEvent.click(nextButton);
await waitFor(() => {
expect(onContinue).toBeCalled();
});
expect(onContinue.mock.calls[0][0]).toEqual(result);
});
test("Boolean-like values are returned as Booleans for 'booleanMatches' props", async () => {
const BOOLEAN_MATCHES_VALUE = 'definitely';
const header = ['is_cool'];
const data = [['true'], ['false'], [BOOLEAN_MATCHES_VALUE]];
const fields = [
{
icon: null,
label: 'Is cool',
key: 'is_cool',
fieldType: {
type: 'checkbox',
booleanMatches: { [BOOLEAN_MATCHES_VALUE]: true },
},
example: 'No',
},
] as const;
const result = [{ is_cool: true }, { is_cool: false }, { is_cool: true }];
const onContinue = jest.fn();
render(
<Providers rsiValues={{ ...mockRsiValues, fields }}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<MatchColumnsStep
headerValues={header}
data={data}
onContinue={onContinue}
/>
</ModalWrapper>
</Providers>,
);
const nextButton = screen.getByRole('button', {
name: 'Next',
});
await userEvent.click(nextButton);
await waitFor(() => {
expect(onContinue).toBeCalled();
});
expect(onContinue.mock.calls[0][0]).toEqual(result);
});
});
describe('Match Columns general tests', () => {
test('Displays all user header columns', async () => {
const header = ['namezz', 'Phone', 'Email'];
const data = [
['John', '123', 'j@j.com'],
['Dane', '333', 'dane@bane.com'],
['Kane', '534', 'kane@linch.com'],
];
const onContinue = jest.fn();
render(
<Providers rsiValues={{ ...mockRsiValues, fields }}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<MatchColumnsStep
headerValues={header}
data={data}
onContinue={onContinue}
/>
</ModalWrapper>
</Providers>,
);
expect(screen.getByText(header[0])).toBeInTheDocument();
expect(screen.getByText(header[1])).toBeInTheDocument();
expect(screen.getByText(header[2])).toBeInTheDocument();
});
test('Displays two rows of example data', async () => {
const header = ['namezz', 'Phone', 'Email'];
const data = [
['John', '123', 'j@j.com'],
['Dane', '333', 'dane@bane.com'],
['Kane', '534', 'kane@linch.com'],
];
const onContinue = jest.fn();
render(
<Providers rsiValues={{ ...mockRsiValues, fields }}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<MatchColumnsStep
headerValues={header}
data={data}
onContinue={onContinue}
/>
</ModalWrapper>
</Providers>,
);
// only displays two rows
expect(screen.queryByText(data[0][0])).toBeInTheDocument();
expect(screen.queryByText(data[0][1])).toBeInTheDocument();
expect(screen.queryByText(data[0][2])).toBeInTheDocument();
expect(screen.queryByText(data[1][0])).toBeInTheDocument();
expect(screen.queryByText(data[1][1])).toBeInTheDocument();
expect(screen.queryByText(data[1][2])).toBeInTheDocument();
expect(screen.queryByText(data[2][0])).not.toBeInTheDocument();
expect(screen.queryByText(data[2][1])).not.toBeInTheDocument();
expect(screen.queryByText(data[2][2])).not.toBeInTheDocument();
});
test('Displays all fields in selects dropdown', async () => {
const header = ['Something random', 'Phone', 'Email'];
const data = [
['John', '123', 'j@j.com'],
['Dane', '333', 'dane@bane.com'],
['Kane', '534', 'kane@linch.com'],
];
const onContinue = jest.fn();
render(
<Providers rsiValues={{ ...mockRsiValues, fields }}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<MatchColumnsStep
headerValues={header}
data={data}
onContinue={onContinue}
/>
</ModalWrapper>
</Providers>,
);
const firstSelect = screen.getByLabelText(header[0]);
await userEvent.click(firstSelect);
fields.forEach((field) => {
expect(screen.queryByText(field.label)).toBeInTheDocument();
});
});
test('Manually matches first column', async () => {
const header = ['Something random', 'Phone', 'Email'];
const data = [
['John', '123', 'j@j.com'],
['Dane', '333', 'dane@bane.com'],
['Kane', '534', 'kane@linch.com'],
];
const result = [
{ name: data[0][0] },
{ name: data[1][0] },
{ name: data[2][0] },
];
const onContinue = jest.fn();
render(
<Providers rsiValues={{ ...mockRsiValues, fields }}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<MatchColumnsStep
headerValues={header}
data={data}
onContinue={onContinue}
/>
<div id={SELECT_DROPDOWN_ID} />
</ModalWrapper>
</Providers>,
);
const container = document.getElementById(SELECT_DROPDOWN_ID);
if (!container) {
throw new Error('Container not found');
}
await selectEvent.select(
screen.getByLabelText(header[0]),
fields[0].label,
{
container,
},
);
const nextButton = screen.getByRole('button', {
name: 'Next',
});
await userEvent.click(nextButton);
await waitFor(() => {
expect(onContinue).toBeCalled();
});
expect(onContinue.mock.calls[0][0]).toEqual(result);
});
test('Checkmark changes when field is matched', async () => {
const header = ['Something random', 'Phone', 'Email'];
const data = [
['John', '123', 'j@j.com'],
['Dane', '333', 'dane@bane.com'],
['Kane', '534', 'kane@linch.com'],
];
const onContinue = jest.fn();
render(
<Providers rsiValues={{ ...mockRsiValues, fields }}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<MatchColumnsStep
headerValues={header}
data={data}
onContinue={onContinue}
/>
<div id={SELECT_DROPDOWN_ID} />
</ModalWrapper>
</Providers>,
);
const checkmark = screen.getAllByTestId('column-checkmark')[0];
// kinda dumb way to check if it has checkmark or not
expect(checkmark).toBeEmptyDOMElement();
const container = document.getElementById(SELECT_DROPDOWN_ID);
if (!container) {
throw new Error('Container not found');
}
await selectEvent.select(
screen.getByLabelText(header[0]),
fields[0].label,
{
container,
},
);
expect(checkmark).not.toBeEmptyDOMElement();
});
test('Selecting select field adds more selects', async () => {
const OPTION_ONE = 'one';
const OPTION_TWO = 'two';
const OPTION_RESULT_ONE = 'uno';
const OPTION_RESULT_TWO = 'dos';
const options = [
{ label: 'One', value: OPTION_RESULT_ONE },
{ label: 'Two', value: OPTION_RESULT_TWO },
];
const header = ['Something random'];
const data = [[OPTION_ONE], [OPTION_TWO], [OPTION_ONE]];
const result = [
{
team: OPTION_RESULT_ONE,
},
{
team: OPTION_RESULT_TWO,
},
{
team: OPTION_RESULT_ONE,
},
];
const enumFields = [
{
icon: null,
label: 'Team',
key: 'team',
fieldType: {
type: 'select',
options: options,
},
},
] as const;
const onContinue = jest.fn();
render(
<Providers rsiValues={{ ...mockRsiValues, fields: enumFields }}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<MatchColumnsStep
headerValues={header}
data={data}
onContinue={onContinue}
/>
<div id={SELECT_DROPDOWN_ID} />
</ModalWrapper>
</Providers>,
);
expect(screen.queryByTestId('accordion-button')).not.toBeInTheDocument();
const container = document.getElementById(SELECT_DROPDOWN_ID);
if (!container) {
throw new Error('Container not found');
}
await selectEvent.select(
screen.getByLabelText(header[0]),
enumFields[0].label,
{
container,
},
);
expect(screen.queryByTestId('accordion-button')).toBeInTheDocument();
await userEvent.click(screen.getByTestId('accordion-button'));
await selectEvent.select(
screen.getByLabelText(data[0][0]),
options[0].label,
{
container,
},
);
await selectEvent.select(
screen.getByLabelText(data[1][0]),
options[1].label,
{
container,
},
);
const nextButton = screen.getByRole('button', {
name: 'Next',
});
await userEvent.click(nextButton);
await waitFor(() => {
expect(onContinue).toBeCalled();
});
expect(onContinue.mock.calls[0][0]).toEqual(result);
});
test('Can ignore columns', async () => {
const header = ['Something random', 'Phone', 'Email'];
const data = [
['John', '123', 'j@j.com'],
['Dane', '333', 'dane@bane.com'],
['Kane', '534', 'kane@linch.com'],
];
const onContinue = jest.fn();
render(
<Providers rsiValues={{ ...mockRsiValues, fields }}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<MatchColumnsStep
headerValues={header}
data={data}
onContinue={onContinue}
/>
</ModalWrapper>
</Providers>,
);
const ignoreButton = screen.getAllByLabelText('Ignore column')[0];
expect(screen.queryByText('Column ignored')).not.toBeInTheDocument();
await userEvent.click(ignoreButton);
expect(screen.queryByText('Column ignored')).toBeInTheDocument();
});
test('Required unselected fields show warning alert on submit', async () => {
const header = ['Something random', 'Phone', 'Email'];
const data = [
['John', '123', 'j@j.com'],
['Dane', '333', 'dane@bane.com'],
['Kane', '534', 'kane@linch.com'],
];
const requiredFields = [
{
icon: null,
label: 'Name',
key: 'name',
fieldType: {
type: 'input',
},
example: 'Stephanie',
validations: [
{
rule: 'required',
errorMessage: 'Hello',
},
],
},
] as const;
const onContinue = jest.fn();
render(
<Providers rsiValues={{ ...mockRsiValues, fields: requiredFields }}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<MatchColumnsStep
headerValues={header}
data={data}
onContinue={onContinue}
/>
</ModalWrapper>
</Providers>,
);
const nextButton = screen.getByRole('button', {
name: 'Next',
});
await userEvent.click(nextButton);
expect(onContinue).not.toBeCalled();
expect(
screen.queryByText(
'There are required columns that are not matched or ignored. Do you want to continue?',
),
).toBeInTheDocument();
const continueButton = screen.getByRole('button', {
name: 'Continue',
});
await userEvent.click(continueButton);
await waitFor(() => {
expect(onContinue).toBeCalled();
});
});
test('Selecting the same field twice shows toast', async () => {
const header = ['Something random', 'Phone', 'Email'];
const data = [
['John', '123', 'j@j.com'],
['Dane', '333', 'dane@bane.com'],
['Kane', '534', 'kane@linch.com'],
];
const onContinue = jest.fn();
render(
<Providers rsiValues={{ ...mockRsiValues, fields }}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<MatchColumnsStep
headerValues={header}
data={data}
onContinue={onContinue}
/>
<div id={SELECT_DROPDOWN_ID} />
</ModalWrapper>
</Providers>,
);
const container = document.getElementById(SELECT_DROPDOWN_ID);
if (!container) {
throw new Error('Container not found');
}
await selectEvent.select(
screen.getByLabelText(header[0]),
fields[0].label,
{
container,
},
);
await selectEvent.select(
screen.getByLabelText(header[1]),
fields[0].label,
{
container,
},
);
const toasts = await screen.queryAllByText('Columns cannot duplicate');
expect(toasts?.[0]).toBeInTheDocument();
});
test('matchColumnsStepHook should be called after columns are matched', async () => {
const matchColumnsStepHook = jest.fn(async (values) => values);
const mockValues = {
...mockRsiValues,
fields: mockRsiValues.fields.filter(
(field) => field.key === 'name' || field.key === 'age',
),
};
render(
<SpreadsheetImport
{...mockValues}
matchColumnsStepHook={matchColumnsStepHook}
initialStepState={{
type: StepType.matchColumns,
data: [
['Josh', '2'],
['Charlie', '3'],
['Lena', '50'],
],
headerValues: ['name', 'age'],
}}
/>,
);
const continueButton = screen.getByText(CONTINUE_BUTTON);
await userEvent.click(continueButton);
await waitFor(() => {
expect(matchColumnsStepHook).toBeCalled();
});
});
test('matchColumnsStepHook mutations to rawData should show up in ValidationStep', async () => {
const matchColumnsStepHook = jest.fn(async ([firstEntry, ...values]) => {
return [{ ...firstEntry, name: MUTATED_ENTRY }, ...values];
});
const mockValues = {
...mockRsiValues,
fields: mockRsiValues.fields.filter(
(field) => field.key === 'name' || field.key === 'age',
),
};
render(
<SpreadsheetImport
{...mockValues}
matchColumnsStepHook={matchColumnsStepHook}
initialStepState={{
type: StepType.matchColumns,
data: [
['Josh', '2'],
['Charlie', '3'],
['Lena', '50'],
],
headerValues: ['name', 'age'],
}}
/>,
);
const continueButton = screen.getByText(CONTINUE_BUTTON);
await userEvent.click(continueButton);
const mutatedEntry = await screen.findByText(MUTATED_ENTRY);
expect(mutatedEntry).toBeInTheDocument();
});
test('Should show error toast if error is thrown in matchColumnsStepHook', async () => {
const matchColumnsStepHook = jest.fn(async () => {
throw new Error(ERROR_MESSAGE);
});
const mockValues = {
...mockRsiValues,
fields: mockRsiValues.fields.filter(
(field) => field.key === 'name' || field.key === 'age',
),
};
render(
<SpreadsheetImport
{...mockValues}
matchColumnsStepHook={matchColumnsStepHook}
initialStepState={{
type: StepType.matchColumns,
data: [
['Josh', '2'],
['Charlie', '3'],
['Lena', '50'],
],
headerValues: ['name', 'age'],
}}
/>,
);
const continueButton = screen.getByText(CONTINUE_BUTTON);
await userEvent.click(continueButton);
const errorToast = await screen.findAllByText(ERROR_MESSAGE, undefined, {
timeout: 5000,
});
expect(errorToast?.[0]).toBeInTheDocument();
});
});

View File

@ -1,257 +0,0 @@
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { readFileSync } from 'fs';
import { ModalWrapper } from '@/spreadsheet-import/components/core/ModalWrapper';
import { Providers } from '@/spreadsheet-import/components/core/Providers';
import { SpreadsheetImport } from '@/spreadsheet-import/components/SpreadsheetImport';
import { SelectHeaderStep } from '@/spreadsheet-import/components/steps/SelectHeaderStep/SelectHeaderStep';
import { StepType } from '@/spreadsheet-import/components/steps/UploadFlow';
import { mockRsiValues } from '@/spreadsheet-import/tests/mockRsiValues';
import '@testing-library/jest-dom';
const MUTATED_HEADER = 'mutated header';
const CONTINUE_BUTTON = 'Next';
const ERROR_MESSAGE = 'Something happened';
const RAW_DATE = '2020-03-03';
const FORMATTED_DATE = '2020/03/03';
const TRAILING_CELL = 'trailingcell';
describe('Select header step tests', () => {
test('Select header row and click next', async () => {
const data = [
['Some random header'],
['2030'],
['Name', 'Phone', 'Email'],
['John', '123', 'j@j.com'],
['Dane', '333', 'dane@bane.com'],
];
const selectRowIndex = 2;
const onContinue = jest.fn();
render(
<Providers rsiValues={mockRsiValues}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<SelectHeaderStep data={data} onContinue={onContinue} />
</ModalWrapper>
</Providers>,
);
const radioButtons = screen.getAllByRole('radio');
await userEvent.click(radioButtons[selectRowIndex]);
const nextButton = screen.getByRole('button', {
name: 'Next',
});
await userEvent.click(nextButton);
await waitFor(() => {
expect(onContinue).toBeCalled();
});
expect(onContinue.mock.calls[0][0]).toEqual(data[selectRowIndex]);
expect(onContinue.mock.calls[0][1]).toEqual(data.slice(selectRowIndex + 1));
});
test('selectHeaderStepHook should be called after header is selected', async () => {
const selectHeaderStepHook = jest.fn(async (headerValues, data) => {
return { headerValues, data };
});
render(
<SpreadsheetImport
{...mockRsiValues}
selectHeaderStepHook={selectHeaderStepHook}
/>,
);
const uploader = screen.getByTestId('rsi-dropzone');
const data = readFileSync(__dirname + '/../../../../static/Workbook2.xlsx');
fireEvent.drop(uploader, {
target: {
files: [
new File([data], 'testFile.xlsx', {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
}),
],
},
});
const continueButton = await screen.findByText(CONTINUE_BUTTON, undefined, {
timeout: 10000,
});
fireEvent.click(continueButton);
await waitFor(() => {
expect(selectHeaderStepHook).toBeCalledWith(
['name', 'age', 'date'],
[
['Josh', '2', '2020-03-03'],
['Charlie', '3', '2010-04-04'],
['Lena', '50', '1994-02-27'],
],
);
});
});
test('selectHeaderStepHook should be able to modify raw data', async () => {
const selectHeaderStepHook = jest.fn(
async ([_val, ...headerValues], data) => {
return { headerValues: [MUTATED_HEADER, ...headerValues], data };
},
);
render(
<SpreadsheetImport
{...mockRsiValues}
selectHeaderStepHook={selectHeaderStepHook}
initialStepState={{
type: StepType.selectHeader,
data: [
['name', 'age'],
['Josh', '2'],
['Charlie', '3'],
['Lena', '50'],
],
}}
/>,
);
const continueButton = screen.getByText(CONTINUE_BUTTON);
fireEvent.click(continueButton);
const mutatedHeader = await screen.findByText(MUTATED_HEADER);
await waitFor(() => {
expect(mutatedHeader).toBeInTheDocument();
});
});
test('Should show error toast if error is thrown in selectHeaderStepHook', async () => {
const selectHeaderStepHook = jest.fn(async () => {
throw new Error(ERROR_MESSAGE);
});
render(
<SpreadsheetImport
{...mockRsiValues}
selectHeaderStepHook={selectHeaderStepHook}
initialStepState={{
type: StepType.selectHeader,
data: [
['name', 'age'],
['Josh', '2'],
['Charlie', '3'],
['Lena', '50'],
],
}}
/>,
);
const continueButton = screen.getByText(CONTINUE_BUTTON);
await userEvent.click(continueButton);
const errorToast = await screen.findAllByText(ERROR_MESSAGE, undefined, {
timeout: 5000,
});
expect(errorToast?.[0]).toBeInTheDocument();
});
test('dateFormat property should NOT be applied to dates read from csv files IF parseRaw=true', async () => {
const file = new File([RAW_DATE], 'test.csv', {
type: 'text/csv',
});
render(
<SpreadsheetImport
{...mockRsiValues}
dateFormat="yyyy/mm/dd"
parseRaw={true}
/>,
);
const uploader = screen.getByTestId('rsi-dropzone');
fireEvent.drop(uploader, {
target: { files: [file] },
});
const el = await screen.findByText(RAW_DATE, undefined, { timeout: 5000 });
expect(el).toBeInTheDocument();
});
test('dateFormat property should be applied to dates read from csv files IF parseRaw=false', async () => {
const file = new File([RAW_DATE], 'test.csv', {
type: 'text/csv',
});
render(
<SpreadsheetImport
{...mockRsiValues}
dateFormat="yyyy/mm/dd"
parseRaw={false}
/>,
);
const uploader = screen.getByTestId('rsi-dropzone');
fireEvent.drop(uploader, {
target: { files: [file] },
});
const el = await screen.findByText(FORMATTED_DATE, undefined, {
timeout: 5000,
});
expect(el).toBeInTheDocument();
});
test('dateFormat property should be applied to dates read from xlsx files', async () => {
render(<SpreadsheetImport {...mockRsiValues} dateFormat="yyyy/mm/dd" />);
const uploader = screen.getByTestId('rsi-dropzone');
const data = readFileSync(__dirname + '/../../../../static/Workbook2.xlsx');
fireEvent.drop(uploader, {
target: {
files: [
new File([data], 'testFile.xlsx', {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
}),
],
},
});
const el = await screen.findByText(FORMATTED_DATE, undefined, {
timeout: 10000,
});
expect(el).toBeInTheDocument();
});
test.skip(
'trailing (not under a header) cells should be rendered in SelectHeaderStep table, ' +
'but not in MatchColumnStep if a shorter row is selected as a header',
async () => {
const selectHeaderStepHook = jest.fn(async (headerValues, data) => {
return { headerValues, data };
});
render(
<SpreadsheetImport
{...mockRsiValues}
selectHeaderStepHook={selectHeaderStepHook}
/>,
);
const uploader = screen.getByTestId('rsi-dropzone');
const data = readFileSync(
__dirname + '/../../../../static/TrailingCellsWorkbook.xlsx',
);
fireEvent.drop(uploader, {
target: {
files: [
new File([data], 'testFile.xlsx', {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
}),
],
},
});
const trailingCell = await screen.findByText(TRAILING_CELL, undefined, {
timeout: 10000,
});
expect(trailingCell).toBeInTheDocument();
const nextButton = screen.getByRole('button', {
name: 'Next',
});
await userEvent.click(nextButton);
const trailingCellNextPage = await screen.findByText(
TRAILING_CELL,
undefined,
{ timeout: 10000 },
);
expect(trailingCellNextPage).not.toBeInTheDocument();
},
);
});

View File

@ -1,134 +0,0 @@
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { readFileSync } from 'fs';
import { ModalWrapper } from '@/spreadsheet-import/components/core/ModalWrapper';
import { Providers } from '@/spreadsheet-import/components/core/Providers';
import { SpreadsheetImport } from '@/spreadsheet-import/components/SpreadsheetImport';
import { SelectSheetStep } from '@/spreadsheet-import/components/steps/SelectSheetStep/SelectSheetStep';
import { mockRsiValues } from '@/spreadsheet-import/tests/mockRsiValues';
import '@testing-library/jest-dom';
const SHEET_TITLE_1 = 'Sheet1';
const SHEET_TITLE_2 = 'Sheet2';
const SELECT_HEADER_TABLE_ENTRY_1 = 'Charlie';
const SELECT_HEADER_TABLE_ENTRY_2 = 'Josh';
const SELECT_HEADER_TABLE_ENTRY_3 = '50';
const ERROR_MESSAGE = 'Something happened';
test('Should render select sheet screen if multi-sheet excel file was uploaded', async () => {
render(<SpreadsheetImport {...mockRsiValues} />);
const uploader = screen.getByTestId('rsi-dropzone');
const data = readFileSync(__dirname + '/../../../../static/Workbook1.xlsx');
fireEvent.drop(uploader, {
target: {
files: [
new File([data], 'testFile.xlsx', {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
}),
],
},
});
const sheetTitle = await screen.findByText(SHEET_TITLE_1, undefined, {
timeout: 5000,
});
const sheetTitle2 = screen.getByRole('radio', { name: SHEET_TITLE_2 });
expect(sheetTitle).toBeInTheDocument();
expect(sheetTitle2).toBeInTheDocument();
});
test('Should render select header screen with relevant data if single-sheet excel file was uploaded', async () => {
render(<SpreadsheetImport {...mockRsiValues} />);
const uploader = screen.getByTestId('rsi-dropzone');
const data = readFileSync(__dirname + '/../../../../static/Workbook2.xlsx');
fireEvent.drop(uploader, {
target: {
files: [
new File([data], 'testFile.xlsx', {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
}),
],
},
});
const tableEntry1 = await screen.findByText(
SELECT_HEADER_TABLE_ENTRY_1,
undefined,
{ timeout: 5000 },
);
const tableEntry2 = screen.getByRole('gridcell', {
name: SELECT_HEADER_TABLE_ENTRY_2,
});
const tableEntry3 = screen.getByRole('gridcell', {
name: SELECT_HEADER_TABLE_ENTRY_3,
});
expect(tableEntry1).toBeInTheDocument();
expect(tableEntry2).toBeInTheDocument();
expect(tableEntry3).toBeInTheDocument();
});
test('Select sheet and click next', async () => {
const sheetNames = ['Sheet1', 'Sheet2'];
const selectSheetIndex = 1;
const onContinue = jest.fn();
render(
<Providers rsiValues={mockRsiValues}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<SelectSheetStep sheetNames={sheetNames} onContinue={onContinue} />
</ModalWrapper>
</Providers>,
);
const firstRadio = screen.getByLabelText(sheetNames[selectSheetIndex]);
await userEvent.click(firstRadio);
const nextButton = screen.getByRole('button', {
name: 'Next',
});
await userEvent.click(nextButton);
await waitFor(() => {
expect(onContinue).toBeCalled();
});
expect(onContinue.mock.calls[0][0]).toEqual(sheetNames[selectSheetIndex]);
});
test('Should show error toast if error is thrown in uploadStepHook', async () => {
const uploadStepHook = jest.fn(async () => {
throw new Error(ERROR_MESSAGE);
});
render(
<SpreadsheetImport {...mockRsiValues} uploadStepHook={uploadStepHook} />,
);
const uploader = screen.getByTestId('rsi-dropzone');
const data = readFileSync(__dirname + '/../../../../static/Workbook1.xlsx');
fireEvent.drop(uploader, {
target: {
files: [
new File([data], 'testFile.xlsx', {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
}),
],
},
});
const nextButton = await screen.findByRole(
'button',
{
name: 'Next',
},
{ timeout: 5000 },
);
await userEvent.click(nextButton);
const errorToast = await screen.findAllByText(ERROR_MESSAGE, undefined, {
timeout: 5000,
});
expect(errorToast?.[0]).toBeInTheDocument();
});

View File

@ -1,105 +0,0 @@
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { ModalWrapper } from '@/spreadsheet-import/components/core/ModalWrapper';
import { Providers } from '@/spreadsheet-import/components/core/Providers';
import { SpreadsheetImport } from '@/spreadsheet-import/components/SpreadsheetImport';
import { UploadStep } from '@/spreadsheet-import/components/steps/UploadStep/UploadStep';
import { mockRsiValues } from '@/spreadsheet-import/tests/mockRsiValues';
import '@testing-library/jest-dom';
const MUTATED_RAW_DATA = 'Bye';
const ERROR_MESSAGE = 'Something happened while uploading';
test('Upload a file', async () => {
const file = new File(['Hello, Hello, Hello, Hello'], 'test.csv', {
type: 'text/csv',
});
const onContinue = jest.fn();
render(
<Providers rsiValues={mockRsiValues}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<UploadStep onContinue={onContinue} />
</ModalWrapper>
</Providers>,
);
const uploader = screen.getByTestId('rsi-dropzone');
fireEvent.drop(uploader, {
target: { files: [file] },
});
await waitFor(
() => {
expect(onContinue).toBeCalled();
},
{ timeout: 5000 },
);
});
test('Should call uploadStepHook on file upload', async () => {
const file = new File(['Hello, Hello, Hello, Hello'], 'test.csv', {
type: 'text/csv',
});
const uploadStepHook = jest.fn(async (values) => {
return values;
});
render(
<SpreadsheetImport {...mockRsiValues} uploadStepHook={uploadStepHook} />,
);
const uploader = screen.getByTestId('rsi-dropzone');
fireEvent.drop(uploader, {
target: { files: [file] },
});
await waitFor(
() => {
expect(uploadStepHook).toBeCalled();
},
{ timeout: 5000 },
);
});
test('uploadStepHook should be able to mutate raw upload data', async () => {
const file = new File(['Hello, Hello, Hello, Hello'], 'test.csv', {
type: 'text/csv',
});
const uploadStepHook = jest.fn(async ([[, ...values]]) => {
return [[MUTATED_RAW_DATA, ...values]];
});
render(
<SpreadsheetImport {...mockRsiValues} uploadStepHook={uploadStepHook} />,
);
const uploader = screen.getByTestId('rsi-dropzone');
fireEvent.drop(uploader, {
target: { files: [file] },
});
const el = await screen.findByText(MUTATED_RAW_DATA, undefined, {
timeout: 5000,
});
expect(el).toBeInTheDocument();
});
test('Should show error toast if error is thrown in uploadStepHook', async () => {
const file = new File(['Hello, Hello, Hello, Hello'], 'test.csv', {
type: 'text/csv',
});
const uploadStepHook = jest.fn(async () => {
throw new Error(ERROR_MESSAGE);
});
render(
<SpreadsheetImport {...mockRsiValues} uploadStepHook={uploadStepHook} />,
);
const uploader = screen.getByTestId('rsi-dropzone');
fireEvent.drop(uploader, {
target: { files: [file] },
});
const errorToast = await screen.findAllByText(ERROR_MESSAGE, undefined, {
timeout: 5000,
});
expect(errorToast?.[0]).toBeInTheDocument();
});

View File

@ -1,763 +0,0 @@
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { ModalWrapper } from '@/spreadsheet-import/components/core/ModalWrapper';
import { Providers } from '@/spreadsheet-import/components/core/Providers';
import { defaultRSIProps } from '@/spreadsheet-import/components/SpreadsheetImport';
import { ValidationStep } from '@/spreadsheet-import/components/steps/ValidationStep/ValidationStep';
import '@testing-library/jest-dom';
const mockValues = {
...defaultRSIProps,
fields: [],
onSubmit: jest.fn(),
isOpen: true,
onClose: jest.fn(),
} as const;
const getFilterSwitch = () =>
screen.getByRole('checkbox', {
name: 'Show only rows with errors',
});
const file = new File([''], 'file.csv');
describe('Validation step tests', () => {
test('Submit data', async () => {
const onSubmit = jest.fn();
render(
<Providers rsiValues={{ ...mockValues, onSubmit: onSubmit }}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<ValidationStep initialData={[]} file={file} />
</ModalWrapper>
</Providers>,
);
const finishButton = screen.getByRole('button', {
name: 'Confirm',
});
await userEvent.click(finishButton);
await waitFor(() => {
expect(onSubmit).toBeCalledWith(
{ all: [], invalidData: [], validData: [] },
file,
);
});
});
test('Filters rows with required errors', async () => {
const UNIQUE_NAME = 'very unique name';
const initialData = [
{
name: UNIQUE_NAME,
},
{
name: undefined,
},
];
const fields = [
{
icon: null,
label: 'Name',
key: 'name',
fieldType: {
type: 'input',
},
validations: [
{
rule: 'required',
errorMessage: 'Name is required',
},
],
},
] as const;
render(
<Providers rsiValues={{ ...mockValues, fields }}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<ValidationStep initialData={initialData} file={file} />
</ModalWrapper>
</Providers>,
);
const allRowsWithHeader = await screen.findAllByRole('row');
expect(allRowsWithHeader).toHaveLength(3);
const validRow = screen.getByText(UNIQUE_NAME);
expect(validRow).toBeInTheDocument();
const switchFilter = getFilterSwitch();
await userEvent.click(switchFilter);
const filteredRowsWithHeader = await screen.findAllByRole('row');
expect(filteredRowsWithHeader).toHaveLength(2);
});
test('Filters rows with errors, fixes row, removes filter', async () => {
const UNIQUE_NAME = 'very unique name';
const SECOND_UNIQUE_NAME = 'another unique name';
const FINAL_NAME = 'just name';
const initialData = [
{
name: UNIQUE_NAME,
},
{
name: undefined,
},
{
name: SECOND_UNIQUE_NAME,
},
];
const fields = [
{
icon: null,
label: 'Name',
key: 'name',
fieldType: {
type: 'input',
},
validations: [
{
rule: 'required',
errorMessage: 'Name is required',
},
],
},
] as const;
const onSubmit = jest.fn();
render(
<Providers rsiValues={{ ...mockValues, fields, onSubmit }}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<ValidationStep initialData={initialData} file={file} />
</ModalWrapper>
</Providers>,
);
const allRowsWithHeader = await screen.findAllByRole('row');
expect(allRowsWithHeader).toHaveLength(4);
const validRow = screen.getByText(UNIQUE_NAME);
expect(validRow).toBeInTheDocument();
const switchFilter = getFilterSwitch();
await userEvent.click(switchFilter);
const filteredRowsWithHeader = await screen.findAllByRole('row');
expect(filteredRowsWithHeader).toHaveLength(2);
// don't really know another way to select an empty cell
const emptyCell = screen.getAllByRole('gridcell', { name: undefined })[1];
await userEvent.click(emptyCell);
await userEvent.keyboard(FINAL_NAME + '{enter}');
const filteredRowsNoErrorsWithHeader = await screen.findAllByRole('row');
expect(filteredRowsNoErrorsWithHeader).toHaveLength(1);
await userEvent.click(switchFilter);
const allRowsFixedWithHeader = await screen.findAllByRole('row');
expect(allRowsFixedWithHeader).toHaveLength(4);
const finishButton = screen.getByRole('button', {
name: 'Confirm',
});
await userEvent.click(finishButton);
await waitFor(() => {
expect(onSubmit).toBeCalled();
});
});
test('Filters rows with unique errors', async () => {
const NON_UNIQUE_NAME = 'very unique name';
const initialData = [
{
name: NON_UNIQUE_NAME,
},
{
name: NON_UNIQUE_NAME,
},
{
name: 'I am fine',
},
];
const fields = [
{
icon: null,
label: 'Name',
key: 'name',
fieldType: {
type: 'input',
},
validations: [
{
rule: 'unique',
errorMessage: 'Name must be unique',
},
],
},
] as const;
render(
<Providers rsiValues={{ ...mockValues, fields }}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<ValidationStep initialData={initialData} file={file} />
</ModalWrapper>
</Providers>,
);
const allRowsWithHeader = await screen.findAllByRole('row');
expect(allRowsWithHeader).toHaveLength(4);
const switchFilter = getFilterSwitch();
await userEvent.click(switchFilter);
const filteredRowsWithHeader = await screen.findAllByRole('row');
expect(filteredRowsWithHeader).toHaveLength(3);
});
test('Filters rows with regex errors', async () => {
const NOT_A_NUMBER = 'not a number';
const initialData = [
{
name: NOT_A_NUMBER,
},
{
name: '1234',
},
{
name: '9999999',
},
];
const fields = [
{
icon: null,
label: 'Name',
key: 'name',
fieldType: {
type: 'input',
},
validations: [
{
rule: 'regex',
errorMessage: 'Name must be unique',
value: '^[0-9]*$',
},
],
},
] as const;
render(
<Providers rsiValues={{ ...mockValues, fields }}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<ValidationStep initialData={initialData} file={file} />
</ModalWrapper>
</Providers>,
);
const allRowsWithHeader = await screen.findAllByRole('row');
expect(allRowsWithHeader).toHaveLength(4);
const switchFilter = getFilterSwitch();
await userEvent.click(switchFilter);
const filteredRowsWithHeader = await screen.findAllByRole('row');
expect(filteredRowsWithHeader).toHaveLength(2);
});
test('Deletes selected rows', async () => {
const FIRST_DELETE = 'first';
const SECOND_DELETE = 'second';
const THIRD = 'third';
const initialData = [
{
name: FIRST_DELETE,
},
{
name: SECOND_DELETE,
},
{
name: THIRD,
},
];
const fields = [
{
icon: null,
label: 'Name',
key: 'name',
fieldType: {
type: 'input',
},
},
] as const;
render(
<Providers rsiValues={{ ...mockValues, fields }}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<ValidationStep initialData={initialData} file={file} />
</ModalWrapper>
</Providers>,
);
const allRowsWithHeader = await screen.findAllByRole('row');
expect(allRowsWithHeader).toHaveLength(4);
const switchFilters = screen.getAllByRole('checkbox', {
name: 'Select',
});
await userEvent.click(switchFilters[0]);
await userEvent.click(switchFilters[1]);
const discardButton = screen.getByRole('button', {
name: 'Discard selected rows',
});
await userEvent.click(discardButton);
const filteredRowsWithHeader = await screen.findAllByRole('row');
expect(filteredRowsWithHeader).toHaveLength(2);
const validRow = screen.getByText(THIRD);
expect(validRow).toBeInTheDocument();
});
test('Deletes selected rows, changes the last one', async () => {
const FIRST_DELETE = 'first';
const SECOND_DELETE = 'second';
const THIRD = 'third';
const THIRD_CHANGED = 'third_changed';
const initialData = [
{
name: FIRST_DELETE,
},
{
name: SECOND_DELETE,
},
{
name: THIRD,
},
];
const fields = [
{
icon: null,
label: 'Name',
key: 'name',
fieldType: {
type: 'input',
},
},
] as const;
render(
<Providers rsiValues={{ ...mockValues, fields }}>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<ValidationStep initialData={initialData} file={file} />
</ModalWrapper>
</Providers>,
);
const allRowsWithHeader = await screen.findAllByRole('row');
expect(allRowsWithHeader).toHaveLength(4);
const switchFilters = screen.getAllByRole('checkbox', {
name: 'Select',
});
await userEvent.click(switchFilters[0]);
await userEvent.click(switchFilters[1]);
const discardButton = screen.getByRole('button', {
name: 'Discard selected rows',
});
await userEvent.click(discardButton);
const filteredRowsWithHeader = await screen.findAllByRole('row');
expect(filteredRowsWithHeader).toHaveLength(2);
const nameCell = screen.getByRole('gridcell', {
name: THIRD,
});
await userEvent.click(nameCell);
screen.getByRole<HTMLInputElement>('textbox');
await userEvent.keyboard(THIRD_CHANGED + '{enter}');
const validRow = screen.getByText(THIRD_CHANGED);
expect(validRow).toBeInTheDocument();
});
test('All inputs change values', async () => {
const NAME = 'John';
const NEW_NAME = 'Johnny';
const OPTIONS = [
{ value: 'one', label: 'ONE' },
{ value: 'two', label: 'TWO' },
] as const;
const initialData = [
{
name: NAME,
lastName: OPTIONS[0].value,
is_cool: false,
},
];
const fields = [
{
icon: null,
label: 'Name',
key: 'name',
fieldType: {
type: 'input',
},
},
{
icon: null,
label: 'lastName',
key: 'lastName',
fieldType: {
type: 'select',
options: OPTIONS,
},
},
{
icon: null,
label: 'is cool',
key: 'is_cool',
fieldType: {
type: 'checkbox',
},
},
] as const;
render(
<Providers
rsiValues={{
...mockValues,
fields,
}}
>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<ValidationStep initialData={initialData} file={file} />
</ModalWrapper>
</Providers>,
);
// input
const nameCell = screen.getByRole('gridcell', {
name: NAME,
});
await userEvent.click(nameCell);
const input: HTMLInputElement | null =
screen.getByRole<HTMLInputElement>('textbox');
expect(input).toHaveValue(NAME);
expect(input).toHaveFocus();
expect(input.selectionStart).toBe(0);
expect(input.selectionEnd).toBe(NAME.length);
await userEvent.keyboard(NEW_NAME + '{enter}');
expect(input).not.toBeInTheDocument();
const newNameCell = screen.getByRole('gridcell', {
name: NEW_NAME,
});
expect(newNameCell).toBeInTheDocument();
// select
const lastNameCell = screen.getByRole('gridcell', {
name: OPTIONS[0].label,
});
await userEvent.click(lastNameCell);
const newOption = screen.getByRole('button', {
name: OPTIONS[1].label,
});
await userEvent.click(newOption);
expect(newOption).not.toBeInTheDocument();
const newLastName = screen.getByRole('gridcell', {
name: OPTIONS[1].label,
});
expect(newLastName).toBeInTheDocument();
// Boolean
const checkbox = screen.getByRole('checkbox', {
name: '',
});
expect(checkbox).not.toBeChecked();
await userEvent.click(checkbox);
expect(checkbox).toBeChecked();
});
test('Row hook transforms data', async () => {
const NAME = 'John';
const LASTNAME = 'Doe';
const NEW_NAME = 'Johnny';
const NEW_LASTNAME = 'CENA';
const initialData = [
{
name: NAME + ' ' + LASTNAME,
lastName: undefined,
},
];
const fields = [
{
icon: null,
label: 'Name',
key: 'name',
fieldType: {
type: 'input',
},
},
{
icon: null,
label: 'lastName',
key: 'lastName',
fieldType: {
type: 'input',
},
},
] as const;
render(
<Providers
rsiValues={{
...mockValues,
fields,
rowHook: (value) => ({
name: value.name?.toString()?.split(/(\s+)/)[0],
lastName: value.name?.toString()?.split(/(\s+)/)[2],
}),
}}
>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<ValidationStep initialData={initialData} file={file} />
</ModalWrapper>
</Providers>,
);
const nameCell = screen.getByRole('gridcell', {
name: NAME,
});
expect(nameCell).toBeInTheDocument();
const lastNameCell = screen.getByRole('gridcell', {
name: LASTNAME,
});
expect(lastNameCell).toBeInTheDocument();
// activate input
await userEvent.click(nameCell);
await userEvent.keyboard(NEW_NAME + ' ' + NEW_LASTNAME + '{enter}');
const newNameCell = screen.getByRole('gridcell', {
name: NEW_NAME,
});
expect(newNameCell).toBeInTheDocument();
const newLastNameCell = screen.getByRole('gridcell', {
name: NEW_LASTNAME,
});
expect(newLastNameCell).toBeInTheDocument();
});
test('Row hook raises error', async () => {
const WRONG_NAME = 'Johnny';
const RIGHT_NAME = 'Jonathan';
const initialData = [
{
name: WRONG_NAME,
},
];
const fields = [
{
icon: null,
label: 'Name',
key: 'name',
fieldType: {
type: 'input',
},
},
] as const;
render(
<Providers
rsiValues={{
...mockValues,
fields,
rowHook: (value, setError) => {
if (value.name === WRONG_NAME) {
setError(fields[0].key, {
message: 'Wrong name',
level: 'error',
});
}
return value;
},
}}
>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<ValidationStep initialData={initialData} file={file} />
</ModalWrapper>
</Providers>,
);
const switchFilter = getFilterSwitch();
await expect(await screen.findAllByRole('row')).toHaveLength(2);
await userEvent.click(switchFilter);
await expect(await screen.findAllByRole('row')).toHaveLength(2);
const nameCell = screen.getByRole('gridcell', {
name: WRONG_NAME,
});
expect(nameCell).toBeInTheDocument();
await userEvent.click(nameCell);
screen.getByRole<HTMLInputElement>('textbox');
await userEvent.keyboard(RIGHT_NAME + '{enter}');
await expect(await screen.findAllByRole('row')).toHaveLength(1);
});
test('Table hook transforms data', async () => {
const NAME = 'John';
const SECOND_NAME = 'Doe';
const NEW_NAME = 'Jakee';
const ADDITION = 'last';
const initialData = [
{
name: NAME,
},
{
name: SECOND_NAME,
},
];
const fields = [
{
icon: null,
label: 'Name',
key: 'name',
fieldType: {
type: 'input',
},
},
] as const;
render(
<Providers
rsiValues={{
...mockValues,
fields,
tableHook: (data) =>
data.map((value) => ({
name: value.name + ADDITION,
})),
}}
>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<ValidationStep initialData={initialData} file={file} />
</ModalWrapper>
</Providers>,
);
const nameCell = screen.getByRole('gridcell', {
name: NAME + ADDITION,
});
expect(nameCell).toBeInTheDocument();
const lastNameCell = screen.getByRole('gridcell', {
name: SECOND_NAME + ADDITION,
});
expect(lastNameCell).toBeInTheDocument();
// activate input
await userEvent.click(nameCell);
await userEvent.keyboard(NEW_NAME + '{enter}');
const newNameCell = screen.getByRole('gridcell', {
name: NEW_NAME + ADDITION,
});
expect(newNameCell).toBeInTheDocument();
});
test('Table hook raises error', async () => {
const WRONG_NAME = 'Johnny';
const RIGHT_NAME = 'Jonathan';
const initialData = [
{
name: WRONG_NAME,
},
{
name: WRONG_NAME,
},
];
const fields = [
{
icon: null,
label: 'Name',
key: 'name',
fieldType: {
type: 'input',
},
},
] as const;
render(
<Providers
rsiValues={{
...mockValues,
fields,
tableHook: (data, setError) => {
data.forEach((value, index) => {
if (value.name === WRONG_NAME) {
setError(index, fields[0].key, {
message: 'Wrong name',
level: 'error',
});
}
return value;
});
return data;
},
}}
>
<ModalWrapper isOpen={true} onClose={jest.fn()}>
<ValidationStep initialData={initialData} file={file} />
</ModalWrapper>
</Providers>,
);
const switchFilter = getFilterSwitch();
await expect(await screen.findAllByRole('row')).toHaveLength(3);
await userEvent.click(switchFilter);
await expect(await screen.findAllByRole('row')).toHaveLength(3);
const nameCell = await screen.getAllByRole('gridcell', {
name: WRONG_NAME,
})[0];
await userEvent.click(nameCell);
screen.getByRole<HTMLInputElement>('textbox');
await userEvent.keyboard(RIGHT_NAME + '{enter}');
await expect(await screen.findAllByRole('row')).toHaveLength(2);
});
});

View File

@ -30,7 +30,7 @@ export const SelectHeaderStep = ({ data, onContinue }: SelectHeaderProps) => {
const [isLoading, setIsLoading] = useState(false);
const handleContinue = useCallback(async () => {
const [selectedRowIndex] = selectedRows;
const [selectedRowIndex] = Array.from(new Set(selectedRows));
// We consider data above header to be redundant
const trimmedData = data.slice(selectedRowIndex + 1);
setIsLoading(true);

View File

@ -1,33 +0,0 @@
import { render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { SpreadsheetImport } from '@/spreadsheet-import/components/SpreadsheetImport';
import { mockRsiValues } from '@/spreadsheet-import/tests/mockRsiValues';
import '@testing-library/jest-dom';
test('Close modal', async () => {
let isOpen = true;
const onClose = jest.fn(() => {
isOpen = !isOpen;
});
const { getByText, getByLabelText } = render(
<SpreadsheetImport {...mockRsiValues} onClose={onClose} isOpen={isOpen} />,
);
const closeButton = getByLabelText('Close modal');
await userEvent.click(closeButton);
const confirmButton = getByText('Exit flow');
await userEvent.click(confirmButton);
expect(onClose).toBeCalled();
});
test('Should throw error if no fields are provided', async () => {
const errorRender = () =>
render(<SpreadsheetImport {...mockRsiValues} fields={undefined} />);
expect(errorRender).toThrow();
});

View File

@ -3,7 +3,7 @@ import { BlockNoteView } from '@blocknote/react';
import styled from '@emotion/styled';
interface BlockEditorProps {
editor: BlockNoteEditor | null;
editor: BlockNoteEditor;
}
const StyledEditor = styled.div`

View File

@ -162,7 +162,7 @@ function SortAndFilterBar<SortField>({
/>
);
})}
{sorts.length && filtersWithDefinition.length && (
{!!sorts.length && !!filtersWithDefinition.length && (
<StyledSeperatorContainer>
<StyledSeperator />
</StyledSeperatorContainer>

View File

@ -1,6 +1,6 @@
{
"compilerOptions": {
"target": "es6",
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,

File diff suppressed because it is too large Load Diff