diff --git a/package-lock.json b/package-lock.json
index 5e9e1f2a3e..f11b3911d7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -53983,11 +53983,15 @@
"prop-types": "^15.8.1"
},
"devDependencies": {
+ "@instructure/ui-axe-check": "8.46.0",
"@instructure/ui-babel-preset": "8.46.0",
"@instructure/ui-color-utils": "8.46.0",
"@instructure/ui-test-locator": "8.46.0",
"@instructure/ui-test-utils": "8.46.0",
- "@instructure/ui-themes": "8.46.0"
+ "@instructure/ui-themes": "8.46.0",
+ "@testing-library/jest-dom": "^5.17.0",
+ "@testing-library/react": "^14.0.0",
+ "@testing-library/user-event": "^14.4.3"
},
"peerDependencies": {
"react": ">=16.8 <=18"
@@ -59682,6 +59686,7 @@
"@instructure/console": "8.46.0",
"@instructure/emotion": "8.46.0",
"@instructure/shared-types": "8.46.0",
+ "@instructure/ui-axe-check": "8.46.0",
"@instructure/ui-babel-preset": "8.46.0",
"@instructure/ui-color-utils": "8.46.0",
"@instructure/ui-dom-utils": "8.46.0",
@@ -59697,6 +59702,9 @@
"@instructure/ui-utils": "8.46.0",
"@instructure/ui-view": "8.46.0",
"@instructure/uid": "8.46.0",
+ "@testing-library/jest-dom": "^5.17.0",
+ "@testing-library/react": "^14.0.0",
+ "@testing-library/user-event": "^14.4.3",
"keycode": "^2.2.1",
"prop-types": "^15.8.1"
}
diff --git a/packages/ui-checkbox/package.json b/packages/ui-checkbox/package.json
index d9d368f8b9..6dee6035ad 100644
--- a/packages/ui-checkbox/package.json
+++ b/packages/ui-checkbox/package.json
@@ -45,7 +45,11 @@
"@instructure/ui-color-utils": "8.46.0",
"@instructure/ui-test-locator": "8.46.0",
"@instructure/ui-test-utils": "8.46.0",
- "@instructure/ui-themes": "8.46.0"
+ "@instructure/ui-themes": "8.46.0",
+ "@instructure/ui-axe-check": "8.46.0",
+ "@testing-library/jest-dom": "^5.17.0",
+ "@testing-library/react": "^14.0.0",
+ "@testing-library/user-event": "^14.4.3"
},
"peerDependencies": {
"react": ">=16.8 <=18"
diff --git a/packages/ui-checkbox/src/Checkbox/CheckboxFacade/__tests__/CheckboxFacade.test.tsx b/packages/ui-checkbox/src/Checkbox/CheckboxFacade/__new-tests__/CheckboxFacade.test.tsx
similarity index 69%
rename from packages/ui-checkbox/src/Checkbox/CheckboxFacade/__tests__/CheckboxFacade.test.tsx
rename to packages/ui-checkbox/src/Checkbox/CheckboxFacade/__new-tests__/CheckboxFacade.test.tsx
index f99678fae9..5515afc147 100644
--- a/packages/ui-checkbox/src/Checkbox/CheckboxFacade/__tests__/CheckboxFacade.test.tsx
+++ b/packages/ui-checkbox/src/Checkbox/CheckboxFacade/__new-tests__/CheckboxFacade.test.tsx
@@ -23,19 +23,26 @@
*/
import React from 'react'
-import { expect, mount, within } from '@instructure/ui-test-utils'
+import { render, screen } from '@testing-library/react'
+import '@testing-library/jest-dom/extend-expect'
+import { runAxeCheck } from '@instructure/ui-axe-check'
import { CheckboxFacade } from '../index'
-describe('', async () => {
- it('should render', async () => {
- const subject = await mount(label text)
- const checkboxFacade = within(subject.getDOMNode())
- expect(checkboxFacade).to.exist()
+const TEST_TEXT = 'test-text'
+
+describe('', () => {
+ it('should render', () => {
+ render({TEST_TEXT})
+ const facade = screen.getByText(TEST_TEXT)
+
+ expect(facade).toBeInTheDocument()
})
+
it('should meet a11y standards', async () => {
- const subject = await mount(label text)
- const checkboxFacade = within(subject.getDOMNode())
- expect(await checkboxFacade.accessible()).to.be.true()
+ const { container } = render({TEST_TEXT})
+ const axeCheck = await runAxeCheck(container)
+
+ expect(axeCheck).toBe(true)
})
})
diff --git a/packages/ui-checkbox/src/Checkbox/CheckboxLocator.ts b/packages/ui-checkbox/src/Checkbox/CheckboxLocator.ts
deleted file mode 100644
index 6ee80a1cbf..0000000000
--- a/packages/ui-checkbox/src/Checkbox/CheckboxLocator.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 - present Instructure, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-import { locator } from '@instructure/ui-test-locator'
-
-import { Checkbox } from './index'
-
-// @ts-expect-error ts-migrate(2339) FIXME: Property 'selector' does not exist on type 'typeof... Remove this comment to see the full error message
-export const CheckboxLocator = locator(Checkbox.selector)
diff --git a/packages/ui-checkbox/src/Checkbox/ToggleFacade/__tests__/ToggleFacade.test.tsx b/packages/ui-checkbox/src/Checkbox/ToggleFacade/__new-tests__/ToggleFacade.test.tsx
similarity index 69%
rename from packages/ui-checkbox/src/Checkbox/ToggleFacade/__tests__/ToggleFacade.test.tsx
rename to packages/ui-checkbox/src/Checkbox/ToggleFacade/__new-tests__/ToggleFacade.test.tsx
index d12f80ad3d..3de5ca16eb 100644
--- a/packages/ui-checkbox/src/Checkbox/ToggleFacade/__tests__/ToggleFacade.test.tsx
+++ b/packages/ui-checkbox/src/Checkbox/ToggleFacade/__new-tests__/ToggleFacade.test.tsx
@@ -23,20 +23,26 @@
*/
import React from 'react'
-import { expect, mount, within } from '@instructure/ui-test-utils'
+import { render, screen } from '@testing-library/react'
+import '@testing-library/jest-dom/extend-expect'
+import { runAxeCheck } from '@instructure/ui-axe-check'
import { ToggleFacade } from '../index'
-describe('', async () => {
- it('should render', async () => {
- const subject = await mount(label text)
- const toggleFacade = within(subject.getDOMNode())
- expect(toggleFacade).to.exist()
+const TEST_TEXT = 'test-text'
+
+describe('', () => {
+ it('should render', () => {
+ render({TEST_TEXT})
+ const facade = screen.getByText(TEST_TEXT)
+
+ expect(facade).toBeInTheDocument()
})
it('should meet a11y standards', async () => {
- const subject = await mount(label text)
- const toggleFacade = within(subject.getDOMNode())
- expect(await toggleFacade.accessible()).to.be.true()
+ const { container } = render({TEST_TEXT})
+ const axeCheck = await runAxeCheck(container)
+
+ expect(axeCheck).toBe(true)
})
})
diff --git a/packages/ui-checkbox/src/Checkbox/__new-tests__/Checkbox.test.tsx b/packages/ui-checkbox/src/Checkbox/__new-tests__/Checkbox.test.tsx
new file mode 100644
index 0000000000..d83027f658
--- /dev/null
+++ b/packages/ui-checkbox/src/Checkbox/__new-tests__/Checkbox.test.tsx
@@ -0,0 +1,221 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 - present Instructure, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+import React from 'react'
+import { fireEvent, render, screen, waitFor } from '@testing-library/react'
+import userEvent from '@testing-library/user-event'
+import '@testing-library/jest-dom/extend-expect'
+
+import { runAxeCheck } from '@instructure/ui-axe-check'
+import { Checkbox } from '../index'
+import { CheckboxProps } from '../props'
+
+const TEST_VALUE = 'test-value'
+const TEST_NAME = 'test-name'
+const TEST_LABEL = 'test-label'
+
+const initProps = {
+ label: TEST_LABEL,
+ defaultChecked: true,
+ value: TEST_VALUE,
+ name: TEST_NAME
+}
+
+const renderCheckbox = (props?: Partial) => {
+ const allProps: CheckboxProps = {
+ ...initProps,
+ ...props
+ }
+ return render()
+}
+
+describe('', () => {
+ it('renders an input with type "checkbox"', () => {
+ renderCheckbox()
+ const inputElem = screen.getByRole('checkbox')
+
+ expect(inputElem).toBeInTheDocument()
+ expect(inputElem.tagName).toBe('INPUT')
+ expect(inputElem).toHaveAttribute('type', 'checkbox')
+ })
+
+ it('`simple` variant only displays a checkmark when checked', async () => {
+ const { container } = renderCheckbox({
+ variant: 'simple',
+ defaultChecked: false
+ })
+ const checkboxElement = container.querySelector('input[type="checkbox"]')
+ const svgElement = container.querySelector('svg')
+
+ expect(svgElement).not.toBeInTheDocument()
+
+ userEvent.click(checkboxElement!)
+ await waitFor(() => {
+ const svgElementAfterClick = container.querySelector('svg')
+ expect(svgElementAfterClick).toBeInTheDocument()
+ })
+ })
+
+ it('`simple` variant supports indeterminate/mixed state', () => {
+ renderCheckbox({ variant: 'simple', indeterminate: true })
+
+ const inputElem = screen.getByRole('checkbox')
+
+ expect(inputElem).toBeInTheDocument()
+ expect(inputElem).toHaveAttribute('aria-checked', 'mixed')
+ })
+
+ describe('events', () => {
+ it('when clicked, fires onClick and onChange events', async () => {
+ const onClick = jest.fn()
+ const onChange = jest.fn()
+ renderCheckbox({ onClick, onChange })
+ const checkboxElement = screen.getByRole('checkbox')
+
+ userEvent.click(checkboxElement)
+
+ await waitFor(() => {
+ expect(onClick).toHaveBeenCalled()
+ expect(onChange).toHaveBeenCalled()
+ })
+ })
+
+ it('when clicked, does not call onClick or onChange when disabled', async () => {
+ const onClick = jest.fn()
+ const onChange = jest.fn()
+ renderCheckbox({ onClick, onChange, disabled: true })
+ const checkboxElement = screen.getByRole('checkbox')
+
+ fireEvent.click(checkboxElement)
+
+ await waitFor(() => {
+ expect(onClick).not.toHaveBeenCalled()
+ expect(onChange).not.toHaveBeenCalled()
+ expect(checkboxElement).toBeDisabled()
+ })
+ })
+
+ it('when clicked, does not call onClick or onChange when readOnly', async () => {
+ const onClick = jest.fn()
+ const onChange = jest.fn()
+ renderCheckbox({ onClick, onChange, readOnly: true })
+ const checkboxElement = screen.getByRole('checkbox')
+
+ fireEvent.click(checkboxElement)
+
+ await waitFor(() => {
+ expect(onClick).not.toHaveBeenCalled()
+ expect(onChange).not.toHaveBeenCalled()
+ })
+ })
+
+ it('calls onChange when enter key is pressed', async () => {
+ const onChange = jest.fn()
+ renderCheckbox({ onChange })
+ const checkboxElement = screen.getByRole('checkbox')
+
+ userEvent.type(checkboxElement, '{enter}')
+
+ await waitFor(() => {
+ expect(onChange).toHaveBeenCalled()
+ })
+ })
+
+ it('responds to onBlur event', async () => {
+ const onBlur = jest.fn()
+ renderCheckbox({ onBlur })
+
+ userEvent.tab()
+ userEvent.tab()
+
+ await waitFor(() => {
+ expect(onBlur).toHaveBeenCalled()
+ })
+ })
+
+ it('responds to onFocus event', async () => {
+ const onFocus = jest.fn()
+ renderCheckbox({ onFocus })
+
+ userEvent.tab()
+
+ await waitFor(() => {
+ expect(onFocus).toHaveBeenCalled()
+ })
+ })
+
+ it('focuses with the focus helper', () => {
+ const checkboxRef = React.createRef()
+ render()
+ const checkboxElement = screen.getByRole('checkbox')
+
+ expect(checkboxElement).not.toHaveFocus()
+
+ checkboxRef.current?.focus()
+
+ expect(checkboxElement).toHaveFocus()
+ })
+
+ it('calls onMouseOver', async () => {
+ const onMouseOver = jest.fn()
+ renderCheckbox({ onMouseOver })
+ const checkboxElement = screen.getByRole('checkbox')
+
+ userEvent.hover(checkboxElement)
+
+ await waitFor(() => {
+ expect(onMouseOver).toHaveBeenCalled()
+ })
+ })
+
+ it('calls onMouseOut', async () => {
+ const onMouseOut = jest.fn()
+ renderCheckbox({ onMouseOut })
+ const checkboxElement = screen.getByRole('checkbox')
+
+ userEvent.hover(checkboxElement)
+ userEvent.unhover(checkboxElement)
+
+ await waitFor(() => {
+ expect(onMouseOut).toHaveBeenCalled()
+ })
+ })
+ })
+
+ describe('for a11y', () => {
+ it('`simple` variant should meet standards', async () => {
+ const { container } = renderCheckbox({ variant: 'simple' })
+ const axeCheck = await runAxeCheck(container)
+
+ expect(axeCheck).toBe(true)
+ })
+
+ it('`toggle` variant should meet standards', async () => {
+ const { container } = renderCheckbox({ variant: 'toggle' })
+ const axeCheck = await runAxeCheck(container)
+
+ expect(axeCheck).toBe(true)
+ })
+ })
+})
diff --git a/packages/ui-checkbox/src/Checkbox/__tests__/Checkbox.test.tsx b/packages/ui-checkbox/src/Checkbox/__tests__/Checkbox.test.tsx
deleted file mode 100644
index e482fa2ba6..0000000000
--- a/packages/ui-checkbox/src/Checkbox/__tests__/Checkbox.test.tsx
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 - present Instructure, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-import React from 'react'
-import { expect, mount, stub, wait } from '@instructure/ui-test-utils'
-
-import { Checkbox } from '../index'
-import { CheckboxLocator } from '../CheckboxLocator'
-
-describe('', async () => {
- it('renders an input with type "checkbox"', async () => {
- await mount(
-
- )
-
- const checkbox = await CheckboxLocator.find()
- const input = await checkbox.find('input')
-
- expect((input.getDOMNode() as HTMLInputElement).type).to.equal('checkbox')
- })
-
- it('`simple` variant only displays a checkmark when checked', async () => {
- await mount(
-
- )
-
- const checkbox = await CheckboxLocator.find()
-
- expect(await checkbox.find('svg', { expectEmpty: true })).to.not.exist()
- })
-
- it('`simple` variant supports indeterminate/mixed state', async () => {
- await mount(
-
- )
-
- const checkbox = await CheckboxLocator.find()
- const input = await checkbox.find('input')
-
- expect(input).to.have.attribute('aria-checked', 'mixed')
- })
-
- describe('events', async () => {
- it('when clicked, fires onClick and onChange events', async () => {
- const onClick = stub()
- const onChange = stub()
-
- await mount(
-
- )
-
- const checkbox = await CheckboxLocator.find()
- const input = await checkbox.find('input')
-
- await input.click()
-
- await wait(() => {
- expect(onClick).to.have.been.called()
- expect(onChange).to.have.been.called()
- })
- })
-
- it('when clicked, does not call onClick or onChange when disabled', async () => {
- const onClick = stub()
- const onChange = stub()
-
- await mount(
-
- )
-
- const checkbox = await CheckboxLocator.find()
- const input = await checkbox.find('input')
- await input.click(undefined, { clickable: false })
-
- expect(onClick).to.not.have.been.called()
- expect(onChange).to.not.have.been.called()
- })
-
- it('when clicked, does not call onClick or onChange when readOnly', async () => {
- const onClick = stub()
- const onChange = stub()
-
- await mount(
-
- )
-
- const checkbox = await CheckboxLocator.find()
- const input = await checkbox.find('input')
-
- await input.click()
-
- await wait(() => {
- expect(onClick).to.not.have.been.called()
- expect(onChange).to.not.have.been.called()
- })
- })
-
- it('calls onChange when enter key is pressed', async () => {
- const onChange = stub()
-
- await mount(
-
- )
-
- const checkbox = await CheckboxLocator.find()
- const input = await checkbox.find('input')
-
- await input.keyDown('enter')
-
- await wait(() => {
- expect(onChange).to.have.been.called()
- })
- })
-
- it('responds to onBlur event', async () => {
- const onBlur = stub()
-
- await mount(
-
- )
-
- const checkbox = await CheckboxLocator.find()
- const input = await checkbox.find('input')
-
- await input.focusOut()
-
- await wait(() => {
- expect(onBlur).to.have.been.called()
- })
- })
-
- it('responds to onFocus event', async () => {
- const onFocus = stub()
-
- await mount(
-
- )
-
- const checkbox = await CheckboxLocator.find()
- const input = await checkbox.find('input')
-
- await input.focus()
-
- await wait(() => {
- expect(onFocus).to.have.been.called()
- })
- })
-
- it('focuses with the focus helper', async () => {
- let checkboxRef: Checkbox | undefined
-
- await mount(
- {
- checkboxRef = el
- }}
- />
- )
-
- expect(checkboxRef?.focused).to.be.false()
-
- checkboxRef?.focus()
-
- expect(checkboxRef?.focused).to.be.true()
-
- const checkbox = await CheckboxLocator.find()
- const input = await checkbox.find('input')
-
- await wait(() => {
- expect(input).to.have.focus()
- })
- })
-
- it('calls onMouseOver', async () => {
- const onMouseOver = stub()
-
- /* eslint-disable jsx-a11y/mouse-events-have-key-events */
-
- await mount(
-
- )
- /* eslint-enable jsx-a11y/mouse-events-have-key-events */
-
- const checkbox = await CheckboxLocator.find()
-
- await checkbox.mouseOver()
-
- await wait(() => {
- expect(onMouseOver).to.have.been.called()
- })
- })
-
- it('calls onMouseOut', async () => {
- const onMouseOut = stub()
-
- /* eslint-disable jsx-a11y/mouse-events-have-key-events */
-
- await mount(
-
- )
- /* eslint-enable jsx-a11y/mouse-events-have-key-events */
-
- const checkbox = await CheckboxLocator.find()
-
- await checkbox.mouseOut()
-
- await wait(() => {
- expect(onMouseOut).to.have.been.called()
- })
- })
- })
-
- describe('for a11y', () => {
- it('`simple` variant should meet standards', async () => {
- await mount(
-
- )
-
- const checkbox = await CheckboxLocator.find()
-
- expect(await checkbox.accessible()).to.be.true()
- })
-
- it('`toggle` variant should meet standards', async () => {
- await mount(
-
- )
-
- const checkbox = await CheckboxLocator.find()
-
- expect(await checkbox.accessible()).to.be.true()
- })
- })
-})
diff --git a/packages/ui-checkbox/src/Checkbox/locator.ts b/packages/ui-checkbox/src/Checkbox/locator.ts
deleted file mode 100644
index ed5c2888db..0000000000
--- a/packages/ui-checkbox/src/Checkbox/locator.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 - present Instructure, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-import { CheckboxLocator } from './CheckboxLocator'
-
-export { CheckboxLocator }
-export default CheckboxLocator
diff --git a/packages/ui-checkbox/src/CheckboxGroup/CheckboxGroupLocator.ts b/packages/ui-checkbox/src/CheckboxGroup/CheckboxGroupLocator.ts
deleted file mode 100644
index 76de9685f8..0000000000
--- a/packages/ui-checkbox/src/CheckboxGroup/CheckboxGroupLocator.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 - present Instructure, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-import { locator } from '@instructure/ui-test-locator'
-
-import { CheckboxGroup } from './index'
-
-// @ts-expect-error ts-migrate(2339) FIXME: Property 'selector' does not exist on type 'typeof... Remove this comment to see the full error message
-export const CheckboxGroupLocator = locator(CheckboxGroup.selector)
diff --git a/packages/ui-checkbox/src/CheckboxGroup/__new-tests__/CheckboxGroup.test.tsx b/packages/ui-checkbox/src/CheckboxGroup/__new-tests__/CheckboxGroup.test.tsx
new file mode 100644
index 0000000000..1f8b869abe
--- /dev/null
+++ b/packages/ui-checkbox/src/CheckboxGroup/__new-tests__/CheckboxGroup.test.tsx
@@ -0,0 +1,202 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 - present Instructure, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+import React from 'react'
+import { fireEvent, render, screen, waitFor } from '@testing-library/react'
+import userEvent from '@testing-library/user-event'
+import '@testing-library/jest-dom/extend-expect'
+
+import { runAxeCheck } from '@instructure/ui-axe-check'
+import { CheckboxGroup } from '../index'
+import { CheckboxGroupProps } from '../props'
+import { Checkbox } from '../../Checkbox'
+
+const TEST_NAME = 'test-name'
+const TEST_DESCRIPTION = 'test-description'
+const TEST_ERROR_MESSAGE = 'test-error-message'
+const TEST_VALUE_1 = 'test-value-1'
+const TEST_VALUE_2 = 'test-value-2'
+const TEST_LABEL_1 = 'test-label-1'
+const TEST_LABEL_2 = 'test-label-2'
+
+const renderCheckboxGroup = (props?: Partial) => {
+ const allProps: CheckboxGroupProps = {
+ name: TEST_NAME,
+ description: TEST_DESCRIPTION,
+ ...props
+ }
+
+ return render(
+
+
+
+
+ )
+}
+
+describe('', () => {
+ it('adds the name props to all Checkbox types', () => {
+ renderCheckboxGroup({ name: TEST_NAME })
+ const checkboxes = screen.getAllByRole('checkbox')
+
+ expect(checkboxes.length).toBe(2)
+ expect(checkboxes[0]).toHaveAttribute('name', TEST_NAME)
+ expect(checkboxes[1]).toHaveAttribute('name', TEST_NAME)
+ })
+
+ it('links the messages to the fieldset via aria-describedby', () => {
+ const { container } = renderCheckboxGroup({
+ messages: [{ text: TEST_ERROR_MESSAGE, type: 'error' }]
+ })
+ const fieldset = screen.getByRole('group')
+ const ariaDesc = fieldset.getAttribute('aria-describedby')
+ const messageById = container.querySelector(`[id="${ariaDesc}"]`)
+
+ expect(messageById).toBeInTheDocument()
+ expect(messageById).toHaveTextContent(TEST_ERROR_MESSAGE)
+ })
+
+ it('displays description message inside the legend', () => {
+ const { container } = renderCheckboxGroup({ description: TEST_DESCRIPTION })
+ const legend = container.querySelector('legend')
+
+ expect(legend).toBeInTheDocument()
+ expect(legend).toHaveTextContent(TEST_DESCRIPTION)
+ })
+
+ it('does not call the onChange prop when disabled', async () => {
+ const onChange = jest.fn()
+ renderCheckboxGroup({ onChange, disabled: true })
+ const checkboxElement = screen.getAllByRole('checkbox')[0]
+
+ fireEvent.click(checkboxElement)
+
+ await waitFor(() => {
+ expect(onChange).not.toHaveBeenCalled()
+ expect(checkboxElement).toBeDisabled()
+ })
+ })
+
+ it('does not call the onChange prop when readOnly', async () => {
+ const onChange = jest.fn()
+ renderCheckboxGroup({ onChange, readOnly: true })
+ const checkboxElement = screen.getAllByRole('checkbox')[0]
+
+ fireEvent.click(checkboxElement)
+
+ await waitFor(() => {
+ expect(onChange).not.toHaveBeenCalled()
+ expect(checkboxElement).toBeDisabled()
+ })
+ })
+
+ it('should not update the value when the value prop is set', async () => {
+ const onChange = jest.fn()
+ renderCheckboxGroup({ onChange, value: ['tester'] })
+ const checkboxes = screen.getAllByRole('checkbox')
+
+ expect(checkboxes[0]).not.toBeChecked()
+ expect(checkboxes[1]).not.toBeChecked()
+
+ userEvent.click(checkboxes[0])
+
+ await waitFor(() => {
+ expect(onChange).not.toHaveBeenCalled()
+ expect(checkboxes[0]).not.toBeChecked()
+ expect(checkboxes[1]).not.toBeChecked()
+ })
+ })
+
+ it('should add the checkbox value to the value list when it is checked', async () => {
+ const onChange = jest.fn()
+ renderCheckboxGroup({ onChange })
+ const checkboxes = screen.getAllByRole('checkbox')
+
+ expect(checkboxes[0]).not.toBeChecked()
+ expect(checkboxes[1]).not.toBeChecked()
+
+ userEvent.click(checkboxes[0])
+ userEvent.click(checkboxes[1])
+
+ await waitFor(() => {
+ expect(checkboxes[0]).toBeChecked()
+ expect(checkboxes[1]).toBeChecked()
+ expect(onChange).toHaveBeenCalledWith([TEST_VALUE_1, TEST_VALUE_2])
+ })
+ })
+
+ it('should check the checkboxes based on the defaultValue prop', () => {
+ const defaultValue = [TEST_VALUE_2]
+ renderCheckboxGroup({ defaultValue })
+ const checkboxes = screen.getAllByRole('checkbox')
+
+ expect(checkboxes[0]).not.toBeChecked()
+ expect(checkboxes[1]).toBeChecked()
+ })
+
+ it('should remove the checkbox value from the value list when it is unchecked', async () => {
+ const onChange = jest.fn()
+ const defaultValue = [TEST_VALUE_1, TEST_VALUE_2]
+ renderCheckboxGroup({ onChange, defaultValue })
+ const checkboxes = screen.getAllByRole('checkbox')
+
+ expect(checkboxes[0]).toBeChecked()
+ expect(checkboxes[1]).toBeChecked()
+
+ userEvent.click(checkboxes[0])
+
+ await waitFor(() => {
+ expect(checkboxes[0]).not.toBeChecked()
+ expect(checkboxes[1]).toBeChecked()
+ expect(onChange).toHaveBeenCalledWith([TEST_VALUE_2])
+ })
+ })
+
+ it('passes the array of selected values to onChange handler', async () => {
+ const onChange = jest.fn()
+ const defaultValue = [TEST_VALUE_2]
+ renderCheckboxGroup({ onChange, defaultValue })
+ const checkboxes = screen.getAllByRole('checkbox')
+
+ expect(checkboxes[0]).not.toBeChecked()
+ expect(checkboxes[1]).toBeChecked()
+
+ userEvent.click(checkboxes[0])
+
+ await waitFor(() => {
+ expect(checkboxes[0]).toBeChecked()
+ expect(checkboxes[1]).toBeChecked()
+ expect(onChange).toHaveBeenCalledWith([TEST_VALUE_2, TEST_VALUE_1])
+ })
+ })
+
+ describe('for a11y', () => {
+ it('should meet standards', async () => {
+ const { container } = renderCheckboxGroup()
+ const axeCheck = await runAxeCheck(container)
+
+ expect(axeCheck).toBe(true)
+ })
+ })
+})
diff --git a/packages/ui-checkbox/src/CheckboxGroup/__tests__/CheckboxGroup.test.tsx b/packages/ui-checkbox/src/CheckboxGroup/__tests__/CheckboxGroup.test.tsx
deleted file mode 100644
index c2effad5bf..0000000000
--- a/packages/ui-checkbox/src/CheckboxGroup/__tests__/CheckboxGroup.test.tsx
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 - present Instructure, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-import React from 'react'
-import { expect, mount, stub } from '@instructure/ui-test-utils'
-
-import { CheckboxGroupLocator } from '../CheckboxGroupLocator'
-
-import { CheckboxGroup } from '../index'
-import { Checkbox } from '../../Checkbox'
-
-describe('', async () => {
- it('adds the name props to all Checkbox types', async () => {
- await mount(
-
-
-
-
-
-
- )
-
- const checkboxGroup = await CheckboxGroupLocator.find()
- const checkboxes = await checkboxGroup.findAll('input[name="sports"]')
- expect(checkboxes.length).to.equal(4)
- })
-
- it('links the messages to the fieldset via aria-describedby', async () => {
- await mount(
-
-
-
-
-
-
- )
-
- const checkboxGroup = await CheckboxGroupLocator.find()
- const fieldset = await checkboxGroup.find('fieldset')
- const messagesId = fieldset.getAttribute('aria-describedby')
- const messages = await checkboxGroup.find(`#${messagesId}`)
-
- expect(messages.getTextContent()).to.equal('Invalid name')
- })
-
- it('displays description message inside the legend', async () => {
- const description = 'You should pick something'
-
- await mount(
-
-
-
-
-
-
- )
-
- const checkboxGroup = await CheckboxGroupLocator.find()
- const legend = await checkboxGroup.find('legend')
- expect(legend.getTextContent()).to.equal(description)
- })
-
- it('does not call the onChange prop when disabled', async () => {
- const onChange = stub()
-
- await mount(
-
-
-
-
-
-
- )
-
- const checkboxGroup = await CheckboxGroupLocator.find()
- const input = await checkboxGroup.find('input[value="football"]')
- await input.click(undefined, { clickable: false })
-
- expect(onChange).to.not.have.been.called()
- })
-
- it('does not call the onChange prop when readOnly', async () => {
- const onChange = stub()
-
- await mount(
-
-
-
-
-
-
- )
-
- const checkboxGroup = await CheckboxGroupLocator.find()
- const input = await checkboxGroup.find('input[value="football"]')
- await input.click()
-
- expect(onChange).to.not.have.been.called()
- })
-
- it('should not update the value when the value prop is set', async () => {
- await mount(
-
-
-
-
-
-
- )
-
- const checkboxGroup = await CheckboxGroupLocator.find()
- const inputs = await checkboxGroup.findAll('input')
- inputs.forEach((input) => {
- expect((input.getDOMNode() as HTMLInputElement).checked).to.be.false()
- })
-
- const input = await checkboxGroup.find('input[value="football"]')
- await input.click()
-
- inputs.forEach((input) => {
- expect((input.getDOMNode() as HTMLInputElement).checked).to.be.false()
- })
- })
-
- it('should add the checkbox value to the value list when it is checked', async () => {
- const onChange = stub()
- await mount(
-
-
-
-
-
-
- )
-
- const checkboxGroup = await CheckboxGroupLocator.find()
- const input = await checkboxGroup.find('input[value="football"]')
- await input.click()
-
- expect(onChange.lastCall.args[0]).to.deep.equal(['football'])
- })
-
- it('should check the checkboxes based on the defaultValue prop', async () => {
- const defaultValue = ['football', 'volleyball']
- await mount(
-
-
-
-
-
-
- )
-
- const checkboxGroup = await CheckboxGroupLocator.find()
- const inputs = await checkboxGroup.findAll('input')
-
- inputs.forEach((input) => {
- if (defaultValue.includes(input.getAttribute('value')!)) {
- expect((input.getDOMNode() as HTMLInputElement).checked).to.be.true()
- } else {
- expect((input.getDOMNode() as HTMLInputElement).checked).to.be.false()
- }
- })
- })
-
- it('should remove the checkbox value from the value list when it is unchecked', async () => {
- const onChange = stub()
-
- await mount(
-
-
-
-
-
-
- )
-
- const checkboxGroup = await CheckboxGroupLocator.find()
- const input = await checkboxGroup.find('input[value="football"]')
- await input.click()
-
- expect(onChange.lastCall.args[0]).to.deep.equal([
- 'basketball',
- 'volleyball'
- ])
- })
-
- it('passes the array of selected values to onChange handler', async () => {
- const onChange = stub()
-
- await mount(
-
-
-
-
-
-
- )
-
- const checkboxGroup = await CheckboxGroupLocator.find()
- const input1 = await checkboxGroup.find('input[value="football"]')
- const input2 = await checkboxGroup.find('input[value="other"]')
-
- await input1.click()
- expect(onChange.lastCall.args[0]).to.deep.equal([
- 'basketball',
- 'volleyball'
- ])
-
- await input2.click()
- expect(onChange.lastCall.args[0]).to.deep.equal([
- 'basketball',
- 'volleyball',
- 'other'
- ])
- })
-
- describe('for a11y', async () => {
- it('should meet standards', async () => {
- await mount(
-
-
-
-
-
-
- )
-
- const checkboxGroup = await CheckboxGroupLocator.find()
- expect(
- await checkboxGroup.accessible({
- ignores: [
- 'checkboxgroup'
- ] /* https://github.com/dequelabs/axe-core/issues/176 */
- })
- ).to.be.true()
- })
- })
-})
diff --git a/packages/ui-checkbox/src/CheckboxGroup/locator.ts b/packages/ui-checkbox/src/CheckboxGroup/locator.ts
deleted file mode 100644
index c01ac6a7af..0000000000
--- a/packages/ui-checkbox/src/CheckboxGroup/locator.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 - present Instructure, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-import { CheckboxGroupLocator } from './CheckboxGroupLocator'
-
-export { CheckboxGroupLocator }
-export default CheckboxGroupLocator
diff --git a/packages/ui-checkbox/tsconfig.build.json b/packages/ui-checkbox/tsconfig.build.json
index 29141a4155..e878844fb3 100644
--- a/packages/ui-checkbox/tsconfig.build.json
+++ b/packages/ui-checkbox/tsconfig.build.json
@@ -22,8 +22,8 @@
{ "path": "../uid/tsconfig.build.json" },
{ "path": "../ui-babel-preset/tsconfig.build.json" },
{ "path": "../ui-color-utils/tsconfig.build.json" },
- { "path": "../ui-test-locator/tsconfig.build.json" },
{ "path": "../ui-test-utils/tsconfig.build.json" },
- { "path": "../ui-themes/tsconfig.build.json" }
+ { "path": "../ui-themes/tsconfig.build.json" },
+ { "path": "../ui-axe-check/tsconfig.build.json" }
]
}