diff --git a/cypress/component/TextInput.cy.tsx b/cypress/component/TextInput.cy.tsx
new file mode 100644
index 0000000000..a08f5666a0
--- /dev/null
+++ b/cypress/component/TextInput.cy.tsx
@@ -0,0 +1,113 @@
+/*
+ * 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 { TextInput } from '../../packages/ui'
+
+import '../support/component'
+import 'cypress-real-events'
+
+describe('', () => {
+ const contentBeforeSVG = (
+
+ )
+
+ const contentAfterSVG = (
+
+ )
+ it('should prepend and append content', async () => {
+ cy.mount(
+ contentBeforeSVG}
+ />
+ )
+
+ cy.get('span[class$="__beforeElement"]')
+ .should('exist')
+ .and('have.text', 'Content before')
+
+ cy.get('[data-cy-root]').then(() => {
+ cy.mount(
+ contentBeforeSVG}
+ renderAfterInput={() => contentAfterSVG}
+ />
+ )
+ })
+
+ cy.get('svg title').eq(0).should('have.text', 'Content before')
+ cy.get('svg title').eq(1).should('have.text', 'Content after')
+
+ cy.get('svg').should('have.length', 2)
+ })
+
+ it('should have no padding on empty before/after content', async () => {
+ cy.mount(
+ }
+ renderAfterInput={}
+ />
+ )
+
+ cy.get('[class*="__beforeElement"]').should(
+ 'have.css',
+ 'padding-inline-start',
+ '0px'
+ )
+ cy.get('[class*="__afterElement"]').should(
+ 'have.css',
+ 'padding-inline-end',
+ '0px'
+ )
+
+ cy.get('[data-cy-root]').then(() => {
+ cy.mount(
+ contentBeforeSVG}
+ renderAfterInput={() => contentAfterSVG}
+ />
+ )
+ })
+
+ cy.get('[class*="__beforeElement"]').should(
+ 'have.css',
+ 'padding-inline-start',
+ '12px'
+ )
+ cy.get('[class*="__afterElement"]').should(
+ 'have.css',
+ 'padding-inline-end',
+ '12px'
+ )
+ })
+})
diff --git a/package-lock.json b/package-lock.json
index 95df75a98c..4c406a20aa 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -48371,17 +48371,73 @@
"prop-types": "^15.8.1"
},
"devDependencies": {
+ "@instructure/ui-axe-check": "10.0.0",
"@instructure/ui-babel-preset": "10.0.0",
"@instructure/ui-badge": "10.0.0",
"@instructure/ui-color-utils": "10.0.0",
"@instructure/ui-test-utils": "10.0.0",
"@instructure/ui-themes": "10.0.0",
- "react-dom": "^18.3.1"
+ "@testing-library/jest-dom": "^6.4.6",
+ "@testing-library/react": "^15.0.7",
+ "@testing-library/user-event": "^14.5.2",
+ "vitest": "^2.0.2"
},
"peerDependencies": {
"react": ">=16.8 <=18"
}
},
+ "packages/ui-text-input/node_modules/@testing-library/dom": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz",
+ "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/runtime": "^7.12.5",
+ "@types/aria-query": "^5.0.1",
+ "aria-query": "5.3.0",
+ "chalk": "^4.1.0",
+ "dom-accessibility-api": "^0.5.9",
+ "lz-string": "^1.5.0",
+ "pretty-format": "^27.0.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "packages/ui-text-input/node_modules/@testing-library/react": {
+ "version": "15.0.7",
+ "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-15.0.7.tgz",
+ "integrity": "sha512-cg0RvEdD1TIhhkm1IeYMQxrzy0MtUNfa3minv4MjbgcYzJAZ7yD0i0lwoPOTPr+INtiXFezt2o8xMSnyHhEn2Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "@testing-library/dom": "^10.0.0",
+ "@types/react-dom": "^18.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/react": "^18.0.0",
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "packages/ui-text-input/node_modules/aria-query": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
+ "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
+ "dev": true,
+ "dependencies": {
+ "dequal": "^2.0.3"
+ }
+ },
"packages/ui-text/node_modules/@testing-library/dom": {
"version": "10.3.0",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.3.0.tgz",
diff --git a/packages/instui-config/package-lists/v11/package-list.json b/packages/instui-config/package-lists/v11/package-list.json
new file mode 100644
index 0000000000..e0ded4e388
--- /dev/null
+++ b/packages/instui-config/package-lists/v11/package-list.json
@@ -0,0 +1,107 @@
+[
+ "@instructure/babel-plugin-transform-imports",
+ "@instructure/browserslist-config-instui",
+ "@instructure/canvas-high-contrast-theme",
+ "@instructure/canvas-theme",
+ "@instructure/command-utils",
+ "@instructure/console",
+ "@instructure/cz-lerna-changelog",
+ "@instructure/debounce",
+ "@instructure/emotion",
+ "@instructure/instui-config",
+ "@instructure/shared-types",
+ "@instructure/template-app",
+ "@instructure/template-component",
+ "@instructure/template-package",
+ "@instructure/theme-registry",
+ "@instructure/ui",
+ "@instructure/ui-a11y-content",
+ "@instructure/ui-a11y-utils",
+ "@instructure/ui-alerts",
+ "@instructure/ui-avatar",
+ "@instructure/ui-axe-check",
+ "@instructure/ui-badge",
+ "@instructure/ui-billboard",
+ "@instructure/ui-breadcrumb",
+ "@instructure/ui-buttons",
+ "@instructure/ui-byline",
+ "@instructure/ui-calendar",
+ "@instructure/ui-checkbox",
+ "@instructure/ui-code-editor",
+ "@instructure/ui-codemods",
+ "@instructure/ui-color-picker",
+ "@instructure/ui-color-utils",
+ "@instructure/ui-date-input",
+ "@instructure/ui-date-time-input",
+ "@instructure/ui-decorator",
+ "@instructure/ui-dialog",
+ "@instructure/ui-dom-utils",
+ "@instructure/ui-drawer-layout",
+ "@instructure/ui-drilldown",
+ "@instructure/ui-editable",
+ "@instructure/ui-expandable",
+ "@instructure/ui-file-drop",
+ "@instructure/ui-flex",
+ "@instructure/ui-focusable",
+ "@instructure/ui-form-field",
+ "@instructure/ui-grid",
+ "@instructure/ui-heading",
+ "@instructure/ui-i18n",
+ "@instructure/ui-icons",
+ "@instructure/ui-icons-build",
+ "@instructure/ui-img",
+ "@instructure/ui-link",
+ "@instructure/ui-list",
+ "@instructure/ui-menu",
+ "@instructure/ui-metric",
+ "@instructure/ui-modal",
+ "@instructure/ui-motion",
+ "@instructure/ui-navigation",
+ "@instructure/ui-number-input",
+ "@instructure/ui-options",
+ "@instructure/ui-overlays",
+ "@instructure/ui-pages",
+ "@instructure/ui-pagination",
+ "@instructure/ui-pill",
+ "@instructure/ui-popover",
+ "@instructure/ui-portal",
+ "@instructure/ui-position",
+ "@instructure/ui-progress",
+ "@instructure/ui-prop-types",
+ "@instructure/ui-radio-input",
+ "@instructure/ui-range-input",
+ "@instructure/ui-rating",
+ "@instructure/ui-react-utils",
+ "@instructure/ui-responsive",
+ "@instructure/ui-select",
+ "@instructure/ui-selectable",
+ "@instructure/ui-side-nav-bar",
+ "@instructure/ui-simple-select",
+ "@instructure/ui-source-code-editor",
+ "@instructure/ui-spinner",
+ "@instructure/ui-svg-images",
+ "@instructure/ui-table",
+ "@instructure/ui-tabs",
+ "@instructure/ui-tag",
+ "@instructure/ui-test-locator",
+ "@instructure/ui-test-queries",
+ "@instructure/ui-test-sandbox",
+ "@instructure/ui-test-utils",
+ "@instructure/ui-testable",
+ "@instructure/ui-text",
+ "@instructure/ui-text-area",
+ "@instructure/ui-text-input",
+ "@instructure/ui-theme-tokens",
+ "@instructure/ui-themes",
+ "@instructure/ui-time-select",
+ "@instructure/ui-toggle-details",
+ "@instructure/ui-tooltip",
+ "@instructure/ui-top-nav-bar",
+ "@instructure/ui-tray",
+ "@instructure/ui-tree-browser",
+ "@instructure/ui-truncate-list",
+ "@instructure/ui-truncate-text",
+ "@instructure/ui-utils",
+ "@instructure/ui-view",
+ "@instructure/uid"
+]
diff --git a/packages/ui-text-input/package.json b/packages/ui-text-input/package.json
index 611f9fefb6..fa40a5016f 100644
--- a/packages/ui-text-input/package.json
+++ b/packages/ui-text-input/package.json
@@ -23,12 +23,16 @@
},
"license": "MIT",
"devDependencies": {
+ "@instructure/ui-axe-check": "10.0.0",
"@instructure/ui-babel-preset": "10.0.0",
"@instructure/ui-badge": "10.0.0",
"@instructure/ui-color-utils": "10.0.0",
"@instructure/ui-test-utils": "10.0.0",
"@instructure/ui-themes": "10.0.0",
- "react-dom": "^18.3.1"
+ "@testing-library/jest-dom": "^6.4.6",
+ "@testing-library/react": "^15.0.7",
+ "@testing-library/user-event": "^14.5.2",
+ "vitest": "^2.0.2"
},
"dependencies": {
"@babel/runtime": "^7.24.5",
diff --git a/packages/ui-text-input/src/TextInput/__new-tests__/TextInput.test.tsx b/packages/ui-text-input/src/TextInput/__new-tests__/TextInput.test.tsx
new file mode 100644
index 0000000000..9e0e82df47
--- /dev/null
+++ b/packages/ui-text-input/src/TextInput/__new-tests__/TextInput.test.tsx
@@ -0,0 +1,235 @@
+/*
+ * 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 { render, screen, waitFor, fireEvent } from '@testing-library/react'
+import userEvent from '@testing-library/user-event'
+import { vi } from 'vitest'
+import '@testing-library/jest-dom'
+
+import { runAxeCheck } from '@instructure/ui-axe-check'
+import { TextInput } from '../index'
+
+describe('', () => {
+ let consoleErrorMock: any
+
+ beforeEach(() => {
+ // Mocking console to prevent test output pollution and expect for messages
+ consoleErrorMock = vi.spyOn(console, 'error').mockImplementation(() => {})
+ })
+
+ afterEach(() => {
+ consoleErrorMock.mockRestore()
+ })
+
+ it('should include a label', async () => {
+ const { container } = render()
+ const label = container.querySelector('label')
+ expect(label).toHaveTextContent('Name')
+ })
+
+ it('should focus the input when focus is called', async () => {
+ let ref: TextInput | undefined
+ render(
+ {
+ ref = el
+ }}
+ />
+ )
+ const input = screen.getByRole('textbox')
+
+ ref?.focus()
+
+ expect(input).toHaveFocus()
+ })
+
+ it('should provide an inputRef prop', async () => {
+ const inputRef = vi.fn()
+ render()
+ const input = screen.getByRole('textbox')
+
+ expect(inputRef).toHaveBeenCalledWith(input)
+ })
+
+ it('should provide a value getter', async () => {
+ let ref: TextInput | undefined
+ render(
+ {
+ ref = el
+ }}
+ />
+ )
+ expect(ref?.value).toBe('bar')
+ })
+
+ it('should provide messageId to FormField', async () => {
+ render(
+
+ )
+ const input = screen.getByRole('textbox')
+
+ expect(input).toHaveAttribute('aria-describedby')
+ })
+
+ it('should have equal messagesId and aria-describedby values', async () => {
+ const { container } = render(
+
+ )
+ const id = screen.getByRole('textbox').getAttribute('aria-describedby')
+ const messages = container.querySelector(
+ 'span[class$="-formFieldMessages"]'
+ )
+
+ expect(messages).toHaveAttribute('id', id)
+ })
+
+ it('should handle multiple aria-describedby ids', async () => {
+ render(
+
+ )
+ const ids = screen.getByRole('textbox').getAttribute('aria-describedby')
+
+ expect(ids).toMatch('assistive-id TextInput-messages')
+ })
+
+ describe('events', () => {
+ it('responds to onChange event', async () => {
+ const onChange = vi.fn()
+ render()
+ const input = screen.getByRole('textbox')
+ fireEvent.change(input, { target: { value: 'foo' } })
+
+ await waitFor(() => {
+ expect(onChange).toHaveBeenCalledTimes(1)
+ })
+ })
+
+ it('responds to onBlur event', async () => {
+ const onBlur = vi.fn()
+ render()
+
+ userEvent.tab()
+ userEvent.tab()
+
+ await waitFor(() => {
+ expect(onBlur).toHaveBeenCalled()
+ })
+ })
+
+ it('responds to onFocus event', async () => {
+ const onFocus = vi.fn()
+ render()
+ const input = screen.getByRole('textbox')
+
+ input.focus()
+
+ await waitFor(() => {
+ expect(onFocus).toHaveBeenCalled()
+ })
+ })
+ })
+
+ describe('interaction', () => {
+ it('should set the disabled attribute when `interaction` is disabled', async () => {
+ render()
+ const input = screen.getByRole('textbox')
+
+ expect(input).toHaveAttribute('disabled')
+ })
+
+ it('should set the disabled attribute when `disabled` is set', async () => {
+ render()
+ const input = screen.getByRole('textbox')
+
+ expect(input).toHaveAttribute('disabled')
+ })
+
+ it('should set the readonly attribute when `interaction` is readonly', async () => {
+ render()
+ const input = screen.getByRole('textbox')
+
+ expect(input).toHaveAttribute('readonly')
+ })
+
+ it('should set the readonly attribute when `readOnly` is set', async () => {
+ render()
+ const input = screen.getByRole('textbox')
+
+ expect(input).toHaveAttribute('readonly')
+ })
+ })
+
+ describe('for a11y', () => {
+ it('should meet standards', async () => {
+ const { container } = render()
+ const axeCheck = await runAxeCheck(container)
+
+ expect(axeCheck).toBe(true)
+ })
+
+ it('should set aria-invalid when errors prop is set', async () => {
+ render(
+
+ )
+ const input = screen.getByRole('textbox')
+
+ expect(input).toHaveAttribute('aria-invalid')
+ })
+ })
+})
diff --git a/packages/ui-text-input/src/TextInput/__tests__/TextInput.test.tsx b/packages/ui-text-input/src/TextInput/__tests__/TextInput.test.tsx
deleted file mode 100644
index 85c26d5e5b..0000000000
--- a/packages/ui-text-input/src/TextInput/__tests__/TextInput.test.tsx
+++ /dev/null
@@ -1,332 +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 ReactDOM from 'react-dom'
-import ReactTestUtils from 'react-dom/test-utils'
-import { expect, mount, stub, within, find } from '@instructure/ui-test-utils'
-
-import { TextInput } from '../index'
-
-const contentBeforeSVG = (
-
-)
-
-const contentAfterSVG = (
-
-)
-
-class WrapperComponent extends React.Component {
- render() {
- return (
-
-
-
- )
- }
-}
-
-describe('', async () => {
- it('can be found and tested with ReactTestUtils', async () => {
- const rootNode = document.createElement('div')
- document.body.appendChild(rootNode)
-
- // eslint-disable-next-line react/no-render-return-value
- const rendered = ReactDOM.render(, rootNode)
- ReactTestUtils.findRenderedComponentWithType(
- rendered as any,
- (TextInput as any).originalType
- )
- })
-
- it('should include a label', async () => {
- await mount()
- const label = await find('label')
- expect(label).to.exist()
- })
-
- it('should focus the input when focus is called', async () => {
- let ref: TextInput | undefined
-
- const subject = await mount(
- (ref = el)}
- />
- )
- const textInput = within(subject.getDOMNode())
- const input = await textInput.find('input')
-
- ref?.focus()
- expect(input.focused()).to.be.true()
- })
-
- it('should provide an inputRef prop', async () => {
- const inputRef = stub()
-
- const subject = await mount(
-
- )
- const textInput = within(subject.getDOMNode())
- const input = await textInput.find('input')
-
- expect(inputRef).to.have.been.calledWith(input.getDOMNode())
- })
-
- it('should prepend and append content', async () => {
- const subject = await mount(
- contentBeforeSVG}
- />
- )
-
- const textInput = within(subject.getDOMNode())
- const contentBefore = await textInput.find('svg:withTitle(Content before)')
- expect(contentBefore).to.exist()
-
- await subject.setProps({
- renderAfterInput: () => contentAfterSVG
- })
- const contentAfter = await textInput.find('svg:withTitle(Content after)')
- expect(contentAfter).to.exist()
-
- const allContent = await textInput.findAll('svg')
- expect(allContent.length).to.equal(2)
- })
-
- it('should have no padding on empty before/after content', async () => {
- const subject = await mount(
- }
- renderAfterInput={}
- />
- )
-
- const textInput = within(subject.getDOMNode())
- let contentBefore = await textInput.find('[class$=__beforeElement]')
- let contentAfter = await textInput.find('[class$=__afterElement]')
-
- let contentBeforePadding = getComputedStyle(
- contentBefore.getDOMNode()
- ).paddingInlineStart
- let contentAfterPadding = getComputedStyle(
- contentAfter.getDOMNode()
- ).paddingInlineEnd
-
- expect(contentBeforePadding).to.equal('0px')
- expect(contentAfterPadding).to.equal('0px')
-
- await subject.setProps({
- renderBeforeInput: () => contentBeforeSVG,
- renderAfterInput: () => contentAfterSVG
- })
-
- contentBefore = await textInput.find('[class$=__beforeElement]')
- contentAfter = await textInput.find('[class$=__afterElement]')
-
- contentBeforePadding = getComputedStyle(
- contentBefore.getDOMNode()
- ).paddingInlineStart
- contentAfterPadding = getComputedStyle(
- contentAfter.getDOMNode()
- ).paddingInlineEnd
-
- expect(contentBeforePadding).to.equal('12px')
- expect(contentAfterPadding).to.equal('12px')
- })
-
- it('should provide a value getter', async () => {
- let ref: TextInput | undefined
-
- await mount(
- (ref = el)}
- />
- )
-
- expect(ref?.value).to.equal('bar')
- })
-
- it('should provide messageId to FormField', async () => {
- const subject = await mount(
-
- )
- const textInput = within(subject.getDOMNode())
- const input = await textInput.find('input')
-
- expect(input.getAttribute('aria-describedby')).to.exist()
- })
-
- it('should have equal messagesId and aria-describedby values', async () => {
- const subject = await mount(
-
- )
- const textInput = within(subject.getDOMNode())
- const input = await textInput.find('input')
-
- const id = input.getAttribute('aria-describedby')
- const messages = await textInput.find(`[id="${id}"]`)
-
- expect(messages).to.exist()
- })
-
- it('should handle multiple aria-describedby ids', async () => {
- const subject = await mount(
-
- )
- const textInput = within(subject.getDOMNode())
- const input = await textInput.find('input')
- const ids = input.getAttribute('aria-describedby')
-
- expect(ids).to.startWith('assistive-id TextInput-messages')
- })
-
- describe('events', async () => {
- it('responds to onChange event', async () => {
- const onChange = stub()
-
- const subject = await mount(
-
- )
- const textInput = within(subject.getDOMNode())
- const input = await textInput.find('input')
-
- await input.change({ target: { value: 'foo' } })
- expect(onChange).to.have.been.called()
- })
-
- it('responds to onBlur event', async () => {
- const onBlur = stub()
-
- const subject = await mount(
-
- )
- const textInput = within(subject.getDOMNode())
- const input = await textInput.find('input')
-
- await input.focusOut()
- expect(onBlur).to.have.been.called()
- })
-
- it('responds to onFocus event', async () => {
- const onFocus = stub()
-
- const subject = await mount(
-
- )
- const textInput = within(subject.getDOMNode())
- const input = await textInput.find('input')
-
- await input.focus()
- expect(onFocus).to.have.been.called()
- })
- })
-
- describe('interaction', async () => {
- it('should set the disabled attribute when `interaction` is disabled', async () => {
- const subject = await mount(
-
- )
- const textInput = within(subject.getDOMNode())
- expect(await textInput.find('input[disabled]')).to.exist()
- })
-
- it('should set the disabled attribute when `disabled` is set', async () => {
- const subject = await mount()
- const textInput = within(subject.getDOMNode())
- expect(await textInput.find('input[disabled]')).to.exist()
- })
-
- it('should set the readonly attribute when `interaction` is readonly', async () => {
- const subject = await mount(
-
- )
- const textInput = within(subject.getDOMNode())
- expect(await textInput.find('input[readonly]')).to.exist()
- })
-
- it('should set the readonly attribute when `readOnly` is set', async () => {
- const subject = await mount()
- const textInput = within(subject.getDOMNode())
- expect(await textInput.find('input[readonly]')).to.exist()
- })
- })
-
- describe('for a11y', async () => {
- it('should meet standards', async () => {
- const subject = await mount()
- const textInput = within(subject.getDOMNode())
- expect(await textInput.accessible()).to.be.true()
- })
-
- it('should set aria-invalid when errors prop is set', async () => {
- const subject = await mount(
-
- )
- const textInput = within(subject.getDOMNode())
- const input = await textInput.find('input')
- expect(input.getAttribute('aria-invalid')).to.exist()
- })
- })
-})
diff --git a/packages/ui-text-input/tsconfig.build.json b/packages/ui-text-input/tsconfig.build.json
index 458e67ad26..3e3f01025f 100644
--- a/packages/ui-text-input/tsconfig.build.json
+++ b/packages/ui-text-input/tsconfig.build.json
@@ -14,6 +14,7 @@
{ "path": "../ui-themes/tsconfig.build.json" },
{ "path": "../emotion/tsconfig.build.json" },
{ "path": "../shared-types/tsconfig.build.json" },
+ { "path": "../ui-axe-check/tsconfig.build.json" },
{ "path": "../ui-dom-utils/tsconfig.build.json" },
{ "path": "../ui-form-field/tsconfig.build.json" },
{ "path": "../ui-icons/tsconfig.build.json" },