Files
headlessui/packages/@headlessui-vue/src/test-utils/interactions.test.ts
T
Robin Malfait fdd2629795 Improve overal codebase, use modern tech like esbuild and TypeScript 4! (#1055)
* use esbuild for React instead of tsdx

* remove tsdx from Vue

* use consistent names

* add jest and prettier

* update scripts

* ignore some folders for prettier

* run lint script instead of tsdx lint

* run prettier en-masse

This has a few changes because of the new prettier version.

* bump typescript to latest version

* make typescript happy

* cleanup playground package.json

* make esbuild a dev dependency

* make scripts consistent

* fix husky hooks

* add dedicated watch script

* add `yarn playground-react` and `yarn react-playground` (alias)

This will make sure to run a watcher for the actual @headlessui/react
package, and start a development server in the playground-react package.

* ignore formatting in the .next folder

* run prettier on playground-react package

* setup playground-vue

Still not 100% working, but getting there!

* add playground aliases in @headlessui/vue and @headlessui/react

This allows you to run `yarn react playground` or `yarn vue playground`
from the root.

* add `clean` script

* move examples folder in playground-vue to root

* ensure new lines for consistency in scripts

* fix typescript issue

* fix typescript issues in playgrounds

* make sure to run prettier on everything it can

* run prettier on all files

* improve error output

If you minify the code, then it could happen that the errors are a bit
obscure. This will hardcode the component name to improve errors.

* add the `prettier-plugin-tailwindcss` plugin, party!

* update changelog
2022-01-27 17:07:38 +01:00

218 lines
6.1 KiB
TypeScript

import { render } from './vue-testing-library'
import { type, shift, Keys } from './interactions'
import { ComponentOptionsWithoutProps, defineComponent, h } from 'vue'
type Events = 'onKeydown' | 'onKeyup' | 'onKeypress' | 'onClick' | 'onBlur' | 'onFocus'
let events: Events[] = ['onKeydown', 'onKeyup', 'onKeypress', 'onClick', 'onBlur', 'onFocus']
function renderTemplate(input: string | ComponentOptionsWithoutProps) {
let defaultComponents = {}
if (typeof input === 'string') {
return render(defineComponent({ template: input, components: defaultComponents }))
}
return render(
defineComponent(
Object.assign({}, input, {
components: { ...defaultComponents, ...input.components },
}) as Parameters<typeof defineComponent>[0]
)
)
}
type Args = [
string | Partial<KeyboardEvent>,
(string | Partial<KeyboardEvent | MouseEvent>)[],
Set<Events>
]
function key(input: string | Partial<KeyboardEvent>): Partial<KeyboardEvent> {
if (typeof input === 'string') return { key: input }
return input
}
function event(
input: string | Partial<KeyboardEvent | MouseEvent>,
target?: string
): Partial<KeyboardEvent | MouseEvent> {
let e = typeof input === 'string' ? { type: input } : input
if (target) {
Object.defineProperty(e, 'target', {
configurable: false,
enumerable: true,
get() {
return document.getElementById(target!)
},
})
}
return e
}
describe('Keyboard', () => {
describe('type', () => {
it.each<Args>([
// Default - no cancellation
['a', ['keydown', 'keypress', 'keyup'], new Set()],
[Keys.Space, ['keydown', 'keypress', 'keyup', 'click'], new Set()],
[Keys.Enter, ['keydown', 'keypress', 'click', 'keyup'], new Set()],
[
Keys.Tab,
[
event('keydown', 'trigger'),
event('blur', 'trigger'),
event('focus', 'after'),
event('keyup', 'after'),
],
new Set(),
],
[
shift(Keys.Tab),
[
event('keydown', 'trigger'),
event('blur', 'trigger'),
event('focus', 'before'),
event('keyup', 'before'),
],
new Set(),
],
// Canceling keydown
['a', ['keydown', 'keyup'], new Set<Events>(['onKeydown'])],
[Keys.Space, ['keydown', 'keyup'], new Set<Events>(['onKeydown'])],
[Keys.Enter, ['keydown', 'keyup'], new Set<Events>(['onKeydown'])],
[Keys.Tab, ['keydown', 'keyup'], new Set<Events>(['onKeydown'])],
[shift(Keys.Tab), ['keydown', 'keyup'], new Set<Events>(['onKeydown'])],
// Canceling keypress
['a', ['keydown', 'keypress', 'keyup'], new Set<Events>(['onKeypress'])],
[Keys.Space, ['keydown', 'keypress', 'keyup', 'click'], new Set<Events>(['onKeypress'])],
[Keys.Enter, ['keydown', 'keypress', 'keyup'], new Set<Events>(['onKeypress'])],
[
Keys.Tab,
[
event('keydown', 'trigger'),
event('blur', 'trigger'),
event('focus', 'after'),
event('keyup', 'after'),
],
new Set<Events>(['onKeypress']),
],
[
shift(Keys.Tab),
[
event('keydown', 'trigger'),
event('blur', 'trigger'),
event('focus', 'before'),
event('keyup', 'before'),
],
new Set<Events>(['onKeypress']),
],
// Canceling keyup
['a', ['keydown', 'keypress', 'keyup'], new Set<Events>(['onKeyup'])],
[Keys.Space, ['keydown', 'keypress', 'keyup'], new Set<Events>(['onKeyup'])],
[Keys.Enter, ['keydown', 'keypress', 'click', 'keyup'], new Set<Events>(['onKeyup'])],
[
Keys.Tab,
[
event('keydown', 'trigger'),
event('blur', 'trigger'),
event('focus', 'after'),
event('keyup', 'after'),
],
new Set<Events>(['onKeyup']),
],
[
shift(Keys.Tab),
[
event('keydown', 'trigger'),
event('blur', 'trigger'),
event('focus', 'before'),
event('keyup', 'before'),
],
new Set<Events>(['onKeyup']),
],
// Cancelling blur
[
Keys.Tab,
[
event('keydown', 'trigger'),
event('blur', 'trigger'),
event('focus', 'after'),
event('keyup', 'after'),
],
new Set<Events>(['onBlur']),
],
[
shift(Keys.Tab),
[
event('keydown', 'trigger'),
event('blur', 'trigger'),
event('focus', 'before'),
event('keyup', 'before'),
],
new Set<Events>(['onBlur']),
],
])('should fire the correct events %#', async (input, result, prevents) => {
let fired: (KeyboardEvent | MouseEvent)[] = []
let state = { readyToCapture: false }
function createProps(id: string) {
return events.reduce<Record<string, string | ((event: any) => void)>>(
(props, name) => {
props[name] = (event: any) => {
if (!state.readyToCapture) return
if (prevents.has(name)) event.preventDefault()
fired.push(event)
}
return props
},
{ id }
)
}
renderTemplate({
template: `
<div>
<Button id="before">Before</Button>
<Button id="trigger">Trigger</Button>
<Button id="after">After</Button>
</div>
`,
components: {
Button: defineComponent({
setup(_props, { slots, attrs }) {
return () => {
return h('button', createProps(attrs.id as string), slots.default!())
}
},
}),
},
})
let trigger = document.getElementById('trigger')
trigger?.focus()
state.readyToCapture = true
await type([key(input)])
let expected = result.map((e) => event(e))
expect(fired.length).toEqual(result.length)
for (let [idx, event] of fired.entries()) {
for (let key in expected[idx]) {
let _key = key as keyof (KeyboardEvent | MouseEvent)
expect(event[_key]).toBe(expected[idx][_key])
}
}
})
})
})