From 8b3f6f5c79b4144cb7d2ad33661c88964df8e8e3 Mon Sep 17 00:00:00 2001 From: Adrian Mucha Date: Fri, 29 Mar 2024 12:12:43 +0100 Subject: [PATCH] Migrated `TextField` tests to @testing-library/react (#1298) --- .../uniforms-antd/__tests__/TextField.tsx | 193 ------------ .../__tests__/TextField.tsx | 189 ------------ .../uniforms-bootstrap3/__tests__/index.ts | 2 +- .../__tests__/TextField.tsx | 189 ------------ .../uniforms-bootstrap4/__tests__/index.ts | 2 +- .../__tests__/TextField.tsx | 200 ------------ .../uniforms-bootstrap5/__tests__/index.ts | 5 +- .../__tests__/LongTextField.tsx | 73 ----- .../uniforms-material/__tests__/TextField.tsx | 272 ----------------- .../__tests__/{index.ts => index.tsx} | 36 ++- packages/uniforms-mui/__tests__/TextField.tsx | 179 ----------- .../uniforms-semantic/__tests__/TextField.tsx | 284 ------------------ packages/uniforms-semantic/__tests__/index.ts | 6 +- .../uniforms-unstyled/__tests__/TextField.tsx | 171 ----------- packages/uniforms-unstyled/__tests__/index.ts | 2 +- .../uniforms/__suites__/LongTextField.tsx | 74 ++++- packages/uniforms/__suites__/TextField.tsx | 209 ++++++++++++- 17 files changed, 326 insertions(+), 1760 deletions(-) delete mode 100644 packages/uniforms-antd/__tests__/TextField.tsx delete mode 100644 packages/uniforms-bootstrap3/__tests__/TextField.tsx delete mode 100644 packages/uniforms-bootstrap4/__tests__/TextField.tsx delete mode 100644 packages/uniforms-bootstrap5/__tests__/TextField.tsx delete mode 100644 packages/uniforms-material/__tests__/LongTextField.tsx delete mode 100644 packages/uniforms-material/__tests__/TextField.tsx rename packages/uniforms-material/__tests__/{index.ts => index.tsx} (69%) delete mode 100644 packages/uniforms-mui/__tests__/TextField.tsx delete mode 100644 packages/uniforms-semantic/__tests__/TextField.tsx delete mode 100644 packages/uniforms-unstyled/__tests__/TextField.tsx diff --git a/packages/uniforms-antd/__tests__/TextField.tsx b/packages/uniforms-antd/__tests__/TextField.tsx deleted file mode 100644 index fcaaa22ec..000000000 --- a/packages/uniforms-antd/__tests__/TextField.tsx +++ /dev/null @@ -1,193 +0,0 @@ -import { screen } from '@testing-library/react'; -import Input from 'antd/lib/input'; -import React from 'react'; -import { TextField } from 'uniforms-antd'; -import { render } from 'uniforms/__suites__'; - -import createContext from './_createContext'; -import mount from './_mount'; - -describe('@RTL - TextField tests', () => { - test(' - renders component with unknown props', () => { - const props = { - 'data-x': 'x', - 'data-y': 'y', - 'data-z': 'z', - }; - render(, { x: String }); - - const input = screen.getByRole('textbox'); - Object.entries(props).forEach(([key, value]) => - expect(input).toHaveAttribute(key, value), - ); - }); -}); - -test(' - renders an input', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(Input)).toHaveLength(1); -}); - -test(' - renders an input with correct disabled state', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(Input)).toHaveLength(1); - expect(wrapper.find(Input).prop('disabled')).toBe(true); -}); - -test(' - renders an input with correct readOnly state', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(Input)).toHaveLength(1); - expect(wrapper.find(Input).prop('readOnly')).toBe(true); -}); - -test(' - renders an input with correct id (inherited)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(Input)).toHaveLength(1); - expect(wrapper.find(Input).prop('id')).toBeTruthy(); -}); - -test(' - renders an input with correct id (specified)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(Input)).toHaveLength(1); - expect(wrapper.find(Input).prop('id')).toBe('y'); -}); - -test(' - renders an input with correct name', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(Input)).toHaveLength(1); - expect(wrapper.find(Input).prop('name')).toBe('x'); -}); - -test(' - renders an input with correct placeholder', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(Input)).toHaveLength(1); - expect(wrapper.find(Input).prop('placeholder')).toBe('y'); -}); - -test(' - renders an input with correct type', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(Input)).toHaveLength(1); - expect(wrapper.find(Input).prop('type')).toBe('text'); -}); - -test(' - renders an input with correct value (default)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(Input)).toHaveLength(1); - expect(wrapper.find(Input).prop('value')).toBe(''); -}); - -test(' - renders an input with correct value (model)', () => { - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { model: { x: 'y' } }), - ); - - expect(wrapper.find(Input)).toHaveLength(1); - expect(wrapper.find(Input).prop('value')).toBe('y'); -}); - -test(' - renders an input with correct value (specified)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(Input)).toHaveLength(1); - expect(wrapper.find(Input).prop('value')).toBe('y'); -}); - -test(' - renders an input which correctly reacts on change', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { onChange }), - ); - - expect(wrapper.find(Input)).toHaveLength(1); - expect( - wrapper.find(Input).simulate('change', { target: { value: 'y' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', 'y'); -}); - -test(' - renders an input which correctly reacts on change (empty)', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { onChange }), - ); - - expect(wrapper.find(Input)).toHaveLength(1); - expect( - wrapper.find(Input).simulate('change', { target: { value: '' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', ''); -}); - -test(' - renders an input which correctly reacts on change (same value)', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { model: { x: 'y' }, onChange }), - ); - - expect(wrapper.find(Input)).toHaveLength(1); - expect( - wrapper.find(Input).simulate('change', { target: { value: 'y' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', 'y'); -}); - -test(' - renders a label', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('label')).toHaveLength(1); - expect(wrapper.find('label').text()).toBe('y'); -}); - -test(' - renders a wrapper with unknown props', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(Input).prop('data-x')).toBe('x'); - expect(wrapper.find(Input).prop('data-y')).toBe('y'); - expect(wrapper.find(Input).prop('data-z')).toBe('z'); -}); - -test(' - renders a input with correct type prop', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(Input).prop('type')).toBe('password'); -}); - -test(' - renders a input with autocomplete turned off', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(Input).prop('autoComplete')).toBe('off'); -}); diff --git a/packages/uniforms-bootstrap3/__tests__/TextField.tsx b/packages/uniforms-bootstrap3/__tests__/TextField.tsx deleted file mode 100644 index 749c200de..000000000 --- a/packages/uniforms-bootstrap3/__tests__/TextField.tsx +++ /dev/null @@ -1,189 +0,0 @@ -import { screen } from '@testing-library/react'; -import React from 'react'; -import { TextField } from 'uniforms-bootstrap3'; -import { render } from 'uniforms/__suites__'; - -import createContext from './_createContext'; -import mount from './_mount'; - -describe('@RTL - TextField tests', () => { - test(' - renders a wrapper with unknown props', () => { - const props = { - 'data-x': 'x', - 'data-y': 'y', - 'data-z': 'z', - }; - render(, { x: String }); - - const wrapper = screen.getByRole('textbox').closest('div'); - Object.entries(props).forEach(([key, value]) => - expect(wrapper).toHaveAttribute(key, value), - ); - }); -}); - -test(' - renders an input', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); -}); - -test(' - renders an input with correct disabled state', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('disabled')).toBe(true); -}); - -test(' - renders an input with correct readOnly state', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('readOnly')).toBe(true); -}); - -test(' - renders an input with correct id (inherited)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('id')).toBeTruthy(); -}); - -test(' - renders an input with correct id (specified)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('id')).toBe('y'); -}); - -test(' - renders an input with correct name', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('name')).toBe('x'); -}); - -test(' - renders an input with correct placeholder', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('placeholder')).toBe('y'); -}); - -test(' - renders an input with correct type', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('type')).toBe('text'); -}); - -test(' - renders an input with correct value (default)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('value')).toBe(''); -}); - -test(' - renders an input with correct value (model)', () => { - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { model: { x: 'y' } }), - ); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('value')).toBe('y'); -}); - -test(' - renders an input with correct value (specified)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('value')).toBe('y'); -}); - -test(' - renders an input which correctly reacts on change', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { onChange }), - ); - - expect(wrapper.find('input')).toHaveLength(1); - expect( - wrapper.find('input').simulate('change', { target: { value: 'y' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', 'y'); -}); - -test(' - renders an input which correctly reacts on change (empty)', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { onChange }), - ); - - expect(wrapper.find('input')).toHaveLength(1); - expect( - wrapper.find('input').simulate('change', { target: { value: '' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', ''); -}); - -test(' - renders an input which correctly reacts on change (same value)', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { model: { x: 'y' }, onChange }), - ); - - expect(wrapper.find('input')).toHaveLength(1); - expect( - wrapper.find('input').simulate('change', { target: { value: 'y' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', 'y'); -}); - -test(' - renders a label', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('label')).toHaveLength(1); - expect(wrapper.find('label').text()).toBe('y'); - expect(wrapper.find('label').prop('htmlFor')).toBe( - wrapper.find('input').prop('id'), - ); -}); - -test(' - renders a wrapper with unknown props', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('div').at(0).prop('data-x')).toBe('x'); - expect(wrapper.find('div').at(0).prop('data-y')).toBe('y'); - expect(wrapper.find('div').at(0).prop('data-z')).toBe('z'); -}); - -test(' - renders a input with autocomplete turned off', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('div').at(0).prop('autoComplete')).toBeFalsy(); - expect(wrapper.find('input').prop('autoComplete')).toBe('off'); -}); diff --git a/packages/uniforms-bootstrap3/__tests__/index.ts b/packages/uniforms-bootstrap3/__tests__/index.ts index fb7d76594..17c4da346 100644 --- a/packages/uniforms-bootstrap3/__tests__/index.ts +++ b/packages/uniforms-bootstrap3/__tests__/index.ts @@ -56,7 +56,7 @@ describe('@RTL', () => { suites.testQuickForm(theme.QuickForm); suites.testRadioField(theme.RadioField); suites.testSubmitField(theme.SubmitField); - suites.testTextField(theme.TextField); + suites.testTextField(theme.TextField, { testWrapClassName: true }); suites.testValidatedForm(theme.ValidatedForm); suites.testValidatedQuickForm(theme.ValidatedQuickForm); }); diff --git a/packages/uniforms-bootstrap4/__tests__/TextField.tsx b/packages/uniforms-bootstrap4/__tests__/TextField.tsx deleted file mode 100644 index 666bfc861..000000000 --- a/packages/uniforms-bootstrap4/__tests__/TextField.tsx +++ /dev/null @@ -1,189 +0,0 @@ -import { screen } from '@testing-library/react'; -import React from 'react'; -import { TextField } from 'uniforms-bootstrap4'; -import { render } from 'uniforms/__suites__'; - -import createContext from './_createContext'; -import mount from './_mount'; - -describe('@RTL - TextField tests', () => { - test(' - renders a wrapper with unknown props', () => { - const props = { - 'data-x': 'x', - 'data-y': 'y', - 'data-z': 'z', - }; - render(, { x: String }); - - const wrapper = screen.getByRole('textbox').closest('div'); - Object.entries(props).forEach(([key, value]) => - expect(wrapper).toHaveAttribute(key, value), - ); - }); -}); - -test(' - renders an input', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); -}); - -test(' - renders an input with correct disabled state', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('disabled')).toBe(true); -}); - -test(' - renders an input with correct readOnly state', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('readOnly')).toBe(true); -}); - -test(' - renders an input with correct id (inherited)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('id')).toBeTruthy(); -}); - -test(' - renders an input with correct id (specified)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('id')).toBe('y'); -}); - -test(' - renders an input with correct name', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('name')).toBe('x'); -}); - -test(' - renders an input with correct placeholder', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('placeholder')).toBe('y'); -}); - -test(' - renders an input with correct type', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('type')).toBe('text'); -}); - -test(' - renders an input with correct value (default)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('value')).toBe(''); -}); - -test(' - renders an input with correct value (model)', () => { - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { model: { x: 'y' } }), - ); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('value')).toBe('y'); -}); - -test(' - renders an input with correct value (specified)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('value')).toBe('y'); -}); - -test(' - renders an input which correctly reacts on change', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { onChange }), - ); - - expect(wrapper.find('input')).toHaveLength(1); - expect( - wrapper.find('input').simulate('change', { target: { value: 'y' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', 'y'); -}); - -test(' - renders an input which correctly reacts on change (empty)', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { onChange }), - ); - - expect(wrapper.find('input')).toHaveLength(1); - expect( - wrapper.find('input').simulate('change', { target: { value: '' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', ''); -}); - -test(' - renders an input which correctly reacts on change (same value)', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { model: { x: 'y' }, onChange }), - ); - - expect(wrapper.find('input')).toHaveLength(1); - expect( - wrapper.find('input').simulate('change', { target: { value: 'y' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', 'y'); -}); - -test(' - renders a label', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('label')).toHaveLength(1); - expect(wrapper.find('label').text()).toBe('y'); - expect(wrapper.find('label').prop('htmlFor')).toBe( - wrapper.find('input').prop('id'), - ); -}); - -test(' - renders a wrapper with unknown props', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('div').at(0).prop('data-x')).toBe('x'); - expect(wrapper.find('div').at(0).prop('data-y')).toBe('y'); - expect(wrapper.find('div').at(0).prop('data-z')).toBe('z'); -}); - -test(' - renders a input with autocomplete turned off', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('div').at(0).prop('autoComplete')).toBeFalsy(); - expect(wrapper.find('input').prop('autoComplete')).toBe('off'); -}); diff --git a/packages/uniforms-bootstrap4/__tests__/index.ts b/packages/uniforms-bootstrap4/__tests__/index.ts index 31e0a2b56..6d828563a 100644 --- a/packages/uniforms-bootstrap4/__tests__/index.ts +++ b/packages/uniforms-bootstrap4/__tests__/index.ts @@ -56,7 +56,7 @@ describe('@RTL', () => { suites.testQuickForm(theme.QuickForm); suites.testRadioField(theme.RadioField); suites.testSubmitField(theme.SubmitField); - suites.testTextField(theme.TextField); + suites.testTextField(theme.TextField, { testWrapClassName: true }); suites.testValidatedForm(theme.ValidatedForm); suites.testValidatedQuickForm(theme.ValidatedQuickForm); }); diff --git a/packages/uniforms-bootstrap5/__tests__/TextField.tsx b/packages/uniforms-bootstrap5/__tests__/TextField.tsx deleted file mode 100644 index aee886918..000000000 --- a/packages/uniforms-bootstrap5/__tests__/TextField.tsx +++ /dev/null @@ -1,200 +0,0 @@ -import { screen } from '@testing-library/react'; -import React from 'react'; -import { TextField } from 'uniforms-bootstrap5'; -import { render } from 'uniforms/__suites__'; - -import createContext from './_createContext'; -import mount from './_mount'; - -describe('@RTL - TextField tests', () => { - test(' - renders a wrapper with unknown props', () => { - const props = { - 'data-x': 'x', - 'data-y': 'y', - 'data-z': 'z', - }; - render(, { x: String }); - - const wrapper = screen.getByRole('textbox').closest('div'); - Object.entries(props).forEach(([key, value]) => - expect(wrapper).toHaveAttribute(key, value), - ); - }); -}); - -test(' - renders an input', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); -}); - -test(' - renders an input with correct disabled state', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('disabled')).toBe(true); -}); - -test(' - renders an input with correct readOnly state', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('readOnly')).toBe(true); -}); - -test(' - renders an input with correct id (inherited)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('id')).toBeTruthy(); -}); - -test(' - renders an input with correct id (specified)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('id')).toBe('y'); -}); - -test(' - renders an input with correct name', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('name')).toBe('x'); -}); - -test(' - renders an input with correct placeholder', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('placeholder')).toBe('y'); -}); - -test(' - renders an input with correct type', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('type')).toBe('text'); -}); - -test(' - renders an input with correct value (default)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('value')).toBe(''); -}); - -test(' - renders an input with correct value (model)', () => { - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { model: { x: 'y' } }), - ); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('value')).toBe('y'); -}); - -test(' - renders an input with correct value (specified)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('value')).toBe('y'); -}); - -test(' - renders an input which correctly reacts on change', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { onChange }), - ); - - expect(wrapper.find('input')).toHaveLength(1); - expect( - wrapper.find('input').simulate('change', { target: { value: 'y' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', 'y'); -}); - -test(' - renders an input which correctly reacts on change (empty)', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { onChange }), - ); - - expect(wrapper.find('input')).toHaveLength(1); - expect( - wrapper.find('input').simulate('change', { target: { value: '' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', ''); -}); - -test(' - renders an input which correctly reacts on change (same value)', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { model: { x: 'y' }, onChange }), - ); - - expect(wrapper.find('input')).toHaveLength(1); - expect( - wrapper.find('input').simulate('change', { target: { value: 'y' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', 'y'); -}); - -test(' - renders a label', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('label')).toHaveLength(1); - expect(wrapper.find('label').text()).toBe('y'); - expect(wrapper.find('label').prop('htmlFor')).toBe( - wrapper.find('input').prop('id'), - ); -}); - -test(' - renders a wrapper with unknown props', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('div').at(0).prop('data-x')).toBe('x'); - expect(wrapper.find('div').at(0).prop('data-y')).toBe('y'); - expect(wrapper.find('div').at(0).prop('data-z')).toBe('z'); -}); - -test(' - renders a input with autocomplete turned off', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('div').at(0).prop('autoComplete')).toBeFalsy(); - expect(wrapper.find('input').prop('autoComplete')).toBe('off'); -}); - -test(' - renders a input with minLength and maxLength', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('div').at(0).prop('minLength')).toBeFalsy(); - expect(wrapper.find('input').prop('minLength')).toBe(1); - - expect(wrapper.find('div').at(0).prop('maxLength')).toBeFalsy(); - expect(wrapper.find('input').prop('maxLength')).toBe(10); -}); diff --git a/packages/uniforms-bootstrap5/__tests__/index.ts b/packages/uniforms-bootstrap5/__tests__/index.ts index 6e036c834..851845fe8 100644 --- a/packages/uniforms-bootstrap5/__tests__/index.ts +++ b/packages/uniforms-bootstrap5/__tests__/index.ts @@ -58,7 +58,10 @@ describe('@RTL', () => { suites.testQuickForm(theme.QuickForm); suites.testRadioField(theme.RadioField); suites.testSubmitField(theme.SubmitField); - suites.testTextField(theme.TextField); + suites.testTextField(theme.TextField, { + testWrapClassName: true, + testMinMaxLength: true, + }); suites.testValidatedForm(theme.ValidatedForm); suites.testValidatedQuickForm(theme.ValidatedQuickForm); }); diff --git a/packages/uniforms-material/__tests__/LongTextField.tsx b/packages/uniforms-material/__tests__/LongTextField.tsx deleted file mode 100644 index 9c2708667..000000000 --- a/packages/uniforms-material/__tests__/LongTextField.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import createMuiTheme from '@material-ui/core/styles/createMuiTheme'; -import ThemeProvider from '@material-ui/styles/ThemeProvider/ThemeProvider'; -import React from 'react'; -import { LongTextField } from 'uniforms-material'; -import { renderWithZod } from 'uniforms/__suites__'; -import z from 'zod'; - -describe('@RTL - LongTextField tests', () => { - test(' - default props are not passed when MUI theme props are specified', () => { - const theme = createMuiTheme({ - props: { MuiTextField: { fullWidth: false, margin: 'normal' } }, - }); - - const { container } = renderWithZod({ - element: ( - - - - ), - schema: z.object({ x: z.string() }), - }); - - const elements = container.getElementsByClassName( - 'MuiFormControl-marginNormal', - ); - expect(elements).toHaveLength(1); - expect(elements[0]).not.toHaveClass('MuiFormControl-fullWidth'); - }); - - test(' - default props are passed when MUI theme props are absent', () => { - const theme = createMuiTheme({}); - - const { container } = renderWithZod({ - element: ( - - - - ), - schema: z.object({ x: z.string() }), - }); - - const elements = container.getElementsByClassName( - 'MuiFormControl-marginDense', - ); - expect(elements).toHaveLength(1); - expect(elements[0]).toHaveClass('MuiFormControl-fullWidth'); - }); - - test(' - explicit props are passed when MUI theme props are specified', () => { - const theme = createMuiTheme({ - props: { MuiTextField: { fullWidth: true, margin: 'dense' } }, - }); - const explicitProps = { - fullWidth: false, - margin: 'normal' as const, - }; - - const { container } = renderWithZod({ - element: ( - - - - ), - schema: z.object({ x: z.string() }), - }); - - const elements = container.getElementsByClassName( - 'MuiFormControl-marginNormal', - ); - expect(elements).toHaveLength(1); - expect(elements[0]).not.toHaveClass('MuiFormControl-fullWidth'); - }); -}); diff --git a/packages/uniforms-material/__tests__/TextField.tsx b/packages/uniforms-material/__tests__/TextField.tsx deleted file mode 100644 index bda931460..000000000 --- a/packages/uniforms-material/__tests__/TextField.tsx +++ /dev/null @@ -1,272 +0,0 @@ -import TextFieldMaterial from '@material-ui/core/TextField'; -import createMuiTheme from '@material-ui/core/styles/createMuiTheme'; -import ThemeProvider from '@material-ui/styles/ThemeProvider/ThemeProvider'; -import { screen } from '@testing-library/react'; -import React from 'react'; -import { TextField } from 'uniforms-material'; -import { render } from 'uniforms/__suites__'; - -import createContext from './_createContext'; -import mount from './_mount'; - -describe('@RTL - TextField tests', () => { - test(' - renders a TextField with correct error text (specified)', () => { - const errorMessage = 'Error'; - render( - , - { x: String }, - ); - - expect(screen.getByText(errorMessage)).toBeInTheDocument(); - }); - - test(' - renders a TextField with correct error text (showInlineError=false)', () => { - const errorMessage = 'Error'; - render( - , - { x: String }, - ); - - expect(screen.queryByText(errorMessage)).not.toBeInTheDocument(); - }); - - test(' - default props are not passed when MUI theme props are specified', () => { - const theme = createMuiTheme({ - props: { MuiTextField: { fullWidth: false, margin: 'normal' } }, - }); - const { container } = render( - - - , - { x: { type: String } }, - ); - - const elements = container.getElementsByClassName( - 'MuiFormControl-marginNormal', - ); - expect(elements).toHaveLength(1); - expect(elements[0]).not.toHaveClass('MuiFormControl-fullWidth'); - }); - - test(' - default props are passed when MUI theme props are absent', () => { - const theme = createMuiTheme({}); - const { container } = render( - - - , - { x: { type: String } }, - ); - - const elements = container.getElementsByClassName( - 'MuiFormControl-marginDense', - ); - expect(elements).toHaveLength(1); - expect(elements[0]).toHaveClass('MuiFormControl-fullWidth'); - }); - - test(' - explicit props are passed when MUI theme props are specified', () => { - const theme = createMuiTheme({ - props: { MuiTextField: { fullWidth: true, margin: 'dense' } }, - }); - const explicitProps = { - fullWidth: false, - margin: 'normal' as const, - }; - - const { container } = render( - - - , - { x: { type: String } }, - ); - - const elements = container.getElementsByClassName( - 'MuiFormControl-marginNormal', - ); - expect(elements).toHaveLength(1); - expect(elements[0]).not.toHaveClass('MuiFormControl-fullWidth'); - }); -}); - -test(' - renders an TextField', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); -}); - -test(' - renders a TextField with correct disabled state', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('disabled')).toBe(true); -}); - -test(' - renders a TextField with correct readOnly state', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('inputProps')!.readOnly).toBe( - true, - ); -}); - -test(' - renders a TextField with correct id (inherited)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('id')).toBeTruthy(); -}); - -test(' - renders a TextField with correct id (specified)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('id')).toBe('y'); -}); - -test(' - renders a TextField with correct name', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('name')).toBe('x'); -}); - -test(' - renders a TextField with correct placeholder', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('placeholder')).toBe('y'); -}); - -test(' - renders a TextField with correct value (default)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('value')).toBe(''); -}); - -test(' - renders a TextField with correct value (model)', () => { - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { model: { x: 'y' } }), - ); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('value')).toBe('y'); -}); - -test(' - renders a TextField with correct value (specified)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('value')).toBe('y'); -}); - -test(' - renders a TextField which correctly reacts on change', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { onChange }), - ); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect( - wrapper.find('input').simulate('change', { target: { value: 'y' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', 'y'); -}); - -test(' - renders a TextField which correctly reacts on change (empty)', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { onChange }), - ); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect( - wrapper.find('input').simulate('change', { target: { value: '' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', ''); -}); - -test(' - renders a TextField which correctly reacts on change (same value)', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { model: { x: 'y' }, onChange }), - ); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect( - wrapper.find('input').simulate('change', { target: { value: 'y' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', 'y'); -}); - -test(' - renders a label', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('label')).toBe('y'); -}); - -test(' - renders a TextField with correct error text (specified)', () => { - const error = new Error(); - const element = ( - - ); - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial).prop('helperText')).toBe('Error'); -}); - -test(' - renders a TextField with correct error text (showInlineError=false)', () => { - const error = new Error(); - const element = ( - - ); - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial).prop('helperText')).toBeUndefined(); -}); - -test(' - renders a input with autocomplete off', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('autoComplete')).toBe('off'); -}); diff --git a/packages/uniforms-material/__tests__/index.ts b/packages/uniforms-material/__tests__/index.tsx similarity index 69% rename from packages/uniforms-material/__tests__/index.ts rename to packages/uniforms-material/__tests__/index.tsx index a74821372..4376e8005 100644 --- a/packages/uniforms-material/__tests__/index.ts +++ b/packages/uniforms-material/__tests__/index.tsx @@ -1,3 +1,8 @@ +import createMuiTheme, { + ThemeOptions, +} from '@material-ui/core/styles/createMuiTheme'; +import ThemeProvider from '@material-ui/styles/ThemeProvider/ThemeProvider'; +import React, { PropsWithChildren } from 'react'; import * as theme from 'uniforms-material'; import * as suites from 'uniforms/__suites__'; @@ -52,13 +57,40 @@ describe('@RTL', () => { testError: false, }); suites.testListItemField(theme.ListItemField); - suites.testLongTextField(theme.LongTextField); + suites.testLongTextField(theme.LongTextField, { + testPassThemeProps: { + ThemeProvider({ + themeOptions, + ...props + }: PropsWithChildren<{ themeOptions: ThemeOptions }>) { + return ( + + {props.children} + + ); + }, + }, + }); suites.testNestField(theme.NestField, { skipInMuiTests: true }); suites.testNumField(theme.NumField); suites.testQuickForm(theme.QuickForm); suites.testRadioField(theme.RadioField); suites.testSubmitField(theme.SubmitField); - suites.testTextField(theme.TextField); + suites.testTextField(theme.TextField, { + testShowInlineError: true, + testPassThemeProps: { + ThemeProvider({ + themeOptions, + ...props + }: PropsWithChildren<{ themeOptions: ThemeOptions }>) { + return ( + + {props.children} + + ); + }, + }, + }); suites.testValidatedForm(theme.ValidatedForm); suites.testValidatedQuickForm(theme.ValidatedQuickForm); }); diff --git a/packages/uniforms-mui/__tests__/TextField.tsx b/packages/uniforms-mui/__tests__/TextField.tsx deleted file mode 100644 index ae18aca3d..000000000 --- a/packages/uniforms-mui/__tests__/TextField.tsx +++ /dev/null @@ -1,179 +0,0 @@ -import TextFieldMaterial from '@mui/material/TextField'; -import React from 'react'; -import { TextField } from 'uniforms-mui'; - -import createContext from './_createContext'; -import mount from './_mount'; - -test(' - renders an TextField', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); -}); - -test(' - renders a TextField with correct disabled state', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('disabled')).toBe(true); -}); - -test(' - renders a TextField with correct readOnly state', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('inputProps')!.readOnly).toBe( - true, - ); -}); - -test(' - renders a TextField with correct id (inherited)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('id')).toBeTruthy(); -}); - -test(' - renders a TextField with correct id (specified)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('id')).toBe('y'); -}); - -test(' - renders a TextField with correct name', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('name')).toBe('x'); -}); - -test(' - renders a TextField with correct placeholder', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('placeholder')).toBe('y'); -}); - -test(' - renders a TextField with correct value (default)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('value')).toBe(''); -}); - -test(' - renders a TextField with correct value (model)', () => { - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { model: { x: 'y' } }), - ); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('value')).toBe('y'); -}); - -test(' - renders a TextField with correct value (specified)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('value')).toBe('y'); -}); - -test(' - renders a TextField which correctly reacts on change', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { onChange }), - ); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect( - wrapper.find('input').simulate('change', { target: { value: 'y' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', 'y'); -}); - -test(' - renders a TextField which correctly reacts on change (empty)', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { onChange }), - ); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect( - wrapper.find('input').simulate('change', { target: { value: '' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', ''); -}); - -test(' - renders a TextField which correctly reacts on change (same value)', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { model: { x: 'y' }, onChange }), - ); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect( - wrapper.find('input').simulate('change', { target: { value: 'y' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', 'y'); -}); - -test(' - renders a label', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('label')).toBe('y'); -}); - -test(' - renders a TextField with correct error text (specified)', () => { - const error = new Error(); - const element = ( - - ); - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial).prop('helperText')).toBe('Error'); -}); - -test(' - renders a TextField with correct error text (showInlineError=false)', () => { - const error = new Error(); - const element = ( - - ); - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial).prop('helperText')).toBeUndefined(); -}); - -test(' - renders a input with autocomplete off', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find(TextFieldMaterial)).toHaveLength(1); - expect(wrapper.find(TextFieldMaterial).prop('autoComplete')).toBe('off'); -}); diff --git a/packages/uniforms-semantic/__tests__/TextField.tsx b/packages/uniforms-semantic/__tests__/TextField.tsx deleted file mode 100644 index 7f482bfed..000000000 --- a/packages/uniforms-semantic/__tests__/TextField.tsx +++ /dev/null @@ -1,284 +0,0 @@ -import { screen } from '@testing-library/react'; -import React from 'react'; -import { TextField } from 'uniforms-semantic'; -import { render } from 'uniforms/__suites__'; - -import createContext from './_createContext'; -import mount from './_mount'; - -describe('@RTL - TextField tests', () => { - test(' - renders a wrapper with unknown props', () => { - const props = { - 'data-x': 'x', - 'data-y': 'y', - 'data-z': 'z', - }; - render(, { x: String }); - - const wrapper = screen.getByRole('textbox').closest('div')?.parentElement; - Object.entries(props).forEach(([key, value]) => - expect(wrapper).toHaveAttribute(key, value), - ); - }); - - test(' - renders a TextField with correct error text (specified)', () => { - const errorMessage = 'Error'; - render( - , - { x: String }, - ); - - expect(screen.getByText(errorMessage)).toBeInTheDocument(); - }); - - test(' - renders a TextField with correct error text (showInlineError=false)', () => { - const errorMessage = 'Error'; - render( - , - { x: String }, - ); - - expect(screen.queryByText(errorMessage)).not.toBeInTheDocument(); - }); - - test(' - renders an icon', () => { - const { container } = render(, { - x: String, - }); - - expect(container.querySelector('i')).toBeInTheDocument(); - }); - - test(' - renders with a custom wrapClassName', () => { - const testClassName = 'test-class-name'; - render(, { x: String }); - - expect(screen.getByRole('textbox').closest('div')).toHaveClass( - testClassName, - ); - }); -}); - -test(' - renders an input', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); -}); - -test(' - renders an input with correct disabled state', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('disabled')).toBe(true); -}); - -test(' - renders an input with correct readOnly state', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('readOnly')).toBe(true); -}); - -test(' - renders an input with correct id (inherited)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('id')).toBeTruthy(); -}); - -test(' - renders an input with correct id (specified)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('id')).toBe('y'); -}); - -test(' - renders an input with correct name', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('name')).toBe('x'); -}); - -test(' - renders an input with correct placeholder', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('placeholder')).toBe('y'); -}); - -test(' - renders an input with correct type', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('type')).toBe('text'); -}); - -test(' - renders an input with correct value (default)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('value')).toBe(''); -}); - -test(' - renders an input with correct value (model)', () => { - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { model: { x: 'y' } }), - ); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('value')).toBe('y'); -}); - -test(' - renders an input with correct value (specified)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('value')).toBe('y'); -}); - -test(' - renders an input which correctly reacts on change', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { onChange }), - ); - - expect(wrapper.find('input')).toHaveLength(1); - expect( - wrapper.find('input').simulate('change', { target: { value: 'y' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', 'y'); -}); - -test(' - renders an input which correctly reacts on change (empty)', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { onChange }), - ); - - expect(wrapper.find('input')).toHaveLength(1); - expect( - wrapper.find('input').simulate('change', { target: { value: '' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', ''); -}); - -test(' - renders an input which correctly reacts on change (same value)', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { model: { x: 'y' }, onChange }), - ); - - expect(wrapper.find('input')).toHaveLength(1); - expect( - wrapper.find('input').simulate('change', { target: { value: 'y' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', 'y'); -}); - -test(' - renders a label', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('label')).toHaveLength(1); - expect(wrapper.find('label').text()).toBe('y'); - expect(wrapper.find('label').prop('htmlFor')).toBe( - wrapper.find('input').prop('id'), - ); -}); - -test(' - renders a wrapper with unknown props', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('div').at(0).prop('data-x')).toBe('x'); - expect(wrapper.find('div').at(0).prop('data-y')).toBe('y'); - expect(wrapper.find('div').at(0).prop('data-z')).toBe('z'); -}); - -test(' - renders correct error text (specified)', () => { - const error = new Error(); - const element = ( - - ); - const wrapper = mount( - element, - createContext({ x: { type: String, label: '' } }), - ); - - expect(wrapper.children().last().text()).toBe('Error'); -}); - -test(' - renders correct error text (showInlineError=false)', () => { - const error = new Error(); - const element = ( - - ); - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.children().last().text()).not.toBe('Error'); -}); - -test(' - renders a icon', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('i')).toHaveLength(1); -}); - -test(' - renders a icon', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('i')).toHaveLength(1); -}); - -test(' - renders with a custom wrapClassName', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('.ui.input.test-class-name')).toHaveLength(1); -}); - -test(' - renders a input with autocomplete turned off', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input').prop('autoComplete')).toBe('off'); -}); diff --git a/packages/uniforms-semantic/__tests__/index.ts b/packages/uniforms-semantic/__tests__/index.ts index 0713cec2f..0b1d6cd21 100644 --- a/packages/uniforms-semantic/__tests__/index.ts +++ b/packages/uniforms-semantic/__tests__/index.ts @@ -54,7 +54,11 @@ describe('@RTL', () => { suites.testQuickForm(theme.QuickForm); suites.testRadioField(theme.RadioField); suites.testSubmitField(theme.SubmitField); - suites.testTextField(theme.TextField); + suites.testTextField(theme.TextField, { + testWrapClassName: true, + testRenderIcon: true, + testShowInlineError: true, + }); suites.testValidatedForm(theme.ValidatedForm); suites.testValidatedQuickForm(theme.ValidatedQuickForm); }); diff --git a/packages/uniforms-unstyled/__tests__/TextField.tsx b/packages/uniforms-unstyled/__tests__/TextField.tsx deleted file mode 100644 index 16240266f..000000000 --- a/packages/uniforms-unstyled/__tests__/TextField.tsx +++ /dev/null @@ -1,171 +0,0 @@ -import React from 'react'; -import { TextField } from 'uniforms-unstyled'; - -import createContext from './_createContext'; -import mount from './_mount'; - -test(' - renders an input', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); -}); - -test(' - renders an input with correct disabled state', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('disabled')).toBe(true); -}); - -test(' - renders an input with correct readOnly state', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('readOnly')).toBe(true); -}); - -test(' - renders an input with correct id (inherited)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('id')).toBeTruthy(); -}); - -test(' - renders an input with correct id (specified)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('id')).toBe('y'); -}); - -test(' - renders an input with correct name', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('name')).toBe('x'); -}); - -test(' - renders an input with correct placeholder', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('placeholder')).toBe('y'); -}); - -test(' - renders an input with correct type', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('type')).toBe('text'); -}); - -test(' - renders an input with correct value (default)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('value')).toBe(''); -}); - -test(' - renders an input with correct value (model)', () => { - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { model: { x: 'y' } }), - ); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('value')).toBe('y'); -}); - -test(' - renders an input with correct value (specified)', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('value')).toBe('y'); -}); - -test(' - renders an input which correctly reacts on change', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { onChange }), - ); - - expect(wrapper.find('input')).toHaveLength(1); - expect( - wrapper.find('input').simulate('change', { target: { value: 'y' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', 'y'); -}); - -test(' - renders an input which correctly reacts on change (empty)', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { onChange }), - ); - - expect(wrapper.find('input')).toHaveLength(1); - expect( - wrapper.find('input').simulate('change', { target: { value: '' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', ''); -}); - -test(' - renders an input which correctly reacts on change (same value)', () => { - const onChange = jest.fn(); - - const element = ; - const wrapper = mount( - element, - createContext({ x: { type: String } }, { model: { x: 'y' }, onChange }), - ); - - expect(wrapper.find('input')).toHaveLength(1); - expect( - wrapper.find('input').simulate('change', { target: { value: 'y' } }), - ).toBeTruthy(); - expect(onChange).toHaveBeenLastCalledWith('x', 'y'); -}); - -test(' - renders a label', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('label')).toHaveLength(1); - expect(wrapper.find('label').text()).toBe('y'); - expect(wrapper.find('label').prop('htmlFor')).toBe( - wrapper.find('input').prop('id'), - ); -}); - -test(' - renders a wrapper with unknown props', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('div').at(0).prop('data-x')).toBe('x'); - expect(wrapper.find('div').at(0).prop('data-y')).toBe('y'); - expect(wrapper.find('div').at(0).prop('data-z')).toBe('z'); -}); - -test(' - renders an input with autocomplete turned off', () => { - const element = ; - const wrapper = mount(element, createContext({ x: { type: String } })); - - expect(wrapper.find('input')).toHaveLength(1); - expect(wrapper.find('input').prop('autoComplete')).toBe('off'); -}); diff --git a/packages/uniforms-unstyled/__tests__/index.ts b/packages/uniforms-unstyled/__tests__/index.ts index 7df73ce41..323a5f617 100644 --- a/packages/uniforms-unstyled/__tests__/index.ts +++ b/packages/uniforms-unstyled/__tests__/index.ts @@ -59,7 +59,7 @@ describe('@RTL', () => { suites.testQuickForm(theme.QuickForm); suites.testRadioField(theme.RadioField); suites.testSubmitField(theme.SubmitField); - suites.testTextField(theme.TextField); + suites.testTextField(theme.TextField, { testShowInlineError: false }); suites.testValidatedForm(theme.ValidatedForm); suites.testValidatedQuickForm(theme.ValidatedQuickForm); }); diff --git a/packages/uniforms/__suites__/LongTextField.tsx b/packages/uniforms/__suites__/LongTextField.tsx index 21cad4259..fced6b2e8 100644 --- a/packages/uniforms/__suites__/LongTextField.tsx +++ b/packages/uniforms/__suites__/LongTextField.tsx @@ -1,6 +1,6 @@ import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import React, { ComponentType } from 'react'; +import React, { ComponentType, PropsWithChildren } from 'react'; import z from 'zod'; import { renderWithZod } from './render-zod'; @@ -10,6 +10,11 @@ export function testLongTextField( options?: { skipShowInlineErrorTests?: boolean; testMinMaxLength?: boolean; + testPassThemeProps?: { + ThemeProvider: ( + props: PropsWithChildren<{ themeOptions: any }>, + ) => JSX.Element; + }; }, ) { test(' - renders a textarea with correct disabled state', () => { @@ -135,6 +140,73 @@ export function testLongTextField( }); } + if (options?.testPassThemeProps) { + const { ThemeProvider } = options.testPassThemeProps; + + test(' - default props are not passed when MUI theme props are specified', () => { + const themeOptions = { + props: { MuiTextField: { fullWidth: false, margin: 'normal' } }, + }; + const { container } = renderWithZod({ + element: ( + + + + ), + schema: z.object({ x: z.string() }), + }); + + const elements = container.getElementsByClassName( + 'MuiFormControl-marginNormal', + ); + expect(elements).toHaveLength(1); + expect(elements[0]).not.toHaveClass('MuiFormControl-fullWidth'); + }); + + test(' - default props are passed when MUI theme props are absent', () => { + const themeOptions = {}; + const { container } = renderWithZod({ + element: ( + + + + ), + schema: z.object({ x: z.string() }), + }); + + const elements = container.getElementsByClassName( + 'MuiFormControl-marginDense', + ); + expect(elements).toHaveLength(1); + expect(elements[0]).toHaveClass('MuiFormControl-fullWidth'); + }); + + test(' - explicit props are passed when MUI theme props are specified', () => { + const themeOptions = { + props: { MuiTextField: { fullWidth: true, margin: 'dense' } }, + }; + const explicitProps = { + fullWidth: false, + margin: 'normal' as const, + }; + + const { container } = renderWithZod({ + element: ( + + + + ), + schema: z.object({ x: z.string() }), + }); + + const elements = container.getElementsByClassName( + 'MuiFormControl-marginNormal', + ); + expect(elements).toHaveLength(1); + expect(elements[0]).not.toHaveClass('MuiFormControl-fullWidth'); + }); + } + if (options?.testMinMaxLength) { test(' - renders a textarea with minLength and maxLength', () => { renderWithZod({ diff --git a/packages/uniforms/__suites__/TextField.tsx b/packages/uniforms/__suites__/TextField.tsx index 718bd8d06..9040865f4 100644 --- a/packages/uniforms/__suites__/TextField.tsx +++ b/packages/uniforms/__suites__/TextField.tsx @@ -1,11 +1,36 @@ import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import React, { ComponentType } from 'react'; +import React, { ComponentType, PropsWithChildren } from 'react'; import z from 'zod'; import { renderWithZod } from './render-zod'; -export function testTextField(TextField: ComponentType) { +type TestTextFieldOptions = { + testShowInlineError?: boolean; + testPassThemeProps?: { + ThemeProvider: ( + props: PropsWithChildren<{ themeOptions: any }>, + ) => JSX.Element; + }; + testWrapClassName?: boolean; + testRenderIcon?: boolean; + testMinMaxLength?: boolean; +}; + +export function testTextField( + TextField: ComponentType, + options: TestTextFieldOptions = { + testShowInlineError: true, + }, +) { + test(' - renders an input', () => { + renderWithZod({ + element: , + schema: z.object({ x: z.string() }), + }); + expect(screen.getByRole('textbox')).toBeTruthy(); + }); + test(' - renders an input with correct disabled state', () => { renderWithZod({ element: , @@ -133,4 +158,184 @@ export function testTextField(TextField: ComponentType) { }); expect(screen.getByLabelText(/^Y/)).toBeInTheDocument(); }); + + test(' - renders a wrapper with unknown props', () => { + const props = { + 'data-x': 'x', + 'data-y': 'y', + 'data-z': 'z', + }; + renderWithZod({ + element: , + schema: z.object({ x: z.string() }), + }); + + const querySelectorParams = Object.entries(props) + .map(([key, value]) => `[${key}="${value}"]`) + .join(''); + const wrapper = screen.getByRole('textbox').closest(querySelectorParams); + expect(wrapper).toBeTruthy(); + }); + + test(' - renders a input with correct type prop (password)', () => { + renderWithZod({ + element: , + schema: z.object({ x: z.string() }), + }); + const wrapper = screen.getByLabelText(/^X( \*)?$/); + expect(wrapper).toHaveAttribute('type', 'password'); + }); + + if (options.testShowInlineError) { + test(' - renders a TextField with correct error text (specified)', () => { + const errorMessage = 'Error'; + renderWithZod({ + element: ( + + ), + schema: z.object({ x: z.string() }), + }); + + expect(screen.getByText(errorMessage)).toBeInTheDocument(); + }); + + test(' - renders a TextField with correct error text (showInlineError=false)', () => { + const errorMessage = 'Error'; + renderWithZod({ + element: ( + + ), + schema: z.object({ x: z.string() }), + }); + + expect(screen.queryByText(errorMessage)).not.toBeInTheDocument(); + }); + } + + if (options.testPassThemeProps) { + const { ThemeProvider } = options.testPassThemeProps; + + test(' - default props are not passed when MUI theme props are specified', () => { + const themeOptions = { + props: { MuiTextField: { fullWidth: false, margin: 'normal' } }, + }; + const { container } = renderWithZod({ + element: ( + + + + ), + schema: z.object({ x: z.string() }), + }); + + const elements = container.getElementsByClassName( + 'MuiFormControl-marginNormal', + ); + expect(elements).toHaveLength(1); + expect(elements[0]).not.toHaveClass('MuiFormControl-fullWidth'); + }); + + test(' - default props are passed when MUI theme props are absent', () => { + const themeOptions = {}; + const { container } = renderWithZod({ + element: ( + + + + ), + schema: z.object({ x: z.string() }), + }); + + const elements = container.getElementsByClassName( + 'MuiFormControl-marginDense', + ); + expect(elements).toHaveLength(1); + expect(elements[0]).toHaveClass('MuiFormControl-fullWidth'); + }); + + test(' - explicit props are passed when MUI theme props are specified', () => { + const themeOptions = { + props: { MuiTextField: { fullWidth: true, margin: 'dense' } }, + }; + const explicitProps = { + fullWidth: false, + margin: 'normal' as const, + }; + + const { container } = renderWithZod({ + element: ( + + + + ), + schema: z.object({ x: z.string() }), + }); + + const elements = container.getElementsByClassName( + 'MuiFormControl-marginNormal', + ); + expect(elements).toHaveLength(1); + expect(elements[0]).not.toHaveClass('MuiFormControl-fullWidth'); + }); + } + + if (options.testRenderIcon) { + test(' - renders an icon', () => { + const { container } = renderWithZod({ + element: , + schema: z.object({ x: z.string() }), + }); + + expect(container.querySelector('i')).toBeInTheDocument(); + }); + test(' - renders an iconLeft', () => { + const { container } = renderWithZod({ + element: , + schema: z.object({ x: z.string() }), + }); + + expect(container.querySelector('i')).toBeInTheDocument(); + }); + } + + if (options.testWrapClassName) { + test(' - renders with a custom wrapClassName', () => { + const testClassName = 'test-class-name'; + renderWithZod({ + element: , + schema: z.object({ x: z.string() }), + }); + + expect(screen.getByRole('textbox').closest('div')).toHaveClass( + testClassName, + ); + }); + } + + if (options.testMinMaxLength) { + test(' - renders a input with minLength and maxLength', () => { + renderWithZod({ + element: , + schema: z.object({ x: z.string() }), + }); + + const inputElement = screen.getByRole('textbox'); + const wrapperElement = inputElement.parentNode; + + expect(inputElement).toHaveAttribute('minLength', '1'); + expect(inputElement).toHaveAttribute('maxLength', '10'); + expect(wrapperElement).not.toHaveAttribute('minLength'); + expect(wrapperElement).not.toHaveAttribute('maxLength'); + }); + } }