Add Selector to react-test

This commit is contained in:
Jerko Steiner 2019-11-11 18:47:03 -03:00
parent adb3d877a4
commit e86c8b9226
2 changed files with 186 additions and 1 deletions

View File

@ -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 />)

View File

@ -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