Skip to content

Commit a07d3b8

Browse files
committed
refactor: clean up paths (#756)
* refactor: move utils * refactor: use bound APIs instead of imports * refactor: merge files for `type` * refactor: clean up file structure * refactor: clean up file structure * refactor: move tests and simplify imports * refactor: fix absolute import once again
1 parent e919184 commit a07d3b8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+239
-231
lines changed

.eslintrc.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
module.exports = {
22
extends: './node_modules/kcd-scripts/eslint.js',
3+
parser: '@typescript-eslint/parser',
34
settings: {
45
'import/resolver': {
5-
node: {
6-
extensions: ['.js', '.ts'],
7-
},
6+
typescript: {},
87
},
98
},
109
rules: {

jest.config.js

+17-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
11
const config = require('kcd-scripts/jest')
22

3-
module.exports = {
4-
...config,
5-
testEnvironment: 'jest-environment-jsdom',
3+
config.roots = ['<rootDir>']
64

7-
// this repo is testing utils
8-
testPathIgnorePatterns: config.testPathIgnorePatterns.filter(f => f !== '/__tests__/utils/'),
5+
config.moduleNameMapper = {
6+
'^#src$': '<rootDir>/src/index',
7+
'^#src/(.*)$': '<rootDir>/src/$1',
8+
'^#testHelpers/(.*)$': '<rootDir>/tests/_helpers/$1',
99
}
10+
11+
config.testEnvironment = 'jsdom'
12+
13+
config.setupFilesAfterEnv = ['<rootDir>/tests/_setup-env.js']
14+
15+
config.testMatch.push('<rootDir>/tests/**/*.+(js|jsx|ts|tsx)')
16+
17+
// Ignore files/dirs starting with an underscore (setup, helper, ...)
18+
// unless the file ends on `.test.{type}` so that we can add tests of our test utilities.
19+
config.testPathIgnorePatterns.push('/_.*(?<!\\.test\\.[jt]sx?)$')
20+
21+
module.exports = config

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"@types/estree": "0.0.45",
4747
"@types/jest-in-case": "^1.0.3",
4848
"@types/react": "^17.0.3",
49+
"eslint-import-resolver-typescript": "^2.5.0",
4950
"is-ci": "^2.0.0",
5051
"jest-in-case": "^1.0.2",
5152
"jest-serializer-ansi": "^1.0.3",

src/__tests__/react/keyboard.tsx

-21
This file was deleted.

src/clear.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import {isDisabled, isElementType} from './utils'
2-
import {type} from './type'
32
import type {UserEvent} from './setup'
43

54
export function clear(this: UserEvent, element: Element) {
@@ -24,7 +23,7 @@ export function clear(this: UserEvent, element: Element) {
2423
;(element as HTMLInputElement).type = 'text'
2524
}
2625

27-
void type.call(this, element, '{selectall}{del}', {
26+
this.type(element, '{selectall}{del}', {
2827
delay: 0,
2928
initialSelectionStart:
3029
element.selectionStart ?? /* istanbul ignore next */ undefined,

src/click.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import {hasPointerEvents, PointerOptions} from './utils'
2-
import {hover} from './hover'
32
import type {UserEvent} from './setup'
43

54
export declare interface clickOptions {
@@ -24,7 +23,7 @@ export function click(
2423
// istanbul ignore else
2524
if (!skipHover)
2625
// We just checked for `pointerEvents`. We can always skip this one in `hover`.
27-
hover.call(this, element, init, {skipPointerEventsCheck: true})
26+
this.hover(element, init, {skipPointerEventsCheck: true})
2827

2928
const keys =
3029
init?.button === 2 || init?.buttons === 2 ? '[MouseRight]' : '[MouseLeft]'
@@ -42,7 +41,7 @@ export function dblClick(
4241
'unable to double-click element as it has or inherits pointer-events set to "none".',
4342
)
4443
}
45-
hover.call(this, element, init, {skipPointerEventsCheck})
44+
this.hover(element, init, {skipPointerEventsCheck})
4645

4746
this.pointer({keys: '[MouseLeft][MouseLeft]', target: element})
4847
}

src/hover.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {createPointerState} from 'pointer'
1+
import {createPointerState} from './pointer'
22
import type {UserEvent} from './setup'
33
import {hasPointerEvents, PointerOptions} from './utils'
44

src/pointer/pointerPress.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
/* eslint-disable complexity */
22

33
import {fireEvent} from '@testing-library/dom'
4-
import {focus} from '../focus'
54
import {
65
Coords,
76
findClosest,
87
firePointerEvent,
8+
focus,
99
isDisabled,
1010
isFocusable,
1111
} from '../utils'

src/select-options.ts src/selectOptions.ts

+5-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import {createEvent, getConfig, fireEvent} from '@testing-library/dom'
22
import {
3+
focus,
34
hasPointerEvents,
45
isDisabled,
56
isElementType,
67
PointerOptions,
78
} from './utils'
8-
import {click} from './click'
9-
import {focus} from './focus'
10-
import {hover, unhover} from './hover'
119
import type {UserEvent} from './setup'
1210

1311
export function selectOptions(
@@ -110,7 +108,7 @@ function selectOptionsBase(
110108
: hasPointerEvents(select)
111109
// the click to open the select options
112110
if (withPointerEvents) {
113-
click.call(this, select, init, {skipPointerEventsCheck: true})
111+
this.click(select, init, {skipPointerEventsCheck: true})
114112
} else {
115113
focus(select)
116114
}
@@ -136,9 +134,9 @@ function selectOptionsBase(
136134
}
137135
} else if (select.getAttribute('role') === 'listbox') {
138136
selectedOptions.forEach(option => {
139-
hover.call(this, option, init, {skipPointerEventsCheck})
140-
click.call(this, option, init, {skipPointerEventsCheck})
141-
unhover.call(this, option, init, {skipPointerEventsCheck})
137+
this.hover(option, init, {skipPointerEventsCheck})
138+
this.click(option, init, {skipPointerEventsCheck})
139+
this.unhover(option, init, {skipPointerEventsCheck})
142140
})
143141
} else {
144142
throw getConfig().getElementError(

src/setup.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@ import type {keyboardState} from './keyboard/types'
77
import {paste} from './paste'
88
import {createPointerState, pointer} from './pointer'
99
import type {pointerOptions, pointerState} from './pointer/types'
10-
import {deselectOptions, selectOptions} from './select-options'
10+
import {deselectOptions, selectOptions} from './selectOptions'
1111
import {tab, tabOptions} from './tab'
12-
import {type} from './type'
13-
import {typeOptions} from './type/typeImplementation'
12+
import {type, typeOptions} from './type'
1413
import {upload, uploadOptions} from './upload'
1514
import {PointerOptions} from './utils'
1615

src/tab.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import {fireEvent} from '@testing-library/dom'
22
import {
3+
blur,
4+
focus,
35
getActiveElement,
46
FOCUSABLE_SELECTOR,
57
isVisible,
68
isDisabled,
79
isDocument,
810
} from './utils'
9-
import {focus} from './focus'
10-
import {blur} from './blur'
1111
import type {UserEvent} from './setup'
1212

1313
function getNextElement(

src/type/typeImplementation.ts src/type.ts

+44-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1+
import {getConfig as getDOMTestingLibraryConfig} from '@testing-library/dom'
2+
import {prepareDocument} from './document'
3+
import type {UserEvent} from './setup'
14
import {
25
setSelectionRange,
36
getSelectionRange,
47
getValue,
58
getActiveElement,
6-
} from '../utils'
7-
import {click} from '../click'
8-
import {keyboardImplementationWrapper} from '../keyboard'
9-
import {UserEvent} from '../setup'
9+
} from './utils'
10+
import {keyboardImplementationWrapper} from './keyboard'
1011

1112
export interface typeOptions {
1213
delay?: number
@@ -16,10 +17,47 @@ export interface typeOptions {
1617
initialSelectionEnd?: number
1718
}
1819

19-
export async function typeImplementation(
20+
export function type(
2021
this: UserEvent,
2122
element: Element,
2223
text: string,
24+
options?: typeOptions & {delay?: 0},
25+
): void
26+
export function type(
27+
this: UserEvent,
28+
element: Element,
29+
text: string,
30+
options: typeOptions & {delay: number},
31+
): Promise<void>
32+
// this needs to be wrapped in the event/asyncWrapper for React's act and angular's change detection
33+
// depending on whether it will be async.
34+
export function type(
35+
this: UserEvent,
36+
element: Element,
37+
text: string,
38+
{delay = 0, ...options}: typeOptions = {},
39+
): Promise<void> | void {
40+
prepareDocument(element.ownerDocument)
41+
42+
// we do not want to wrap in the asyncWrapper if we're not
43+
// going to actually be doing anything async, so we only wrap
44+
// if the delay is greater than 0
45+
46+
if (delay > 0) {
47+
return getDOMTestingLibraryConfig().asyncWrapper(() =>
48+
typeImplementation(this, element, text, {delay, ...options}),
49+
)
50+
} else {
51+
return void typeImplementation(this, element, text, {delay, ...options})
52+
// prevents users from dealing with UnhandledPromiseRejectionWarning
53+
.catch(console.error)
54+
}
55+
}
56+
57+
async function typeImplementation(
58+
userEvent: UserEvent,
59+
element: Element,
60+
text: string,
2361
{
2462
delay,
2563
skipClick = false,
@@ -32,7 +70,7 @@ export async function typeImplementation(
3270
// we use this workaround for now to prevent changing behavior
3371
if ((element as {disabled?: boolean}).disabled) return
3472

35-
if (!skipClick) click.call(this, element)
73+
if (!skipClick) userEvent.click(element)
3674

3775
// The focused element could change between each event, so get the currently active element each time
3876
const currentElement = () => getActiveElement(element.ownerDocument)

src/type/index.ts

-42
This file was deleted.

src/upload.ts

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
import {fireEvent, createEvent} from '@testing-library/dom'
2-
import {click} from './click'
3-
import {blur} from './blur'
4-
import {focus} from './focus'
5-
import {isDisabled, isElementType} from './utils'
2+
import {blur, focus, isDisabled, isElementType} from './utils'
63
import type {UserEvent} from './setup'
74

85
interface uploadInit {
@@ -32,7 +29,7 @@ export function upload(
3229
}
3330
if (isDisabled(element)) return
3431

35-
click.call(this, element, init?.clickInit)
32+
this.click(element, init?.clickInit)
3633

3734
const files = (Array.isArray(fileOrFiles) ? fileOrFiles : [fileOrFiles])
3835
.filter(file => !applyAccept || isAcceptableFile(file, input.accept))

src/blur.ts src/utils/focus/blur.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import {getActiveElement, isFocusable, eventWrapper} from './utils'
1+
import {eventWrapper} from '../misc/eventWrapper'
2+
import {getActiveElement} from './getActiveElement'
3+
import {isFocusable} from './isFocusable'
24

35
function blur(element: Element) {
46
if (!isFocusable(element)) return

src/focus.ts src/utils/focus/focus.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import {getActiveElement, isFocusable, eventWrapper} from './utils'
1+
import {eventWrapper} from '../misc/eventWrapper'
2+
import {getActiveElement} from './getActiveElement'
3+
import {isFocusable} from './isFocusable'
24

35
function focus(element: Element) {
46
if (!isFocusable(element)) return

src/utils/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ export * from './edit/isValidInputTimeValue'
1212
export * from './edit/maxLength'
1313
export * from './edit/selectionRange'
1414

15+
export * from './focus/blur'
16+
export * from './focus/focus'
1517
export * from './focus/getActiveElement'
1618
export * from './focus/isFocusable'
1719
export * from './focus/selector'
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

src/__tests__/helpers/utils.ts tests/_helpers/utils.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable testing-library/no-node-access */
22
import {eventMap} from '@testing-library/dom/dist/event-map'
3-
import {isElementType} from '../../utils'
3+
import {isElementType} from '#src/utils'
44
// this is pretty helpful:
55
// https://codesandbox.io/s/quizzical-worker-eo909
66

File renamed without changes.

src/__tests__/clear.js tests/clear.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import userEvent from '../'
2-
import {setup} from './helpers/utils'
1+
import userEvent from '#src'
2+
import {setup} from '#testHelpers/utils'
33

44
test('clears text', () => {
55
const {element, getEventSnapshot} = setup('<input value="hello" />')

src/__tests__/click.js tests/click/click.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import userEvent from '../'
2-
import {setup, addEventListener, addListeners} from './helpers/utils'
1+
import userEvent from '#src'
2+
import {setup, addEventListener, addListeners} from '#testHelpers/utils'
33

44
test('click in button', () => {
55
const {element, getEventSnapshot} = setup('<button />')

src/__tests__/dblclick.js tests/click/dblclick.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import userEvent from '../'
2-
import {setup, addEventListener, addListeners} from './helpers/utils'
1+
import userEvent from '#src'
2+
import {setup, addEventListener, addListeners} from '#testHelpers/utils'
33

44
test('fires the correct events on buttons', () => {
55
const {element, getEventSnapshot} = setup('<button />')

0 commit comments

Comments
 (0)