diff --git a/package.json b/package.json index ba2565e6b9..058dfc8a65 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "peerDependencies": { "react": "^16.x || ^17.x", "react-dom": "^16.x || ^17.x", - "uswds": "2.9.0" + "uswds": "2.10.3" }, "devDependencies": { "@babel/core": "^7.10.5", @@ -126,7 +126,7 @@ "ts-jest": "^26.1.2", "typescript": "^3.8.0", "url-loader": "^4.0.0", - "uswds": "2.9.0", + "uswds": "2.10.3", "webpack": "^4.41.0", "webpack-cli": "^4.0.0" }, diff --git a/src/components/Footer/Footer/Footer.stories.tsx b/src/components/Footer/Footer/Footer.stories.tsx index af652fa66f..f607aa1393 100644 --- a/src/components/Footer/Footer/Footer.stories.tsx +++ b/src/components/Footer/Footer/Footer.stories.tsx @@ -96,7 +96,7 @@ export const SlimFooter = (): React.ReactElement => ( src={logoImg} /> } - heading={

Name of Agency

} + heading={

Name of Agency

} /> } /> @@ -127,7 +127,7 @@ export const MediumFooter = (): React.ReactElement => ( src={logoImg} /> } - heading={

Name of Agency

} + heading={

Name of Agency

} />
( href="#"> YouTube , + + Instagram + , ( src={logoImg} /> } - heading={

Name of Agency

} + heading={

Name of Agency

} />
( href="#"> YouTube , + + Instagram + , ( image={ Mock logo } - heading={

Name of Agency

} + heading={

Name of Agency

} />
) diff --git a/src/components/Footer/Logo/Logo.test.tsx b/src/components/Footer/Logo/Logo.test.tsx index 87720fad79..2cf3c07c1f 100644 --- a/src/components/Footer/Logo/Logo.test.tsx +++ b/src/components/Footer/Logo/Logo.test.tsx @@ -5,7 +5,7 @@ jest.mock('../../../deprecation') import { deprecationWarning } from '../../../deprecation' import { Logo } from './Logo' -const heading =

Swoosh Branding

+const heading =

Swoosh Branding

const logoImage = ( YouTube
, + + Instagram + , RSS , diff --git a/src/components/GovBanner/GovBanner.tsx b/src/components/GovBanner/GovBanner.tsx index d8be425f46..5545e96f70 100644 --- a/src/components/GovBanner/GovBanner.tsx +++ b/src/components/GovBanner/GovBanner.tsx @@ -23,7 +23,14 @@ interface GovBannerCopy { const getCopy = (language: Language, tld: TLD): GovBannerCopy => { const lock = ( - lock + {/* eslint-disable-next-line jsx-a11y/no-redundant-roles */} + lock ) @@ -154,7 +161,9 @@ export const GovBanner = ({

@@ -168,7 +177,9 @@ export const GovBanner = ({

diff --git a/src/components/GovBanner/__snapshots__/GovBanner.test.tsx.snap b/src/components/GovBanner/__snapshots__/GovBanner.test.tsx.snap index 71e6548566..88db8748b1 100644 --- a/src/components/GovBanner/__snapshots__/GovBanner.test.tsx.snap +++ b/src/components/GovBanner/__snapshots__/GovBanner.test.tsx.snap @@ -65,8 +65,10 @@ exports[`GovBanner component static content renders consistently in English for className="usa-banner__guidance tablet:grid-col-6" >

) @@ -196,8 +202,10 @@ exports[`GovBanner component static content renders consistently in English for className="usa-banner__guidance tablet:grid-col-6" >
) @@ -327,8 +339,10 @@ exports[`GovBanner component static content renders consistently in Spanish for className="usa-banner__guidance tablet:grid-col-6" >
) @@ -459,8 +477,10 @@ exports[`GovBanner component static content renders consistently in Spanish for className="usa-banner__guidance tablet:grid-col-6" >
) @@ -591,8 +615,10 @@ exports[`GovBanner component static content renders consistently with default pr className="usa-banner__guidance tablet:grid-col-6" >
) diff --git a/src/components/forms/ComboBox/ComboBox.stories.tsx b/src/components/forms/ComboBox/ComboBox.stories.tsx index 3318003b4c..774bb38af7 100644 --- a/src/components/forms/ComboBox/ComboBox.stories.tsx +++ b/src/components/forms/ComboBox/ComboBox.stories.tsx @@ -71,8 +71,16 @@ export const withLabel = (): React.ReactElement => { return (
- - + + ) } diff --git a/src/components/forms/ComboBox/ComboBox.test.tsx b/src/components/forms/ComboBox/ComboBox.test.tsx index 97fdb0096e..0696046929 100644 --- a/src/components/forms/ComboBox/ComboBox.test.tsx +++ b/src/components/forms/ComboBox/ComboBox.test.tsx @@ -40,12 +40,10 @@ describe('ComboBox component', () => { defaultValue="apple" /> ) - expect(getByTestId('combo-box-select')).toBeInstanceOf(HTMLSelectElement) - expect(getByTestId('combo-box-select')).toHaveAttribute( - 'aria-hidden', - 'true' - ) - expect(getByTestId('combo-box-select')).toHaveClass('usa-sr-only') + const comboBoxSelect = getByTestId('combo-box-select') + expect(comboBoxSelect).toBeInstanceOf(HTMLSelectElement) + expect(comboBoxSelect).toHaveAttribute('aria-hidden', 'true') + expect(comboBoxSelect).toHaveClass('usa-sr-only') }) it('renders input element', () => { @@ -57,8 +55,10 @@ describe('ComboBox component', () => { onChange={jest.fn()} /> ) - expect(getByRole('combobox')).toBeInTheDocument() - expect(getByRole('combobox')).toBeInstanceOf(HTMLInputElement) + + const comboBox = getByRole('combobox') + expect(comboBox).toBeInTheDocument() + expect(comboBox).toBeInstanceOf(HTMLInputElement) }) it('renders hidden options list on load', () => { @@ -216,9 +216,9 @@ describe('ComboBox component', () => { selectProps={{ required: true, role: 'testing' }} /> ) - - expect(getByTestId('combo-box-select')).toHaveAttribute('required') - expect(getByTestId('combo-box-select')).toHaveAttribute('role', 'testing') + const comboBoxSelect = getByTestId('combo-box-select') + expect(comboBoxSelect).toHaveAttribute('required') + expect(comboBoxSelect).toHaveAttribute('role', 'testing') }) it('renders input with custom props if passed in', () => { @@ -232,8 +232,27 @@ describe('ComboBox component', () => { /> ) - expect(getByTestId('combo-box-input')).toHaveAttribute('required') - expect(getByTestId('combo-box-input')).toHaveAttribute('role', 'testing') + const comboBoxInput = getByTestId('combo-box-input') + expect(comboBoxInput).toHaveAttribute('required') + expect(comboBoxInput).toHaveAttribute('role', 'testing') + }) + + it('renders input with custom props if passed in', () => { + const { getByTestId } = render( + + ) + + const comboBoxOptionList = getByTestId('combo-box-option-list') + expect(comboBoxOptionList).toHaveAttribute( + 'aria-labelledby', + 'test-label-id' + ) }) // TODO: ❓ Don't know how to test this @@ -460,10 +479,9 @@ describe('ComboBox component', () => { expect(getByTestId('combo-box-clear-button')).not.toBeVisible() expect(getByTestId('combo-box-input')).toHaveValue('') expect(onChange).toHaveBeenNthCalledWith(2, undefined) - expect(getByTestId('combo-box-option-list')).not.toBeVisible() - expect(getByTestId('combo-box-option-list').children.length).toBe( - fruitOptions.length - ) + const comboBoxOptionList = getByTestId('combo-box-option-list') + expect(comboBoxOptionList).not.toBeVisible() + expect(comboBoxOptionList.children.length).toBe(fruitOptions.length) }) it('remains focused on the input after click', () => { @@ -533,9 +551,10 @@ describe('ComboBox component', () => { userEvent.type(getByTestId('combo-box-input'), 'zzz{enter}') + const comboBoxInput = getByTestId('combo-box-input') expect(getByTestId('combo-box-option-list')).not.toBeVisible() - expect(getByTestId('combo-box-input')).toHaveValue('') - expect(getByTestId('combo-box-input')).toHaveFocus() + expect(comboBoxInput).toHaveValue('') + expect(comboBoxInput).toHaveFocus() }) it('clears filter when there is no match and enter is pressed', () => { @@ -549,11 +568,9 @@ describe('ComboBox component', () => { ) userEvent.type(getByTestId('combo-box-input'), 'zzz{enter}') - - expect(getByTestId('combo-box-option-list')).not.toBeVisible() - expect(getByTestId('combo-box-option-list').children.length).toBe( - fruitOptions.length - ) + const comboBoxOptionList = getByTestId('combo-box-option-list') + expect(comboBoxOptionList).not.toBeVisible() + expect(comboBoxOptionList.children.length).toBe(fruitOptions.length) }) it('focuses the first filtered option with tab', () => { @@ -587,11 +604,9 @@ describe('ComboBox component', () => { userEvent.click(getByTestId('combo-box-input')) // open menu userEvent.tab() - expect(getByTestId('combo-box-option-apple')).toHaveFocus() - expect(getByTestId('combo-box-option-apple')).toHaveAttribute( - 'tabindex', - '0' - ) + const appleOption = getByTestId('combo-box-option-apple') + expect(appleOption).toHaveFocus() + expect(appleOption).toHaveAttribute('tabindex', '0') }) it('selects the focused option with tab', () => { @@ -643,11 +658,12 @@ describe('ComboBox component', () => { /> ) - userEvent.type(getByTestId('combo-box-input'), 'apri') + const comboBoxInput = getByTestId('combo-box-input') + userEvent.type(comboBoxInput, 'apri') userEvent.tab() userEvent.type(getByTestId('combo-box-option-apricot'), '{enter}') - expect(getByTestId('combo-box-input')).toHaveValue('Apricot') + expect(comboBoxInput).toHaveValue('Apricot') expect(onChange).toHaveBeenLastCalledWith('apricot') }) @@ -705,8 +721,9 @@ describe('ComboBox component', () => { /> ) - userEvent.click(getByTestId('combo-box-input')) - fireEvent.keyDown(getByTestId('combo-box-input'), { + const comboBoxInput = getByTestId('combo-box-input') + userEvent.click(comboBoxInput) + fireEvent.keyDown(comboBoxInput, { key: 'ArrowDown', }) @@ -724,8 +741,9 @@ describe('ComboBox component', () => { /> ) - userEvent.click(getByTestId('combo-box-input')) - fireEvent.keyDown(getByTestId('combo-box-input'), { + const comboBoxInput = getByTestId('combo-box-input') + userEvent.click(comboBoxInput) + fireEvent.keyDown(comboBoxInput, { key: 'ArrowDown', }) fireEvent.keyDown(getByTestId('combo-box-option-apple'), { @@ -733,7 +751,7 @@ describe('ComboBox component', () => { }) expect(getByTestId('combo-box-option-list')).not.toBeVisible() - expect(getByTestId('combo-box-input')).toHaveFocus() + expect(comboBoxInput).toHaveFocus() }) it('does not change focus when last option is focused and down arrow is pressed', () => { @@ -746,13 +764,14 @@ describe('ComboBox component', () => { /> ) + const yuzuOption = getByTestId('combo-box-option-yuzu') fireEvent.click(getByTestId('combo-box-input')) - userEvent.hover(getByTestId('combo-box-option-yuzu')) - fireEvent.keyDown(getByTestId('combo-box-option-yuzu'), { + userEvent.hover(yuzuOption) + fireEvent.keyDown(yuzuOption, { key: 'ArrowDown', }) - expect(getByTestId('combo-box-option-yuzu')).toHaveFocus() + expect(yuzuOption).toHaveFocus() }) it('pressing tab once in the input with a selected option focuses the clear button', () => { @@ -824,12 +843,13 @@ describe('ComboBox component', () => { ) // Apple is the item at top of list - userEvent.hover(getByTestId('combo-box-option-apple')) - fireEvent.keyDown(getByTestId('combo-box-option-apple'), { + const appleOption = getByTestId('combo-box-option-apple') + userEvent.hover(appleOption) + fireEvent.keyDown(appleOption, { key: 'ArrowUp', }) - expect(getByTestId('combo-box-option-apple')).toHaveFocus() + expect(appleOption).toHaveFocus() expect(getByTestId('combo-box-input')).toHaveAttribute( 'aria-expanded', 'true' @@ -927,10 +947,11 @@ describe('ComboBox component', () => { /> ) const input = getByTestId('combo-box-input') + const apricotOption = getByTestId('combo-box-option-apricot') userEvent.tab() - userEvent.hover(getByTestId('combo-box-option-apricot')) - fireEvent.keyDown(getByTestId('combo-box-option-apricot'), { + userEvent.hover(apricotOption) + fireEvent.keyDown(apricotOption, { key: 'tab', keyCode: 9, shiftKey: true, @@ -950,17 +971,14 @@ describe('ComboBox component', () => { onChange={jest.fn()} /> ) + const input = getByTestId('combo-box-input') + const optionList = getByTestId('combo-box-option-list') - fireEvent.click(getByTestId('combo-box-input')) + fireEvent.click(input) - expect(getByTestId('combo-box-input')).toHaveAttribute( - 'aria-expanded', - 'true' - ) - expect(getByTestId('combo-box-option-list')).toBeVisible() - expect(getByTestId('combo-box-option-list').childElementCount).toEqual( - fruitOptions.length - ) + expect(input).toHaveAttribute('aria-expanded', 'true') + expect(optionList).toBeVisible() + expect(optionList.childElementCount).toEqual(fruitOptions.length) }) it('displays options list when input is clicked twice', () => { @@ -992,13 +1010,11 @@ describe('ComboBox component', () => { /> ) - fireEvent.click(getByTestId('combo-box-input')) - fireEvent.blur(getByTestId('combo-box-input')) + const input = getByTestId('combo-box-input') + fireEvent.click(input) + fireEvent.blur(input) - expect(getByTestId('combo-box-input')).toHaveAttribute( - 'aria-expanded', - 'false' - ) + expect(input).toHaveAttribute('aria-expanded', 'false') expect(getByTestId('combo-box-option-list')).not.toBeVisible() }) @@ -1012,15 +1028,15 @@ describe('ComboBox component', () => { /> ) - fireEvent.click(getByTestId('combo-box-input')) - userEvent.hover(getByTestId('combo-box-option-blackberry')) + const input = getByTestId('combo-box-input') + const blackberryOption = getByTestId('combo-box-option-blackberry') - fireEvent.blur(getByTestId('combo-box-option-blackberry')) + fireEvent.click(input) - expect(getByTestId('combo-box-input')).toHaveAttribute( - 'aria-expanded', - 'false' - ) + userEvent.hover(blackberryOption) + fireEvent.blur(blackberryOption) + + expect(input).toHaveAttribute('aria-expanded', 'false') expect(getByTestId('combo-box-option-list')).not.toBeVisible() }) @@ -1034,21 +1050,17 @@ describe('ComboBox component', () => { /> ) + const input = getByTestId('combo-box-input') + const optionList = getByTestId('combo-box-option-list') fireEvent.click(getByTestId('combo-box-toggle')) - expect(getByTestId('combo-box-input')).toHaveAttribute( - 'aria-expanded', - 'true' - ) - expect(getByTestId('combo-box-option-list')).toBeVisible() + expect(input).toHaveAttribute('aria-expanded', 'true') + expect(optionList).toBeVisible() fireEvent.click(getByTestId('combo-box-toggle')) - expect(getByTestId('combo-box-input')).toHaveAttribute( - 'aria-expanded', - 'false' - ) - expect(getByTestId('combo-box-option-list')).not.toBeVisible() + expect(input).toHaveAttribute('aria-expanded', 'false') + expect(optionList).not.toBeVisible() }) it('selects an item by clicking on an option', () => { @@ -1062,12 +1074,13 @@ describe('ComboBox component', () => { /> ) + const input = getByTestId('combo-box-input') fireEvent.click(getByTestId('combo-box-toggle')) fireEvent.click(getByTestId('combo-box-option-apple')) expect(onChange).toHaveBeenLastCalledWith('apple') - expect(getByTestId('combo-box-input')).toHaveDisplayValue('Apple') - expect(getByTestId('combo-box-input')).toHaveValue('Apple') + expect(input).toHaveDisplayValue('Apple') + expect(input).toHaveValue('Apple') }) it('persists input text when items list is blurred', () => { @@ -1084,13 +1097,14 @@ describe('ComboBox component', () => { ) + const input = getByTestId('combo-box-input') userEvent.click(getByTestId('combo-box-toggle')) userEvent.click(getByTestId('combo-box-option-apple')) - fireEvent.blur(getByTestId('combo-box-input')) + fireEvent.blur(input) expect(onChange).toHaveBeenLastCalledWith('apple') - expect(getByTestId('combo-box-input')).toHaveDisplayValue('Apple') - expect(getByTestId('combo-box-input')).toHaveValue('Apple') + expect(input).toHaveDisplayValue('Apple') + expect(input).toHaveValue('Apple') }) it('persists input text if dropdown is closed and open without selection', () => { @@ -1104,12 +1118,13 @@ describe('ComboBox component', () => { ) const input = getByTestId('combo-box-input') + const toggle = getByTestId('combo-box-toggle') userEvent.type(input, 'yu') - userEvent.click(getByTestId('combo-box-toggle')) + userEvent.click(toggle) expect(input).toHaveValue('yu') - userEvent.click(getByTestId('combo-box-toggle')) + userEvent.click(toggle) expect(input).toHaveValue('yu') }) @@ -1142,20 +1157,21 @@ describe('ComboBox component', () => { /> ) + const yuzuOption = getByTestId('combo-box-option-yuzu') + const blackberryOption = getByTestId('combo-box-option-blackberry') + userEvent.click(getByTestId('combo-box-toggle')) - userEvent.hover(getByTestId('combo-box-option-blackberry')) + userEvent.hover(blackberryOption) - expect(getByTestId('combo-box-option-blackberry')).toHaveClass( + expect(blackberryOption).toHaveClass( 'usa-combo-box__list-option--focused' ) - userEvent.hover(getByTestId('combo-box-option-yuzu')) - expect(getByTestId('combo-box-option-blackberry')).not.toHaveClass( - 'usa-combo-box__list-option--focused' - ) - expect(getByTestId('combo-box-option-yuzu')).toHaveClass( + userEvent.hover(yuzuOption) + expect(blackberryOption).not.toHaveClass( 'usa-combo-box__list-option--focused' ) + expect(yuzuOption).toHaveClass('usa-combo-box__list-option--focused') }) it('clears focus when clicking outside of the component', () => { diff --git a/src/components/forms/ComboBox/ComboBox.tsx b/src/components/forms/ComboBox/ComboBox.tsx index 14ebf5e193..16b83c8df2 100644 --- a/src/components/forms/ComboBox/ComboBox.tsx +++ b/src/components/forms/ComboBox/ComboBox.tsx @@ -37,6 +37,7 @@ interface ComboBoxProps { noResults?: string inputProps?: JSX.IntrinsicElements['input'] selectProps?: JSX.IntrinsicElements['select'] + ulProps?: JSX.IntrinsicElements['ul'] } interface InputProps { @@ -79,6 +80,7 @@ export const ComboBox = ({ noResults, selectProps, inputProps, + ulProps, ...customProps }: ComboBoxProps): React.ReactElement => { const isDisabled = !!disabled @@ -341,7 +343,8 @@ export const ComboBox = ({ id={listID} className="usa-combo-box__list" role="listbox" - hidden={!state.isOpen}> + hidden={!state.isOpen} + {...ulProps}> {state.filteredOptions.map((option, index) => { const focused = option === state.focusedOption const selected = option === state.selectedOption diff --git a/src/stories/templates/documentation.stories.tsx b/src/stories/templates/documentation.stories.tsx index 59830e9a71..f429c8e3ae 100644 --- a/src/stories/templates/documentation.stories.tsx +++ b/src/stories/templates/documentation.stories.tsx @@ -155,7 +155,7 @@ export const DocumentationPage = (): React.ReactElement => { } - heading={

Name of Agency

} + heading={

Name of Agency

} /> { href="javascript:void(0);"> YouTube , + + Instagram + , { } - heading={

Name of Agency

} + heading={

Name of Agency

} /> { href="javascript:void(0);"> YouTube
, + + Instagram + ,