mirror of
https://github.com/fergalmoran/turnstone.git
synced 2025-12-30 13:51:20 +00:00
First pass at some integration tests
This commit is contained in:
2772
package-lock.json
generated
2772
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -26,7 +26,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"first-of-type": "^1.0.0",
|
||||
"nanoid": "^3.3.1",
|
||||
"prop-types": "^15.8.1",
|
||||
"react-use": "^17.3.2",
|
||||
"setify": "^1.0.4",
|
||||
@@ -34,13 +33,17 @@
|
||||
"use-debounce": "^7.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@testing-library/dom": "^8.11.3",
|
||||
"@testing-library/react": "^12.1.3",
|
||||
"@testing-library/react-hooks": "^7.0.2",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"@vitejs/plugin-react": "^1.0.7",
|
||||
"c8": "^7.11.0",
|
||||
"eslint": "^8.9.0",
|
||||
"eslint-plugin-react": "^7.28.0",
|
||||
"jsdom": "^19.0.0",
|
||||
"msw": "^0.36.8",
|
||||
"nanoid": "^3.3.1",
|
||||
"node-fetch": "^2.6.7",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
|
||||
@@ -19,6 +19,7 @@ const App = () => {
|
||||
id={'autocomplete'}
|
||||
itemGroupsAreImmutable={true}
|
||||
maxItems={10}
|
||||
name={'search'}
|
||||
noItemsMessage={'No matching fruit found'}
|
||||
placeholder={'Type something fruity'}
|
||||
styles={styles}
|
||||
|
||||
99
src/lib/__tests__/turnstone.test.jsx
Normal file
99
src/lib/__tests__/turnstone.test.jsx
Normal file
@@ -0,0 +1,99 @@
|
||||
import * as React from 'react'
|
||||
import { render, screen, cleanup } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { describe, expect, test, afterEach } from 'vitest'
|
||||
import Turnstone from '../index'
|
||||
import { fruits } from '../../data'
|
||||
|
||||
describe('Integration tests', () => {
|
||||
afterEach(cleanup)
|
||||
|
||||
test('Minimal render includes expected elements', () => {
|
||||
const placeholder = 'Test placeholder'
|
||||
|
||||
render(<Turnstone
|
||||
data={fruits}
|
||||
dataSearchType={'startswith'}
|
||||
placeholder={placeholder}
|
||||
/>)
|
||||
|
||||
expect(screen.getByRole('combobox'))
|
||||
expect(screen.getByPlaceholderText(placeholder)).toBeDefined()
|
||||
expect(screen.queryByText('listbox')).toBeNull().toBeDefined()
|
||||
expect(screen.queryByRole('button', { name: /clear contents/i })).toBeNull()
|
||||
})
|
||||
|
||||
test('Supplying a text prop populates the query input and opens the dropdown', async () => {
|
||||
const text = 'pe'
|
||||
|
||||
render(<Turnstone
|
||||
autoFocus={true}
|
||||
data={fruits}
|
||||
dataSearchType={'startswith'}
|
||||
text={text}
|
||||
/>)
|
||||
|
||||
expect(screen.getByDisplayValue(text)).toBeDefined()
|
||||
expect(screen.queryByRole('button', { name: /clear contents/i })).toBeDefined()
|
||||
expect(await screen.findByRole('listbox')).toBeDefined()
|
||||
expect(await screen.getByDisplayValue('Peach')).toBeDefined()
|
||||
})
|
||||
|
||||
test('Supplying a clearButton prop displays the clear button', () => {
|
||||
const text = 'pe'
|
||||
|
||||
render(<Turnstone
|
||||
data={fruits}
|
||||
dataSearchType={'startswith'}
|
||||
text={text}
|
||||
/>)
|
||||
|
||||
expect(screen.queryByRole('button', { name: /clear contents/i })).toBeDefined()
|
||||
})
|
||||
|
||||
test('Changing the typed text produces the expected dropdown results', async () => {
|
||||
const placeholder = 'test'
|
||||
|
||||
render(<Turnstone
|
||||
data={fruits}
|
||||
dataSearchType={'startswith'}
|
||||
placeholder={placeholder}
|
||||
/>)
|
||||
|
||||
const container = screen.getByRole('combobox')
|
||||
const input = screen.getByPlaceholderText(placeholder)
|
||||
const typeahead = container.children[1]
|
||||
|
||||
expect(input).toBeDefined()
|
||||
expect(typeahead).toBeDefined()
|
||||
expect(screen.queryByRole('listbox')).toBeNull()
|
||||
userEvent.type(screen.getByRole('textbox'), 'p')
|
||||
expect(await screen.findByRole('listbox')).toBeDefined()
|
||||
expect(typeahead.value).toBe('Peach')
|
||||
expect(input.value).toBe('P')
|
||||
expect(screen.getByRole('option', { name: /peach/i }).getAttribute('aria-selected')).toBe('true')
|
||||
userEvent.type(screen.getByRole('textbox'), 'i', { skipClick: true })
|
||||
expect(screen.getByRole('listbox')).toBeDefined()
|
||||
expect(await screen.findByDisplayValue('Pineapple')).toBeDefined()
|
||||
expect(input.value).toBe('Pi')
|
||||
expect(screen.getByRole('option', { name: /pineapple/i }).getAttribute('aria-selected')).toBe('true')
|
||||
userEvent.type(screen.getByRole('textbox'), '{arrowdown}', { skipClick: true })
|
||||
expect(screen.getByRole('listbox')).toBeDefined()
|
||||
expect(await screen.findByDisplayValue('Pitaya')).toBeDefined()
|
||||
expect(input.value).toBe('Pi')
|
||||
expect(screen.getByRole('option', { name: /pineapple/i }).getAttribute('aria-selected')).toBe('false')
|
||||
expect(screen.getByRole('option', { name: /pitaya/i }).getAttribute('aria-selected')).toBe('true')
|
||||
userEvent.type(screen.getByRole('textbox'), '{arrowup}', { skipClick: true })
|
||||
expect(screen.getByRole('listbox')).toBeDefined()
|
||||
expect(await screen.findByDisplayValue('Pineapple')).toBeDefined()
|
||||
expect(input.value).toBe('Pi')
|
||||
expect(screen.getByRole('option', { name: /pineapple/i }).getAttribute('aria-selected')).toBe('true')
|
||||
expect(screen.getByRole('option', { name: /pitaya/i }).getAttribute('aria-selected')).toBe('false')
|
||||
userEvent.type(screen.getByRole('textbox'), '{backspace}', { skipClick: true })
|
||||
expect(await screen.findByDisplayValue('Peach')).toBeDefined()
|
||||
userEvent.type(screen.getByRole('textbox'), '{backspace}', { skipClick: true })
|
||||
expect(screen.queryByRole('listbox')).toBeNull()
|
||||
expect(input.value).toBe('')
|
||||
expect(typeahead.value).toBe('')
|
||||
})
|
||||
})
|
||||
@@ -2,7 +2,6 @@ import * as types from './actionTypes'
|
||||
import undef from '../utils/undef'
|
||||
|
||||
export const setQuery = (query) => {
|
||||
console.log('setQuery', {query})
|
||||
const payload = {
|
||||
query,
|
||||
selected: undef
|
||||
|
||||
@@ -35,7 +35,6 @@ exports[`Container > Component renders correctly 1`] = `
|
||||
"zIndex": 1,
|
||||
}
|
||||
}
|
||||
tabIndex="1"
|
||||
type="text"
|
||||
/>
|
||||
<input
|
||||
|
||||
@@ -39,12 +39,14 @@ export default function Container(props) {
|
||||
itemGroupsAreImmutable,
|
||||
maxItems,
|
||||
minQueryLength,
|
||||
name,
|
||||
noItemsMessage,
|
||||
onChange,
|
||||
onSelect,
|
||||
onEnter,
|
||||
onTab,
|
||||
placeholder
|
||||
placeholder,
|
||||
tabIndex
|
||||
} = props
|
||||
|
||||
// Destructure itemGroups prop
|
||||
@@ -196,6 +198,7 @@ export default function Container(props) {
|
||||
aria-haspopup='listbox'>
|
||||
<input
|
||||
id={id}
|
||||
name={name}
|
||||
className={customStyles.query}
|
||||
style={defaultStyles.query}
|
||||
disabled={isDisabled}
|
||||
@@ -205,7 +208,7 @@ export default function Container(props) {
|
||||
autoCorrect='off'
|
||||
autoCapitalize='off'
|
||||
spellCheck='false'
|
||||
tabIndex='1'
|
||||
tabIndex={tabIndex}
|
||||
ref={queryInput}
|
||||
onKeyDown={checkKey}
|
||||
onInput={handleInput}
|
||||
|
||||
@@ -92,6 +92,7 @@ Turnstone.propTypes = {
|
||||
`Prop "minQueryLength" must be a number greater than ${propDefaults.minQueryLength - 1}`
|
||||
)
|
||||
},
|
||||
name: PropTypes.string,
|
||||
noItemsMessage: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
onSelect: PropTypes.func,
|
||||
@@ -101,6 +102,7 @@ Turnstone.propTypes = {
|
||||
maxItems: PropTypes.number,
|
||||
splitChar: PropTypes.string,
|
||||
styles: PropTypes.object,
|
||||
tabIndex: PropTypes.number,
|
||||
text: PropTypes.string
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,6 @@ import { defineConfig } from 'vite'
|
||||
export default defineConfig({
|
||||
test: {
|
||||
globals: false,
|
||||
environment: 'node'
|
||||
environment: 'jsdom'
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user