From fffdea59280cf197612c5bb0d12be259e93bf224 Mon Sep 17 00:00:00 2001 From: Konrad Bosak Date: Fri, 19 Jul 2024 13:04:16 +0200 Subject: [PATCH] Enable mui SelectField suite tests (#1355) Co-authored-by: Konrad Bosak --- .../uniforms-mui/__tests__/SelectField.tsx | 143 -------- packages/uniforms-mui/__tests__/index.ts | 5 +- packages/uniforms/__suites__/SelectField.tsx | 339 ++++++++++-------- 3 files changed, 200 insertions(+), 287 deletions(-) diff --git a/packages/uniforms-mui/__tests__/SelectField.tsx b/packages/uniforms-mui/__tests__/SelectField.tsx index d1944b7f5..b9cc43034 100644 --- a/packages/uniforms-mui/__tests__/SelectField.tsx +++ b/packages/uniforms-mui/__tests__/SelectField.tsx @@ -4,14 +4,6 @@ import { SelectField } from 'uniforms-mui'; import { renderWithZod } from 'uniforms/__suites__'; import { z } from 'zod'; -test(' - renders a Select', () => { - renderWithZod({ - element: , - schema: z.object({ x: z.enum(['a', 'b']) }), - }); - expect(screen.getByTestId('select-field')).toBeInTheDocument(); -}); - test(' - renders a Select with correct disabled state', () => { renderWithZod({ element: , @@ -32,37 +24,6 @@ test(' - renders a Select with correct required state', () => { expect(screen.getByLabelText('X *')).toBeInTheDocument(); }); -test(' - renders a Select with correct id (inherited)', () => { - renderWithZod({ - element: , - schema: z.object({ x: z.enum(['a', 'b']) }), - }); - - const select = screen.getByTestId('select-field').querySelector('[id]'); - expect(select?.getAttribute('id')).toBeTruthy(); -}); - -test(' - renders a Select with correct id (specified)', () => { - renderWithZod({ - element: , - schema: z.object({ x: z.enum(['a', 'b']) }), - }); - - const select = screen.getByTestId('select-field').querySelector('[id]'); - expect(select?.getAttribute('id')).toBe('y'); -}); - -test(' - renders a Select with correct name', () => { - renderWithZod({ - element: , - schema: z.object({ x: z.enum(['a', 'b']) }), - }); - - const select = screen.getByTestId('select-field'); - const elementWithAttribute = select.querySelector('[name="x"]') || select; - expect(elementWithAttribute?.getAttribute('name')).toBe('x'); -}); - test(' - renders a Select with correct options', () => { const selectOptions = ['a', 'b'] as const; renderWithZod({ @@ -171,49 +132,6 @@ test(' - renders a Select which correctly reacts on change (same va expect(onChange).toBeCalledTimes(0); }); -test(' - renders a label', () => { - renderWithZod({ - element: , - schema: z.object({ x: z.enum(['a', 'b']) }), - }); - - expect(screen.getByLabelText('y')).toBeInTheDocument(); -}); - -test(' - renders a SelectField with correct error text (showInlineError=true)', () => { - const error = new Error(); - renderWithZod({ - element: ( - - ), - schema: z.object({ x: z.enum(['a', 'b']) }), - }); - - expect(screen.getByText('Error')).toBeInTheDocument(); -}); - -test(' - renders a SelectField with correct error text (showInlineError=false)', () => { - const error = new Error(); - renderWithZod({ - element: ( - - ), - schema: z.object({ x: z.enum(['a', 'b']) }), - }); - - expect(screen.queryByText('Error')).not.toBeInTheDocument(); -}); - test(' - works with special characters', () => { renderWithZod({ element: , @@ -308,35 +226,6 @@ test(' - renders a set of Radio buttons with correct nam expect(screen.getByLabelText('b')).toHaveAttribute('name', 'x'); }); -test(' - renders a set of Radio buttons with correct options', () => { - renderWithZod({ - element: , - schema: z.object({ x: z.enum(['a', 'b']) }), - }); - - expect(screen.getByLabelText('a')).toBeInTheDocument(); - expect(screen.getByLabelText('b')).toBeInTheDocument(); -}); - -test(' - renders a set of Radio buttons with correct options (transform)', () => { - renderWithZod({ - element: ( - - ), - schema: z.object({ x: z.string() }), - }); - - expect(screen.getByLabelText('A')).toBeInTheDocument(); - expect(screen.getByLabelText('B')).toBeInTheDocument(); -}); - test(' - renders a set of Radio buttons with correct value (default)', () => { renderWithZod({ element: , @@ -381,29 +270,6 @@ test(' - renders a set of Radio buttons which correctly expect(onChange).toHaveBeenCalledWith('b'); }); -test(' - renders a set of Checkboxes which correctly reacts on change (array uncheck)', () => { - const onChange = jest.fn(); - - renderWithZod({ - element: ( - - ), - schema: z.object({ - x: z.string().uniforms({ - fieldType: Array, - options: [ - { label: 'A', value: 'a' }, - { label: 'B', value: 'b' }, - ], - }), - }), - }); - - fireEvent.click(screen.getByLabelText('B')); - - expect(onChange).toHaveBeenLastCalledWith([]); -}); - test(' - renders a set of Checkboxes with correct labels', () => { renderWithZod({ element: , @@ -422,15 +288,6 @@ test(' - renders a set of Checkboxes with correct labels expect(screen.getByLabelText('B')).toBeInTheDocument(); }); -test(' - renders a label', () => { - renderWithZod({ - element: , - schema: z.object({ x: z.enum(['a', 'b']) }), - }); - - expect(screen.getByText('y')).toBeInTheDocument(); -}); - test(' - renders a SelectField with correct error text (showInlineError=true)', () => { const error = new Error(); renderWithZod({ diff --git a/packages/uniforms-mui/__tests__/index.ts b/packages/uniforms-mui/__tests__/index.ts index 07c27deb1..c33083cad 100644 --- a/packages/uniforms-mui/__tests__/index.ts +++ b/packages/uniforms-mui/__tests__/index.ts @@ -55,7 +55,10 @@ describe('@RTL MUI', () => { suites.testQuickForm(theme.QuickForm); suites.testRadioField(theme.RadioField); // FIXME: MUI select does not work with new RTL test implementation - // suites.testSelectField(theme.SelectField, { showInlineError: true }); + suites.testSelectField(theme.SelectField, { + showInlineError: true, + theme: 'mui', + }); suites.testSubmitField(theme.SubmitField); suites.testTextField(theme.TextField); suites.testValidatedForm(theme.ValidatedForm); diff --git a/packages/uniforms/__suites__/SelectField.tsx b/packages/uniforms/__suites__/SelectField.tsx index 36d7a539e..de5220189 100644 --- a/packages/uniforms/__suites__/SelectField.tsx +++ b/packages/uniforms/__suites__/SelectField.tsx @@ -8,11 +8,14 @@ import { skipTestIf } from './skipTestIf'; export function testSelectField( SelectField: ComponentType, options?: { - theme?: 'antd'; + theme?: 'antd' | 'mui'; showInlineError?: boolean; getCheckboxInlineOption?: (screen: Screen) => Element | null; + reverseCheckboxOrder?: false; }, ) { + const isTheme = (themes: string[]) => themes.includes(options?.theme ?? ''); + test(' - renders a select', () => { renderWithZod({ element: , @@ -29,14 +32,17 @@ export function testSelectField( expect(screen.getByText('y')).toBeInTheDocument(); }); - test(' - renders a select with correct disabled state', () => { - renderWithZod({ - element: , - schema: z.object({ x: z.enum(['a', 'b']) }), - }); - const select = screen.getByRole('combobox'); - expect(select).toBeDisabled(); - }); + skipTestIf(isTheme(['mui', 'antd']))( + ' - renders a select with correct disabled state', + () => { + renderWithZod({ + element: , + schema: z.object({ x: z.enum(['a', 'b']) }), + }); + const select = screen.getByRole('combobox'); + expect(select).toBeDisabled(); + }, + ); test(' - renders a select with correct readOnly state', () => { const onChange = jest.fn(); @@ -56,7 +62,7 @@ export function testSelectField( expect(onChange).not.toHaveBeenCalled(); }); - skipTestIf(options?.theme === 'antd')( + skipTestIf(isTheme(['mui', 'antd']))( ' - ignores selection with readOnly state ', () => { const onChange = jest.fn(); @@ -77,7 +83,7 @@ export function testSelectField( }, ); - skipTestIf(options?.theme === 'antd')( + skipTestIf(isTheme(['mui', 'antd']))( ' - (multiple) renders a select which correctly reacts on change (uncheck) by value', () => { const onChange = jest.fn(); @@ -91,7 +97,7 @@ export function testSelectField( }, ); - skipTestIf(options?.theme === 'antd')( + skipTestIf(isTheme(['mui', 'antd']))( ' - (multiple) renders a select which correctly reacts on change (uncheck) by selectedIndex', () => { const onChange = jest.fn(); @@ -105,7 +111,7 @@ export function testSelectField( }, ); - skipTestIf(options?.theme === 'antd')( + skipTestIf(isTheme(['mui', 'antd']))( ' - (multiple) renders a select which correctly reacts on change (checked) by selectedIndex', () => { const onChange = jest.fn(); @@ -119,7 +125,7 @@ export function testSelectField( }, ); - skipTestIf(options?.theme === 'antd')( + skipTestIf(isTheme(['mui', 'antd']))( ' - renders a select which correctly reacts on change (uncheck) by value', () => { const onChange = jest.fn(); @@ -133,7 +139,7 @@ export function testSelectField( }, ); - skipTestIf(options?.theme === 'antd')( + skipTestIf(isTheme(['mui', 'antd']))( ' - renders a select which correctly reacts on change (uncheck) by selectedIndex', () => { const onChange = jest.fn(); @@ -175,41 +181,47 @@ export function testSelectField( expect(elementWithAttribute?.getAttribute('name')).toBe('x'); }); - test(' - renders a select with correct options', () => { - const selectOptions = ['a', 'b'] as const; - renderWithZod({ - element: , - schema: z.object({ x: z.enum(selectOptions) }), - }); - const combobox = screen.getByRole('combobox'); - fireEvent.mouseDown(combobox); - selectOptions.forEach(option => { - expect(screen.getByRole('option', { name: option })).not.toBeNull(); - }); - }); + skipTestIf(isTheme(['mui']))( + ' - renders a select with correct options', + () => { + const selectOptions = ['a', 'b'] as const; + renderWithZod({ + element: , + schema: z.object({ x: z.enum(selectOptions) }), + }); + const combobox = screen.getByRole('combobox'); + fireEvent.mouseDown(combobox); + selectOptions.forEach(option => { + expect(screen.getByRole('option', { name: option })).not.toBeNull(); + }); + }, + ); - test(' - renders a select with correct options (transform)', () => { - const selectOptions = ['a', 'b'] as const; - renderWithZod({ - element: ( - - ), - schema: z.object({ x: z.enum(selectOptions) }), - }); - const combobox = screen.getByRole('combobox'); - fireEvent.mouseDown(combobox); - selectOptions.forEach(option => { - expect( - screen.getByRole('option', { name: option.toUpperCase() }), - ).toBeInTheDocument(); - }); - }); + skipTestIf(isTheme(['mui']))( + ' - renders a select with correct options (transform)', + () => { + const selectOptions = ['a', 'b'] as const; + renderWithZod({ + element: ( + + ), + schema: z.object({ x: z.enum(selectOptions) }), + }); + const combobox = screen.getByRole('combobox'); + fireEvent.mouseDown(combobox); + selectOptions.forEach(option => { + expect( + screen.getByRole('option', { name: option.toUpperCase() }), + ).toBeInTheDocument(); + }); + }, + ); test(' - renders a select with correct placeholder (fallback)', () => { renderWithZod({ @@ -219,7 +231,7 @@ export function testSelectField( expect(screen.getByText('y')).toBeInTheDocument(); }); - skipTestIf(options?.theme === 'antd')( + skipTestIf(isTheme(['antd', 'mui']))( ' - renders a select with correct placeholder (implicit)', () => { renderWithZod({ @@ -230,59 +242,71 @@ export function testSelectField( }, ); - test(' - renders a select with correct value (default)', () => { - renderWithZod({ - element: , - schema: z.object({ x: z.enum(['a', 'b']) }), - }); - const select = screen.getByRole('combobox'); - if (options?.theme === 'antd') { - expect(screen.getByText('a')).toBeInTheDocument(); - expect(screen.queryByText('b')).not.toBeInTheDocument(); - } else { - expect(select).toHaveValue('a'); - } - }); + skipTestIf(isTheme(['antd', 'mui']))( + ' - renders a select with correct value (default)', + () => { + renderWithZod({ + element: , + schema: z.object({ x: z.enum(['a', 'b']) }), + }); + const select = screen.getByRole('combobox'); + if (options?.theme === 'antd') { + expect(screen.getByText('a')).toBeInTheDocument(); + expect(screen.queryByText('b')).not.toBeInTheDocument(); + } else { + expect(select).toHaveValue('a'); + } + }, + ); - test(' - renders a select with missing value (model)', () => { - renderWithZod({ - element: , - schema: z.object({ x: z.enum(['a', 'b']) }), - }); - const select = screen.getByRole('combobox'); - expect(select).toHaveValue(''); - }); + skipTestIf(isTheme(['antd', 'mui']))( + ' - renders a select with missing value (model)', + () => { + renderWithZod({ + element: , + schema: z.object({ x: z.enum(['a', 'b']) }), + }); + const select = screen.getByRole('combobox'); + expect(select).toHaveValue(''); + }, + ); - test(' - renders a select with correct value (model)', () => { - renderWithZod({ - element: , - schema: z.object({ x: z.enum(['a', 'b']) }), - model: { x: 'b' }, - }); - const select = screen.getByRole('combobox'); - if (options?.theme === 'antd') { - expect(screen.getByText('b')).toBeInTheDocument(); - expect(screen.queryByText('a')).not.toBeInTheDocument(); - } else { - expect(select).toHaveValue('b'); - } - }); + skipTestIf(isTheme(['antd', 'mui']))( + ' - renders a select with correct value (model)', + () => { + renderWithZod({ + element: , + schema: z.object({ x: z.enum(['a', 'b']) }), + model: { x: 'b' }, + }); + const select = screen.getByRole('combobox'); + if (options?.theme === 'antd') { + expect(screen.getByText('b')).toBeInTheDocument(); + expect(screen.queryByText('a')).not.toBeInTheDocument(); + } else { + expect(select).toHaveValue('b'); + } + }, + ); - test(' - renders a select with correct value (specified)', () => { - renderWithZod({ - element: , - schema: z.object({ x: z.enum(['a', 'b']) }), - }); - const select = screen.getByRole('combobox'); - if (options?.theme === 'antd') { - expect(screen.getByText('b')).toBeInTheDocument(); - expect(screen.queryByText('a')).not.toBeInTheDocument(); - } else { - expect(select).toHaveValue('b'); - } - }); + skipTestIf(isTheme(['antd', 'mui']))( + ' - renders a select with correct value (specified)', + () => { + renderWithZod({ + element: , + schema: z.object({ x: z.enum(['a', 'b']) }), + }); + const select = screen.getByRole('combobox'); + if (options?.theme === 'antd') { + expect(screen.getByText('b')).toBeInTheDocument(); + expect(screen.queryByText('a')).not.toBeInTheDocument(); + } else { + expect(select).toHaveValue('b'); + } + }, + ); - skipTestIf(options?.theme === 'antd')( + skipTestIf(isTheme(['antd', 'mui']))( ' - renders a select which correctly reacts on change', () => { const onChange = jest.fn(); @@ -296,7 +320,7 @@ export function testSelectField( }, ); - skipTestIf(options?.theme === 'antd')( + skipTestIf(isTheme(['antd', 'mui']))( ' - renders a select which correctly reacts on change (empty)', () => { const onChange = jest.fn(); @@ -310,7 +334,7 @@ export function testSelectField( }, ); - skipTestIf(options?.theme === 'antd')( + skipTestIf(isTheme(['antd', 'mui']))( ' - renders a select which correctly reacts on change (same value)', () => { const onChange = jest.fn(); @@ -344,18 +368,21 @@ export function testSelectField( expect(field).toHaveAttribute('data-y', 'y'); }); - test(' - works with special characters', () => { - renderWithZod({ - element: , - schema: z.object({ x: z.enum(['ă', 'ś']) }), - }); - const combobox = screen.getByRole('combobox'); - fireEvent.mouseDown(combobox); - expect(screen.getAllByText('ă')[0]).toBeInTheDocument(); - expect(screen.getAllByText('ś')[0]).toBeInTheDocument(); - }); + skipTestIf(isTheme(['mui']))( + ' - works with special characters', + () => { + renderWithZod({ + element: , + schema: z.object({ x: z.enum(['ă', 'ś']) }), + }); + const combobox = screen.getByRole('combobox'); + fireEvent.mouseDown(combobox); + expect(screen.getAllByText('ă')[0]).toBeInTheDocument(); + expect(screen.getAllByText('ś')[0]).toBeInTheDocument(); + }, + ); - skipTestIf(options?.theme === 'antd')( + skipTestIf(isTheme(['antd', 'mui']))( ' - disabled items (options)', () => { renderWithZod({ @@ -380,7 +407,11 @@ export function testSelectField( element: , schema: z.object({ x: z.enum(['a', 'b']) }), }); - expect(screen.getAllByRole(/checkbox|radio/)).toHaveLength(2); + expect( + screen + .getAllByRole(/checkbox|radio/) + .filter(element => element instanceof HTMLInputElement), + ).toHaveLength(2); }); test(' - renders a set of checkboxes with correct disabled state', () => { @@ -388,7 +419,9 @@ export function testSelectField( element: , schema: z.object({ x: z.enum(['a', 'b']) }), }); - const checkboxes = screen.getAllByRole(/checkbox|radio/); + const checkboxes = screen + .getAllByRole(/checkbox|radio/) + .filter(element => element instanceof HTMLInputElement); expect(checkboxes?.[0]).toBeDisabled(); expect(checkboxes?.[1]).toBeDisabled(); }); @@ -415,7 +448,7 @@ export function testSelectField( }, ); - skipTestIf(options?.theme === 'antd')( + skipTestIf(isTheme(['antd']))( ' - renders a set of checkboxes with correct id (inherited)', () => { renderWithZod({ @@ -427,14 +460,16 @@ export function testSelectField( }, ); - skipTestIf(options?.theme === 'antd')( + skipTestIf(isTheme(['antd']))( ' - renders a set of checkboxes with correct id (specified)', () => { renderWithZod({ element: , schema: z.object({ x: z.enum(['a', 'b']) }), }); - const checkboxes = screen.getAllByRole(/checkbox|radio/); + const checkboxes = screen + .getAllByRole(/checkbox|radio/) + .filter(element => element instanceof HTMLInputElement); expect(checkboxes?.[0]).toHaveAttribute('id', 'y-YQ'); expect(checkboxes?.[1]).toHaveAttribute('id', 'y-Yg'); }, @@ -445,7 +480,9 @@ export function testSelectField( element: , schema: z.object({ x: z.enum(['a', 'b']) }), }); - const checkboxes = screen.getAllByRole(/checkbox|radio/); + const checkboxes = screen + .getAllByRole(/checkbox|radio/) + .filter(element => element instanceof HTMLInputElement); expect(checkboxes?.[0]).toHaveAttribute('name', 'x'); expect(checkboxes?.[1]).toHaveAttribute('name', 'x'); }); @@ -482,7 +519,9 @@ export function testSelectField( element: , schema: z.object({ x: z.enum(['a', 'b']) }), }); - const checkboxes = screen.getAllByRole(/checkbox|radio/); + const checkboxes = screen + .getAllByRole(/checkbox|radio/) + .filter(element => element instanceof HTMLInputElement); expect(checkboxes?.[0]).toBeChecked(); expect(checkboxes?.[1]).not.toBeChecked(); }); @@ -493,7 +532,9 @@ export function testSelectField( schema: z.object({ x: z.enum(['a', 'b']) }), model: { x: 'b' }, }); - const checkboxes = screen.getAllByRole(/checkbox|radio/); + const checkboxes = screen + .getAllByRole(/checkbox|radio/) + .filter(element => element instanceof HTMLInputElement); expect(checkboxes?.[0]).not.toBeChecked(); expect(checkboxes?.[1]).toBeChecked(); }); @@ -503,7 +544,9 @@ export function testSelectField( element: , schema: z.object({ x: z.enum(['a', 'b']) }), }); - const checkboxes = screen.getAllByRole(/checkbox|radio/); + const checkboxes = screen + .getAllByRole(/checkbox|radio/) + .filter(element => element instanceof HTMLInputElement); expect(checkboxes?.[0]).not.toBeChecked(); expect(checkboxes?.[1]).toBeChecked(); }); @@ -514,7 +557,10 @@ export function testSelectField( element: , schema: z.object({ x: z.enum(['a', 'b']) }), }); - const checkboxes = screen.getAllByRole(/checkbox|radio/); + const checkboxes = screen + .getAllByRole(/checkbox|radio/) + .filter(element => element instanceof HTMLInputElement); + fireEvent.click(checkboxes?.[1]); expect(onChange).toHaveBeenCalledWith('b'); }); @@ -579,25 +625,29 @@ export function testSelectField( expect(screen.getByText('y')).toBeInTheDocument(); }); - test(' - renders a wrapper with unknown props', () => { - renderWithZod({ - element: ( - - ), - schema: z.object({ x: z.enum(['a', 'b']) }), - }); - const field = screen.getByTestId('select-field'); - expect(field).toHaveAttribute('data-x', 'x'); - expect(field).toHaveAttribute('data-z', 'z'); - expect(field).toHaveAttribute('data-y', 'y'); - }); + // TODO: Fix me - MUI renders multiple checkboxes and wrappers with the same id + skipTestIf(isTheme(['mui']))( + ' - renders a wrapper with unknown props', + () => { + renderWithZod({ + element: ( + + ), + schema: z.object({ x: z.enum(['a', 'b']) }), + }); + const field = screen.getByTestId('select-field'); + expect(field).toHaveAttribute('data-x', 'x'); + expect(field).toHaveAttribute('data-z', 'z'); + expect(field).toHaveAttribute('data-y', 'y'); + }, + ); test(' - works with special characters', () => { renderWithZod({ @@ -622,7 +672,10 @@ export function testSelectField( ), schema: z.object({ x: z.enum(['a', 'b']) }), }); - const checkboxes = screen.getAllByRole(/checkbox|radio/); + const checkboxes = screen + .getAllByRole(/checkbox|radio/) + .filter(element => element instanceof HTMLInputElement); + expect(checkboxes?.[0]).toBeDisabled(); expect(checkboxes?.[1]).not.toBeDisabled(); }); @@ -650,7 +703,7 @@ export function testSelectField( }, ); - skipTestIf(!options?.showInlineError)( + skipTestIf(options?.showInlineError !== false)( ' - renders correct error text (showInlineError=false)', () => { const error = new Error();