Skip to content

Commit

Permalink
refactor: refactor test setup (testing-library#856)
Browse files Browse the repository at this point in the history
  • Loading branch information
ph-fritsche authored Feb 20, 2022
1 parent bb5ca79 commit 892e6d5
Show file tree
Hide file tree
Showing 38 changed files with 898 additions and 899 deletions.
3 changes: 3 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,7 @@ config.testMatch.push('<rootDir>/tests/**/*.+(js|jsx|ts|tsx)')
// unless the file ends on `.test.{type}` so that we can add tests of our test utilities.
config.testPathIgnorePatterns.push('/_.*(?<!\\.test\\.[jt]sx?)$')

// Ignore declaration files
config.testPathIgnorePatterns.push('\\.d\\.ts$')

module.exports = config
2 changes: 1 addition & 1 deletion tests/_helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ expect.addSnapshotSerializer({
print: val => String((<null | {snapshot?: string}>val)?.snapshot),
})

export {setup} from './setup'
export {render, setup} from './setup'
export {addEventListener, addListeners} from './listeners'
14 changes: 13 additions & 1 deletion tests/_helpers/setup.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import {addListeners, EventHandlers} from './listeners'
import userEvent from '#src'
import {Options} from '#src/options'

export function setup<Elements extends Element | Element[] = HTMLElement>(
export function render<Elements extends Element | Element[] = HTMLElement>(
ui: string,
{
eventHandlers,
Expand Down Expand Up @@ -31,3 +33,13 @@ export function setup<Elements extends Element | Element[] = HTMLElement>(
),
}
}

export function setup<Elements extends Element | Element[] = HTMLElement>(
ui: string,
{eventHandlers, ...options}: Parameters<typeof render>[1] & Options = {},
) {
return {
user: userEvent.setup(options),
...render<Elements>(ui, {eventHandlers}),
}
}
109 changes: 43 additions & 66 deletions tests/clipboard/copy.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
import userEvent from '#src'
import {setup} from '#testHelpers'
import {render, setup} from '#testHelpers'

test('copy selected value', async () => {
const {element, getEvents} = setup<HTMLInputElement>(
const {element, getEvents, user} = setup<HTMLInputElement>(
`<input value="foo bar baz"/>`,
)
element.focus()
element.setSelectionRange(4, 7)

const dt = await userEvent.copy()
const dt = await user.copy()

expect(dt?.getData('text')).toBe('bar')
expect(getEvents('copy')).toHaveLength(1)

await expect(window.navigator.clipboard.readText()).resolves.toBe('bar')
})

test('copy selected text outside of editable', async () => {
const {element, getEvents} = setup(`<div tabindex="-1">foo bar baz</div>`)
const {element, getEvents, user} = setup(
`<div tabindex="-1">foo bar baz</div>`,
)
element.focus()
document
.getSelection()
Expand All @@ -26,14 +30,18 @@ test('copy selected text outside of editable', async () => {
5,
)

const dt = await userEvent.copy()
const dt = await user.copy()

expect(dt?.getData('text')).toBe('oo b')
expect(getEvents('copy')).toHaveLength(1)

await expect(window.navigator.clipboard.readText()).resolves.toBe('oo b')
})

test('copy selected text in contenteditable', async () => {
const {element, getEvents} = setup(`<div contenteditable>foo bar baz</div>`)
const {element, getEvents, user} = setup(
`<div contenteditable>foo bar baz</div>`,
)
element.focus()
document
.getSelection()
Expand All @@ -44,15 +52,36 @@ test('copy selected text in contenteditable', async () => {
5,
)

const dt = await userEvent.copy()
const dt = await user.copy()

expect(dt?.getData('text')).toBe('oo b')
expect(getEvents('copy')).toHaveLength(1)

await expect(window.navigator.clipboard.readText()).resolves.toBe('oo b')
})

describe('write to clipboard', () => {
test('without Clipboard API', async () => {
const {element} = setup<HTMLInputElement>(`<input value="foo bar baz"/>`)
test('copy on empty selection does nothing', async () => {
const {element, getEvents, clearEventCalls, user} = setup(`<input/>`)
element.focus()
await window.navigator.clipboard.writeText('foo')
clearEventCalls()

await user.copy()

await expect(window.navigator.clipboard.readText()).resolves.toBe('foo')
expect(getEvents()).toHaveLength(0)
})

describe('without Clipboard API', () => {
beforeEach(() => {
Object.defineProperty(window.navigator, 'clipboard', {
value: undefined,
configurable: true,
})
})

test('reject if trying to use missing API', async () => {
const {element} = render<HTMLInputElement>(`<input value="foo bar baz"/>`)
element.focus()
element.setSelectionRange(4, 7)

Expand All @@ -63,64 +92,12 @@ describe('write to clipboard', () => {
)
})

test('copy selected value', async () => {
const {element, getEvents} = setup<HTMLInputElement>(
`<input value="foo bar baz"/>`,
)
test('skip using missing API', async () => {
const {element} = render<HTMLInputElement>(`<input value="foo bar baz"/>`)
element.focus()
element.setSelectionRange(4, 7)

const dt = userEvent.setup().copy()

await expect(dt).resolves.toBeTruthy()
expect((await dt)?.getData('text')).toBe('bar')

await expect(window.navigator.clipboard.readText()).resolves.toBe('bar')

expect(getEvents('copy')).toHaveLength(1)
})

test('copy selected text outside of editable', async () => {
const {element, getEvents} = setup(`<div tabindex="-1">foo bar baz</div>`)
element.focus()
document
.getSelection()
?.setBaseAndExtent(
element.firstChild as Text,
1,
element.firstChild as Text,
5,
)

const dt = userEvent.setup().copy()

await expect(dt).resolves.toBeTruthy()
expect((await dt)?.getData('text')).toBe('oo b')

await expect(window.navigator.clipboard.readText()).resolves.toBe('oo b')

expect(getEvents('copy')).toHaveLength(1)
})

test('copy selected text in contenteditable', async () => {
const {element, getEvents} = setup(`<div contenteditable>foo bar baz</div>`)
element.focus()
document
.getSelection()
?.setBaseAndExtent(
element.firstChild as Text,
1,
element.firstChild as Text,
5,
)

const dt = userEvent.setup().copy()

await expect(dt).resolves.toBeTruthy()
expect((await dt)?.getData('text')).toBe('oo b')

await expect(window.navigator.clipboard.readText()).resolves.toBe('oo b')

expect(getEvents('copy')).toHaveLength(1)
const dt = await userEvent.copy()
expect(dt?.getData('text/plain')).toBe('bar')
})
})
114 changes: 43 additions & 71 deletions tests/clipboard/cut.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
import userEvent from '#src'
import {setup} from '#testHelpers'
import {render, setup} from '#testHelpers'

test('cut selected value', async () => {
const {element, getEvents} = setup<HTMLInputElement>(
const {element, getEvents, user} = setup<HTMLInputElement>(
`<input value="foo bar baz"/>`,
)
element.focus()
element.setSelectionRange(4, 7)

const dt = await userEvent.cut()
const dt = await user.cut()

expect(dt?.getData('text')).toBe('bar')
expect(getEvents('cut')).toHaveLength(1)
expect(getEvents('input')).toHaveLength(1)

await expect(window.navigator.clipboard.readText()).resolves.toBe('bar')
})

test('cut selected text outside of editable', async () => {
const {element, getEvents} = setup(`<div tabindex="-1">foo bar baz</div>`)
const {element, getEvents, user} = setup(
`<div tabindex="-1">foo bar baz</div>`,
)
element.focus()
document
.getSelection()
Expand All @@ -27,15 +31,19 @@ test('cut selected text outside of editable', async () => {
5,
)

const dt = await userEvent.cut()
const dt = await user.cut()

expect(dt?.getData('text')).toBe('oo b')
expect(getEvents('cut')).toHaveLength(1)
expect(getEvents('input')).toHaveLength(0)

await expect(window.navigator.clipboard.readText()).resolves.toBe('oo b')
})

test('cut selected text in contenteditable', async () => {
const {element, getEvents} = setup(`<div contenteditable>foo bar baz</div>`)
const {element, getEvents, user} = setup(
`<div contenteditable>foo bar baz</div>`,
)
element.focus()
document
.getSelection()
Expand All @@ -46,17 +54,38 @@ test('cut selected text in contenteditable', async () => {
5,
)

const dt = await userEvent.cut()
const dt = await user.cut()

expect(dt?.getData('text')).toBe('oo b')
expect(getEvents('cut')).toHaveLength(1)
expect(getEvents('input')).toHaveLength(1)
expect(element).toHaveTextContent('far baz')

await expect(window.navigator.clipboard.readText()).resolves.toBe('oo b')
})

describe('write to clipboard', () => {
test('without Clipboard API', async () => {
const {element} = setup<HTMLInputElement>(`<input value="foo bar baz"/>`)
test('cut on empty selection does nothing', async () => {
const {element, getEvents, clearEventCalls, user} = setup(`<input/>`)
element.focus()
await window.navigator.clipboard.writeText('foo')
clearEventCalls()

await user.cut()

await expect(window.navigator.clipboard.readText()).resolves.toBe('foo')
expect(getEvents()).toHaveLength(0)
})

describe('without Clipboard API', () => {
beforeEach(() => {
Object.defineProperty(window.navigator, 'clipboard', {
value: undefined,
configurable: true,
})
})

test('reject if trying to use missing API', async () => {
const {element} = render<HTMLInputElement>(`<input value="foo bar baz"/>`)
element.focus()
element.setSelectionRange(4, 7)

Expand All @@ -67,69 +96,12 @@ describe('write to clipboard', () => {
)
})

test('cut selected value', async () => {
const {element, getEvents} = setup<HTMLInputElement>(
`<input value="foo bar baz"/>`,
)
test('skip using missing API', async () => {
const {element} = render<HTMLInputElement>(`<input value="foo bar baz"/>`)
element.focus()
element.setSelectionRange(4, 7)

const dt = userEvent.setup().cut()

await expect(dt).resolves.toBeTruthy()
expect((await dt)?.getData('text')).toBe('bar')

await expect(window.navigator.clipboard.readText()).resolves.toBe('bar')

expect(getEvents('cut')).toHaveLength(1)
expect(getEvents('input')).toHaveLength(1)
expect(element).toHaveValue('foo baz')
})

test('cut selected text outside of editable', async () => {
const {element, getEvents} = setup(`<div tabindex="-1">foo bar baz</div>`)
element.focus()
document
.getSelection()
?.setBaseAndExtent(
element.firstChild as Text,
1,
element.firstChild as Text,
5,
)

const dt = userEvent.setup().cut()

await expect(dt).resolves.toBeTruthy()
expect((await dt)?.getData('text')).toBe('oo b')

await expect(window.navigator.clipboard.readText()).resolves.toBe('oo b')

expect(getEvents('cut')).toHaveLength(1)
expect(getEvents('input')).toHaveLength(0)
})

test('cut selected text in contenteditable', async () => {
const {element, getEvents} = setup(`<div contenteditable>foo bar baz</div>`)
element.focus()
document
.getSelection()
?.setBaseAndExtent(
element.firstChild as Text,
1,
element.firstChild as Text,
5,
)

const dt = userEvent.setup().cut()

await expect(dt).resolves.toBeTruthy()
expect((await dt)?.getData('text')).toBe('oo b')

await expect(window.navigator.clipboard.readText()).resolves.toBe('oo b')

expect(getEvents('cut')).toHaveLength(1)
expect(getEvents('input')).toHaveLength(1)
expect(element).toHaveTextContent('far baz')
const dt = await userEvent.cut()
expect(dt?.getData('text/plain')).toBe('bar')
})
})
Loading

0 comments on commit 892e6d5

Please sign in to comment.