Add Selector to react-test
This commit is contained in:
parent
adb3d877a4
commit
e86c8b9226
@ -1,4 +1,4 @@
|
||||
import { TestUtils } from './index'
|
||||
import { TestUtils, select } from './index'
|
||||
import React from 'react'
|
||||
|
||||
describe('TestUtils', () => {
|
||||
@ -13,6 +13,114 @@ describe('TestUtils', () => {
|
||||
}
|
||||
}
|
||||
|
||||
type ChangeFn1 = (event: React.ChangeEvent<HTMLInputElement>) => void
|
||||
type ChangeFn2 = (event: React.ChangeEvent<HTMLTextAreaElement>) => void
|
||||
|
||||
describe('Selector', () => {
|
||||
interface FormProps {
|
||||
onSubmit: () => void
|
||||
onClick: () => void
|
||||
onChange1: ChangeFn1
|
||||
onChange2: ChangeFn2
|
||||
value1: string
|
||||
value2: string
|
||||
}
|
||||
|
||||
class Form extends React.PureComponent<FormProps> {
|
||||
render() {
|
||||
const {props} = this
|
||||
return (
|
||||
<form onSubmit={props.onSubmit}>
|
||||
<span>type stuff</span>
|
||||
<input
|
||||
onChange={props.onChange1}
|
||||
value={props.value1}
|
||||
name='value'
|
||||
/>
|
||||
<textarea
|
||||
onChange={props.onChange2}
|
||||
value={props.value2}
|
||||
name='value'
|
||||
/>
|
||||
<input
|
||||
onClick={props.onClick}
|
||||
type='submit'
|
||||
/>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const onChange1: jest.Mock<ChangeFn1> = jest.fn()
|
||||
const onChange2: jest.Mock<ChangeFn2> = jest.fn()
|
||||
const onSubmit = jest.fn()
|
||||
const onClick = jest.fn()
|
||||
|
||||
beforeEach(() => {
|
||||
onChange1.mockClear()
|
||||
onChange2.mockClear()
|
||||
onSubmit.mockClear()
|
||||
onClick.mockClear()
|
||||
})
|
||||
|
||||
const render = async () => {
|
||||
return await tu.render(
|
||||
<Form
|
||||
value1={'a'}
|
||||
value2={'b'}
|
||||
onChange1={onChange1}
|
||||
onChange2={onChange2}
|
||||
onSubmit={onSubmit}
|
||||
onClick={onClick}
|
||||
/>,
|
||||
)
|
||||
}
|
||||
|
||||
describe('type', () => {
|
||||
it('dispatches change event', async () => {
|
||||
const result = await render()
|
||||
const $form = select(result.node)
|
||||
const $inputA = $form.findOneByValue('input', 'a')
|
||||
expect($inputA.value()).toBe('a')
|
||||
$inputA.type('test')
|
||||
expect(onChange1.mock.calls[0][0].target).toEqual({ value: 'test' })
|
||||
})
|
||||
})
|
||||
|
||||
describe('findOne and click', () => {
|
||||
it('dispatches click event', async () => {
|
||||
const result = await render()
|
||||
const $form = select(result.node)
|
||||
const $submit = $form.findOne('input[type=submit]')
|
||||
$submit.click()
|
||||
expect(onClick.mock.calls.length).toBe(1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('submit', () => {
|
||||
it('submits a form', async () => {
|
||||
const result = await render()
|
||||
const $form = select(result.node)
|
||||
$form.submit()
|
||||
expect(onSubmit.mock.calls.length).toBe(1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('findOneByContent', () => {
|
||||
it('retrieves an element with textContent', async () => {
|
||||
const result = await render()
|
||||
const $form = select(result.node)
|
||||
const $item = $form.findOneByContent('span', 'type stuff')
|
||||
expect($item.tag()).toBe('SPAN')
|
||||
expect($item.content()).toBe('type stuff')
|
||||
})
|
||||
})
|
||||
|
||||
describe('findOneByValue', () => {
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
describe('render', () => {
|
||||
it('renders a class component', async () => {
|
||||
const { node, component } = await tu.render(<Class />)
|
||||
|
||||
@ -23,6 +23,83 @@ export class TestContainer extends React.Component<{}> {
|
||||
}
|
||||
}
|
||||
|
||||
export class Selector {
|
||||
constructor(
|
||||
readonly element: Element = document.body,
|
||||
) {
|
||||
expect(this.element).toBeDefined()
|
||||
}
|
||||
|
||||
static findManyByQuery(root: Element, query: string): Selector[] {
|
||||
return Array
|
||||
.from(root.querySelectorAll(query))
|
||||
.map(el => new Selector(el))
|
||||
}
|
||||
|
||||
static findManyByQueryAndCondition(
|
||||
root: Element,
|
||||
query: string,
|
||||
verify: (selector: Selector) => boolean,
|
||||
): Selector[] {
|
||||
return this.findManyByQuery(root, query)
|
||||
.filter(verify)
|
||||
}
|
||||
|
||||
static findOneByQuery(root: Element, query: string): Selector {
|
||||
const result = this.findManyByQuery(root, query)
|
||||
expect(result.length).toBe(1)
|
||||
return result[0]
|
||||
}
|
||||
|
||||
static findOneByQueryAndCondition(
|
||||
root: Element,
|
||||
query: string,
|
||||
verify: (selector: Selector) => boolean,
|
||||
): Selector {
|
||||
const result = this.findManyByQueryAndCondition(root, query, verify)
|
||||
expect(result.length).toBe(1)
|
||||
return result[0]
|
||||
}
|
||||
|
||||
type(value: string) {
|
||||
T.Simulate.change(this.element, {
|
||||
target: {
|
||||
value,
|
||||
} as any,
|
||||
})
|
||||
}
|
||||
click() {
|
||||
T.Simulate.click(this.element)
|
||||
}
|
||||
submit() {
|
||||
T.Simulate.submit(this.element)
|
||||
}
|
||||
findOne(selector: string): Selector {
|
||||
return Selector.findOneByQuery(this.element, selector)
|
||||
}
|
||||
findOneByContent(selector: string, content: string): Selector {
|
||||
return Selector.findOneByQueryAndCondition(
|
||||
this.element, selector, sel => sel.content() === content)
|
||||
}
|
||||
findOneByValue(selector: string, value: string): Selector {
|
||||
return Selector.findOneByQueryAndCondition(
|
||||
this.element, selector, sel => sel.value() === value)
|
||||
}
|
||||
value(): string {
|
||||
return (this.element as HTMLInputElement).value
|
||||
}
|
||||
tag(): string {
|
||||
return this.element.tagName
|
||||
}
|
||||
content(): string | null {
|
||||
return this.element.textContent
|
||||
}
|
||||
}
|
||||
|
||||
export function select(element: Element): Selector {
|
||||
return new Selector(element)
|
||||
}
|
||||
|
||||
export class TestUtils {
|
||||
static defaultTheme?: DefaultTheme
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user