From b6d0e2cf148fc76ac6e436847c44415345858316 Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Tue, 9 Jun 2020 16:46:37 +0200 Subject: [PATCH 01/16] Proposal setup to make the TypeScript migration easier --- babel.config.js | 3 +++ package.json | 6 ++++-- src/{get-node-text.js => get-node-text.ts} | 4 ++-- tests/jest.config.dom.js | 6 ++++++ tests/jest.config.node.js | 6 ++++++ tsconfig.json | 9 +++++++++ types/get-node-text.d.ts | 3 ++- 7 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 babel.config.js rename src/{get-node-text.js => get-node-text.ts} (81%) create mode 100644 tsconfig.json diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 00000000..75d21715 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: ['kcd-scripts/babel', '@babel/preset-typescript'], +} diff --git a/package.json b/package.json index e41e26bb..4b82c6c7 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "test:debug": "node --inspect-brk ./node_modules/.bin/jest --watch --runInBand", "test:update": "npm test -- --updateSnapshot --coverage", "validate": "kcd-scripts validate", + "generate-types": "tsc", "typecheck": "dtslint ./types/" }, "files": [ @@ -44,13 +45,14 @@ "pretty-format": "^25.5.0" }, "devDependencies": { - "dtslint": "^3.6.9", "@testing-library/jest-dom": "^5.9.0", + "dtslint": "^3.6.9", "jest-in-case": "^1.0.2", "jest-serializer-ansi": "^1.0.3", "jest-watch-select-projects": "^2.0.0", "jsdom": "^16.2.2", - "kcd-scripts": "^6.2.0" + "kcd-scripts": "^6.2.0", + "typescript": "^3.9.5" }, "eslintConfig": { "extends": "./node_modules/kcd-scripts/eslint.js", diff --git a/src/get-node-text.js b/src/get-node-text.ts similarity index 81% rename from src/get-node-text.js rename to src/get-node-text.ts index 28b7d3d8..be7f7ef8 100644 --- a/src/get-node-text.js +++ b/src/get-node-text.ts @@ -2,9 +2,9 @@ // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType#Node_type_constants const TEXT_NODE = 3 -function getNodeText(node) { +function getNodeText(node: HTMLElement): string { if (node.matches('input[type=submit], input[type=button]')) { - return node.value + return (node as HTMLInputElement).value } return Array.from(node.childNodes) diff --git a/tests/jest.config.dom.js b/tests/jest.config.dom.js index 72b3b24b..7385fb4e 100644 --- a/tests/jest.config.dom.js +++ b/tests/jest.config.dom.js @@ -11,4 +11,10 @@ module.exports = { '/__node_tests__/', ], testEnvironment: 'jest-environment-jsdom', + transform: { + '^.+\\.(js|jsx|ts|tsx)$': path.join( + __dirname, + '../node_modules/kcd-scripts/dist/config/babel-transform', + ), + }, } diff --git a/tests/jest.config.node.js b/tests/jest.config.node.js index bf37b60b..e3325db9 100644 --- a/tests/jest.config.node.js +++ b/tests/jest.config.node.js @@ -12,4 +12,10 @@ module.exports = { '/__node_tests__/', ], testMatch: ['**/__node_tests__/**.js'], + transform: { + '^.+\\.(js|jsx|ts|tsx)$': path.join( + __dirname, + '../node_modules/kcd-scripts/dist/config/babel-transform', + ), + }, } diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..a968ea95 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "outDir": "./types/", + "allowJs": true, + "declaration": true, + "emitDeclarationOnly": true + }, + "include": ["./src/**/*.ts"] +} diff --git a/types/get-node-text.d.ts b/types/get-node-text.d.ts index 5c5654b5..dd40d013 100644 --- a/types/get-node-text.d.ts +++ b/types/get-node-text.d.ts @@ -1 +1,2 @@ -export function getNodeText(node: HTMLElement): string; +declare function getNodeText(node: HTMLElement): string; +export { getNodeText }; From f11ac62afee95cc9f9f7c213896c950674407c20 Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Tue, 9 Jun 2020 17:34:56 +0200 Subject: [PATCH 02/16] Fix lint (will need a proper eslint settings for TS) --- package.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/package.json b/package.json index 4b82c6c7..a456becf 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "@babel/runtime": "^7.10.2", "aria-query": "^4.0.2", "dom-accessibility-api": "^0.4.5", + "eslint-import-resolver-typescript": "^2.0.0", "pretty-format": "^25.5.0" }, "devDependencies": { @@ -61,6 +62,11 @@ "import/no-unassigned-import": "off", "import/no-useless-path-segments": "off", "no-console": "off" + }, + "settings": { + "import/resolver": { + "typescript": {} + } } }, "eslintIgnore": [ From 53cb86d71598a57893a999812b027bf9155df445 Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Tue, 9 Jun 2020 22:21:22 +0200 Subject: [PATCH 03/16] Migrate event-map.js and matches.js Disable some tslint rules which conflicts with the declarations generated by tsc Also remove the useless babel.config.js --- babel.config.js | 3 - src/event-map.js | 350 ------------------------------ src/event-map.ts | 375 +++++++++++++++++++++++++++++++++ src/{matches.js => matches.ts} | 43 +++- types/event-map.d.ts | 72 +++++++ types/matches.d.ts | 54 +++-- types/tslint.json | 4 +- 7 files changed, 527 insertions(+), 374 deletions(-) delete mode 100644 babel.config.js delete mode 100644 src/event-map.js create mode 100644 src/event-map.ts rename src/{matches.js => matches.ts} (67%) create mode 100644 types/event-map.d.ts diff --git a/babel.config.js b/babel.config.js deleted file mode 100644 index 75d21715..00000000 --- a/babel.config.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - presets: ['kcd-scripts/babel', '@babel/preset-typescript'], -} diff --git a/src/event-map.js b/src/event-map.js deleted file mode 100644 index 98d78e66..00000000 --- a/src/event-map.js +++ /dev/null @@ -1,350 +0,0 @@ -export const eventMap = { - // Clipboard Events - copy: { - EventType: 'ClipboardEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - cut: { - EventType: 'ClipboardEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - paste: { - EventType: 'ClipboardEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - // Composition Events - compositionEnd: { - EventType: 'CompositionEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - compositionStart: { - EventType: 'CompositionEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - compositionUpdate: { - EventType: 'CompositionEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - // Keyboard Events - keyDown: { - EventType: 'KeyboardEvent', - defaultInit: {bubbles: true, cancelable: true, charCode: 0, composed: true}, - }, - keyPress: { - EventType: 'KeyboardEvent', - defaultInit: {bubbles: true, cancelable: true, charCode: 0, composed: true}, - }, - keyUp: { - EventType: 'KeyboardEvent', - defaultInit: {bubbles: true, cancelable: true, charCode: 0, composed: true}, - }, - // Focus Events - focus: { - EventType: 'FocusEvent', - defaultInit: {bubbles: false, cancelable: false, composed: true}, - }, - blur: { - EventType: 'FocusEvent', - defaultInit: {bubbles: false, cancelable: false, composed: true}, - }, - focusIn: { - EventType: 'FocusEvent', - defaultInit: {bubbles: true, cancelable: false, composed: true}, - }, - focusOut: { - EventType: 'FocusEvent', - defaultInit: {bubbles: true, cancelable: false, composed: true}, - }, - // Form Events - change: { - EventType: 'Event', - defaultInit: {bubbles: true, cancelable: false}, - }, - input: { - EventType: 'InputEvent', - defaultInit: {bubbles: true, cancelable: false, composed: true}, - }, - invalid: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: true}, - }, - submit: { - EventType: 'Event', - defaultInit: {bubbles: true, cancelable: true}, - }, - reset: { - EventType: 'Event', - defaultInit: {bubbles: true, cancelable: true}, - }, - // Mouse Events - click: { - EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true, button: 0, composed: true}, - }, - contextMenu: { - EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - dblClick: { - EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - drag: { - EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - dragEnd: { - EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: false, composed: true}, - }, - dragEnter: { - EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - dragExit: { - EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: false, composed: true}, - }, - dragLeave: { - EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: false, composed: true}, - }, - dragOver: { - EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - dragStart: { - EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - drop: { - EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - mouseDown: { - EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - mouseEnter: { - EventType: 'MouseEvent', - defaultInit: {bubbles: false, cancelable: false, composed: true}, - }, - mouseLeave: { - EventType: 'MouseEvent', - defaultInit: {bubbles: false, cancelable: false, composed: true}, - }, - mouseMove: { - EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - mouseOut: { - EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - mouseOver: { - EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - mouseUp: { - EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - // Selection Events - select: { - EventType: 'Event', - defaultInit: {bubbles: true, cancelable: false}, - }, - // Touch Events - touchCancel: { - EventType: 'TouchEvent', - defaultInit: {bubbles: true, cancelable: false, composed: true}, - }, - touchEnd: { - EventType: 'TouchEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - touchMove: { - EventType: 'TouchEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - touchStart: { - EventType: 'TouchEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - // UI Events - scroll: { - EventType: 'UIEvent', - defaultInit: {bubbles: false, cancelable: false}, - }, - // Wheel Events - wheel: { - EventType: 'WheelEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - // Media Events - abort: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - canPlay: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - canPlayThrough: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - durationChange: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - emptied: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - encrypted: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - ended: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - loadedData: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - loadedMetadata: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - loadStart: { - EventType: 'ProgressEvent', - defaultInit: {bubbles: false, cancelable: false}, - }, - pause: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - play: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - playing: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - progress: { - EventType: 'ProgressEvent', - defaultInit: {bubbles: false, cancelable: false}, - }, - rateChange: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - seeked: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - seeking: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - stalled: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - suspend: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - timeUpdate: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - volumeChange: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - waiting: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - // Image Events - load: { - EventType: 'UIEvent', - defaultInit: {bubbles: false, cancelable: false}, - }, - error: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - // Animation Events - animationStart: { - EventType: 'AnimationEvent', - defaultInit: {bubbles: true, cancelable: false}, - }, - animationEnd: { - EventType: 'AnimationEvent', - defaultInit: {bubbles: true, cancelable: false}, - }, - animationIteration: { - EventType: 'AnimationEvent', - defaultInit: {bubbles: true, cancelable: false}, - }, - // Transition Events - transitionEnd: { - EventType: 'TransitionEvent', - defaultInit: {bubbles: true, cancelable: true}, - }, - // pointer events - pointerOver: { - EventType: 'PointerEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - pointerEnter: { - EventType: 'PointerEvent', - defaultInit: {bubbles: false, cancelable: false}, - }, - pointerDown: { - EventType: 'PointerEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - pointerMove: { - EventType: 'PointerEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - pointerUp: { - EventType: 'PointerEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - pointerCancel: { - EventType: 'PointerEvent', - defaultInit: {bubbles: true, cancelable: false, composed: true}, - }, - pointerOut: { - EventType: 'PointerEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - pointerLeave: { - EventType: 'PointerEvent', - defaultInit: {bubbles: false, cancelable: false}, - }, - gotPointerCapture: { - EventType: 'PointerEvent', - defaultInit: {bubbles: false, cancelable: false, composed: true}, - }, - lostPointerCapture: { - EventType: 'PointerEvent', - defaultInit: {bubbles: false, cancelable: false, composed: true}, - }, - // history events - popState: { - EventType: 'PopStateEvent', - defaultInit: {bubbles: true, cancelable: false}, - }, - } - - export const eventAliasMap = { - doubleClick: 'dblClick', - } diff --git a/src/event-map.ts b/src/event-map.ts new file mode 100644 index 00000000..9ca36b90 --- /dev/null +++ b/src/event-map.ts @@ -0,0 +1,375 @@ +type EventMapKey = string + +type LegacyKeyboardEventInit = { + // lib.dom.ts marks 'charCode' as deprecated in KeyboardEvent and does not include it in KeyboardEventInit + charCode?: number +} & KeyboardEventInit + +type EventMapValue = + | {EventType: 'AnimationEvent'; defaultInit: AnimationEventInit} + | {EventType: 'ClipboardEvent'; defaultInit: ClipboardEventInit} + | {EventType: 'CompositionEvent'; defaultInit: CompositionEventInit} + | {EventType: 'DragEvent'; defaultInit: DragEventInit} + | {EventType: 'Event'; defaultInit: EventInit} + | {EventType: 'FocusEvent'; defaultInit: FocusEventInit} + | {EventType: 'KeyboardEvent'; defaultInit: LegacyKeyboardEventInit} + | {EventType: 'InputEvent'; defaultInit: InputEventInit} + | {EventType: 'MouseEvent'; defaultInit: MouseEventInit} + | {EventType: 'PointerEvent'; defaultInit: PointerEventInit} + | {EventType: 'PopStateEvent'; defaultInit: PopStateEventInit} + | {EventType: 'ProgressEvent'; defaultInit: ProgressEventInit} + | {EventType: 'TouchEvent'; defaultInit: TouchEventInit} + | {EventType: 'TransitionEvent'; defaultInit: TransitionEventInit} + | {EventType: 'UIEvent'; defaultInit: UIEventInit} + | {EventType: 'WheelEvent'; defaultInit: WheelEventInit} + +export const eventMap: Record = { + // Clipboard Events + copy: { + EventType: 'ClipboardEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + cut: { + EventType: 'ClipboardEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + paste: { + EventType: 'ClipboardEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + // Composition Events + compositionEnd: { + EventType: 'CompositionEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + compositionStart: { + EventType: 'CompositionEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + compositionUpdate: { + EventType: 'CompositionEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + // Keyboard Events + keyDown: { + EventType: 'KeyboardEvent', + defaultInit: {bubbles: true, cancelable: true, charCode: 0, composed: true}, + }, + keyPress: { + EventType: 'KeyboardEvent', + defaultInit: {bubbles: true, cancelable: true, charCode: 0, composed: true}, + }, + keyUp: { + EventType: 'KeyboardEvent', + defaultInit: {bubbles: true, cancelable: true, charCode: 0, composed: true}, + }, + // Focus Events + focus: { + EventType: 'FocusEvent', + defaultInit: {bubbles: false, cancelable: false, composed: true}, + }, + blur: { + EventType: 'FocusEvent', + defaultInit: {bubbles: false, cancelable: false, composed: true}, + }, + focusIn: { + EventType: 'FocusEvent', + defaultInit: {bubbles: true, cancelable: false, composed: true}, + }, + focusOut: { + EventType: 'FocusEvent', + defaultInit: {bubbles: true, cancelable: false, composed: true}, + }, + // Form Events + change: { + EventType: 'Event', + defaultInit: {bubbles: true, cancelable: false}, + }, + input: { + EventType: 'InputEvent', + defaultInit: {bubbles: true, cancelable: false, composed: true}, + }, + invalid: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: true}, + }, + submit: { + EventType: 'Event', + defaultInit: {bubbles: true, cancelable: true}, + }, + reset: { + EventType: 'Event', + defaultInit: {bubbles: true, cancelable: true}, + }, + // Mouse Events + click: { + EventType: 'MouseEvent', + defaultInit: {bubbles: true, cancelable: true, button: 0, composed: true}, + }, + contextMenu: { + EventType: 'MouseEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + dblClick: { + EventType: 'MouseEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + drag: { + EventType: 'DragEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + dragEnd: { + EventType: 'DragEvent', + defaultInit: {bubbles: true, cancelable: false, composed: true}, + }, + dragEnter: { + EventType: 'DragEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + dragExit: { + EventType: 'DragEvent', + defaultInit: {bubbles: true, cancelable: false, composed: true}, + }, + dragLeave: { + EventType: 'DragEvent', + defaultInit: {bubbles: true, cancelable: false, composed: true}, + }, + dragOver: { + EventType: 'DragEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + dragStart: { + EventType: 'DragEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + drop: { + EventType: 'DragEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + mouseDown: { + EventType: 'MouseEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + mouseEnter: { + EventType: 'MouseEvent', + defaultInit: {bubbles: false, cancelable: false, composed: true}, + }, + mouseLeave: { + EventType: 'MouseEvent', + defaultInit: {bubbles: false, cancelable: false, composed: true}, + }, + mouseMove: { + EventType: 'MouseEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + mouseOut: { + EventType: 'MouseEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + mouseOver: { + EventType: 'MouseEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + mouseUp: { + EventType: 'MouseEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + // Selection Events + select: { + EventType: 'Event', + defaultInit: {bubbles: true, cancelable: false}, + }, + // Touch Events + touchCancel: { + EventType: 'TouchEvent', + defaultInit: {bubbles: true, cancelable: false, composed: true}, + }, + touchEnd: { + EventType: 'TouchEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + touchMove: { + EventType: 'TouchEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + touchStart: { + EventType: 'TouchEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + // UI Events + scroll: { + EventType: 'UIEvent', + defaultInit: {bubbles: false, cancelable: false}, + }, + // Wheel Events + wheel: { + EventType: 'WheelEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + // Media Events + abort: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + canPlay: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + canPlayThrough: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + durationChange: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + emptied: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + encrypted: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + ended: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + loadedData: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + loadedMetadata: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + loadStart: { + EventType: 'ProgressEvent', + defaultInit: {bubbles: false, cancelable: false}, + }, + pause: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + play: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + playing: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + progress: { + EventType: 'ProgressEvent', + defaultInit: {bubbles: false, cancelable: false}, + }, + rateChange: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + seeked: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + seeking: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + stalled: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + suspend: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + timeUpdate: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + volumeChange: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + waiting: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + // Image Events + load: { + EventType: 'UIEvent', + defaultInit: {bubbles: false, cancelable: false}, + }, + error: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + // Animation Events + animationStart: { + EventType: 'AnimationEvent', + defaultInit: {bubbles: true, cancelable: false}, + }, + animationEnd: { + EventType: 'AnimationEvent', + defaultInit: {bubbles: true, cancelable: false}, + }, + animationIteration: { + EventType: 'AnimationEvent', + defaultInit: {bubbles: true, cancelable: false}, + }, + // Transition Events + transitionEnd: { + EventType: 'TransitionEvent', + defaultInit: {bubbles: true, cancelable: true}, + }, + // pointer events + pointerOver: { + EventType: 'PointerEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + pointerEnter: { + EventType: 'PointerEvent', + defaultInit: {bubbles: false, cancelable: false}, + }, + pointerDown: { + EventType: 'PointerEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + pointerMove: { + EventType: 'PointerEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + pointerUp: { + EventType: 'PointerEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + pointerCancel: { + EventType: 'PointerEvent', + defaultInit: {bubbles: true, cancelable: false, composed: true}, + }, + pointerOut: { + EventType: 'PointerEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + pointerLeave: { + EventType: 'PointerEvent', + defaultInit: {bubbles: false, cancelable: false}, + }, + gotPointerCapture: { + EventType: 'PointerEvent', + defaultInit: {bubbles: false, cancelable: false, composed: true}, + }, + lostPointerCapture: { + EventType: 'PointerEvent', + defaultInit: {bubbles: false, cancelable: false, composed: true}, + }, + // history events + popState: { + EventType: 'PopStateEvent', + defaultInit: {bubbles: true, cancelable: false}, + }, +} + +export const eventAliasMap: Record = { + doubleClick: 'dblClick', +} diff --git a/src/matches.js b/src/matches.ts similarity index 67% rename from src/matches.js rename to src/matches.ts index 3241e680..e135b42c 100644 --- a/src/matches.js +++ b/src/matches.ts @@ -1,4 +1,26 @@ -function fuzzyMatches(textToMatch, node, matcher, normalizer) { +export type MatcherFunction = (content: string, element: HTMLElement) => boolean + +export type Matcher = string | RegExp | MatcherFunction + +export type NormalizerFn = (text: string) => string + +export interface MatcherOptions { + exact?: boolean + /** Use normalizer with getDefaultNormalizer instead */ + trim?: boolean + /** Use normalizer with getDefaultNormalizer instead */ + collapseWhitespace?: boolean + normalizer?: NormalizerFn + /** suppress suggestions for a specific query */ + suggest?: boolean +} + +function fuzzyMatches( + textToMatch: string, + node: HTMLElement | null, + matcher: Matcher, + normalizer: NormalizerFn, +) { if (typeof textToMatch !== 'string') { return false } @@ -13,7 +35,12 @@ function fuzzyMatches(textToMatch, node, matcher, normalizer) { } } -function matches(textToMatch, node, matcher, normalizer) { +function matches( + textToMatch: string, + node: HTMLElement | null, + matcher: Matcher, + normalizer: NormalizerFn, +) { if (typeof textToMatch !== 'string') { return false } @@ -28,7 +55,15 @@ function matches(textToMatch, node, matcher, normalizer) { } } -function getDefaultNormalizer({trim = true, collapseWhitespace = true} = {}) { +export interface DefaultNormalizerOptions { + trim?: boolean + collapseWhitespace?: boolean +} + +function getDefaultNormalizer({ + trim = true, + collapseWhitespace = true, +}: DefaultNormalizerOptions = {}): NormalizerFn { return text => { let normalizedText = text normalizedText = trim ? normalizedText.trim() : normalizedText @@ -48,7 +83,7 @@ function getDefaultNormalizer({trim = true, collapseWhitespace = true} = {}) { * @param {Function|undefined} normalizer The user-specified normalizer * @returns {Function} A normalizer */ -function makeNormalizer({trim, collapseWhitespace, normalizer}) { +function makeNormalizer({trim, collapseWhitespace, normalizer}): NormalizerFn { if (normalizer) { // User has specified a custom normalizer if ( diff --git a/types/event-map.d.ts b/types/event-map.d.ts new file mode 100644 index 00000000..d9ea5eef --- /dev/null +++ b/types/event-map.d.ts @@ -0,0 +1,72 @@ +declare type EventMapKey = string +declare type LegacyKeyboardEventInit = { + charCode?: number +} & KeyboardEventInit +declare type EventMapValue = + | { + EventType: 'AnimationEvent' + defaultInit: AnimationEventInit + } + | { + EventType: 'ClipboardEvent' + defaultInit: ClipboardEventInit + } + | { + EventType: 'CompositionEvent' + defaultInit: CompositionEventInit + } + | { + EventType: 'DragEvent' + defaultInit: DragEventInit + } + | { + EventType: 'Event' + defaultInit: EventInit + } + | { + EventType: 'FocusEvent' + defaultInit: FocusEventInit + } + | { + EventType: 'KeyboardEvent' + defaultInit: LegacyKeyboardEventInit + } + | { + EventType: 'InputEvent' + defaultInit: InputEventInit + } + | { + EventType: 'MouseEvent' + defaultInit: MouseEventInit + } + | { + EventType: 'PointerEvent' + defaultInit: PointerEventInit + } + | { + EventType: 'PopStateEvent' + defaultInit: PopStateEventInit + } + | { + EventType: 'ProgressEvent' + defaultInit: ProgressEventInit + } + | { + EventType: 'TouchEvent' + defaultInit: TouchEventInit + } + | { + EventType: 'TransitionEvent' + defaultInit: TransitionEventInit + } + | { + EventType: 'UIEvent' + defaultInit: UIEventInit + } + | { + EventType: 'WheelEvent' + defaultInit: WheelEventInit + } +export declare const eventMap: Record +export declare const eventAliasMap: Record +export {} diff --git a/types/matches.d.ts b/types/matches.d.ts index 6454c86a..4200b734 100644 --- a/types/matches.d.ts +++ b/types/matches.d.ts @@ -1,8 +1,9 @@ -export type MatcherFunction = (content: string, element: HTMLElement) => boolean -export type Matcher = string | RegExp | MatcherFunction - -export type NormalizerFn = (text: string) => string - +export declare type MatcherFunction = ( + content: string, + element: HTMLElement, +) => boolean +export declare type Matcher = string | RegExp | MatcherFunction +export declare type NormalizerFn = (text: string) => string export interface MatcherOptions { exact?: boolean /** Use normalizer with getDefaultNormalizer instead */ @@ -13,21 +14,42 @@ export interface MatcherOptions { /** suppress suggestions for a specific query */ suggest?: boolean } - -export type Match = ( +declare function fuzzyMatches( textToMatch: string, node: HTMLElement | null, matcher: Matcher, - options?: MatcherOptions, -) => boolean - + normalizer: NormalizerFn, +): boolean +declare function matches( + textToMatch: string, + node: HTMLElement | null, + matcher: Matcher, + normalizer: NormalizerFn, +): boolean export interface DefaultNormalizerOptions { trim?: boolean collapseWhitespace?: boolean } - -export function getDefaultNormalizer( - options?: DefaultNormalizerOptions, -): NormalizerFn - -// N.B. Don't expose fuzzyMatches + matches here: they're not public API +declare function getDefaultNormalizer({ + trim, + collapseWhitespace, +}?: DefaultNormalizerOptions): NormalizerFn +/** + * Constructs a normalizer to pass to functions in matches.js + * @param {boolean|undefined} trim The user-specified value for `trim`, without + * any defaulting having been applied + * @param {boolean|undefined} collapseWhitespace The user-specified value for + * `collapseWhitespace`, without any defaulting having been applied + * @param {Function|undefined} normalizer The user-specified normalizer + * @returns {Function} A normalizer + */ +declare function makeNormalizer({ + trim, + collapseWhitespace, + normalizer, +}: { + trim: any + collapseWhitespace: any + normalizer: any +}): NormalizerFn +export {fuzzyMatches, matches, getDefaultNormalizer, makeNormalizer} diff --git a/types/tslint.json b/types/tslint.json index 5d45232f..a3f71e09 100644 --- a/types/tslint.json +++ b/types/tslint.json @@ -1,8 +1,10 @@ { "extends": ["dtslint/dtslint.json"], "rules": { + "no-redundant-jsdoc": false, "no-useless-files": false, "no-relative-import-in-test": false, - "semicolon": false + "semicolon": false, + "strict-export-declare-modifiers": false } } From 65ef08094cd603b3c761ef74286c9f2d6b69a129 Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Wed, 10 Jun 2020 18:28:41 +0200 Subject: [PATCH 04/16] Add the 'types' directory into .prettierignore It seems the prettier settings can conflit with the 'whitespace' rule of dtslint. Also forces the dtslint version to be sure Travis use a version with this fix: https://github.com/microsoft/dtslint/pull/295 --- .prettierignore | 1 + package.json | 2 +- tests/jest.config.dom.js | 6 -- tests/jest.config.node.js | 6 -- types/event-map.d.ts | 126 +++++++++++++++++--------------------- types/matches.d.ts | 64 +++++++------------ 6 files changed, 79 insertions(+), 126 deletions(-) diff --git a/.prettierignore b/.prettierignore index 9c628283..e09c4562 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,4 @@ node_modules coverage dist +types diff --git a/package.json b/package.json index a456becf..3c75817c 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ }, "devDependencies": { "@testing-library/jest-dom": "^5.9.0", - "dtslint": "^3.6.9", + "dtslint": "^3.6.11", "jest-in-case": "^1.0.2", "jest-serializer-ansi": "^1.0.3", "jest-watch-select-projects": "^2.0.0", diff --git a/tests/jest.config.dom.js b/tests/jest.config.dom.js index 7385fb4e..72b3b24b 100644 --- a/tests/jest.config.dom.js +++ b/tests/jest.config.dom.js @@ -11,10 +11,4 @@ module.exports = { '/__node_tests__/', ], testEnvironment: 'jest-environment-jsdom', - transform: { - '^.+\\.(js|jsx|ts|tsx)$': path.join( - __dirname, - '../node_modules/kcd-scripts/dist/config/babel-transform', - ), - }, } diff --git a/tests/jest.config.node.js b/tests/jest.config.node.js index e3325db9..bf37b60b 100644 --- a/tests/jest.config.node.js +++ b/tests/jest.config.node.js @@ -12,10 +12,4 @@ module.exports = { '/__node_tests__/', ], testMatch: ['**/__node_tests__/**.js'], - transform: { - '^.+\\.(js|jsx|ts|tsx)$': path.join( - __dirname, - '../node_modules/kcd-scripts/dist/config/babel-transform', - ), - }, } diff --git a/types/event-map.d.ts b/types/event-map.d.ts index d9ea5eef..08d06811 100644 --- a/types/event-map.d.ts +++ b/types/event-map.d.ts @@ -1,72 +1,56 @@ -declare type EventMapKey = string +declare type EventMapKey = string; declare type LegacyKeyboardEventInit = { - charCode?: number -} & KeyboardEventInit -declare type EventMapValue = - | { - EventType: 'AnimationEvent' - defaultInit: AnimationEventInit - } - | { - EventType: 'ClipboardEvent' - defaultInit: ClipboardEventInit - } - | { - EventType: 'CompositionEvent' - defaultInit: CompositionEventInit - } - | { - EventType: 'DragEvent' - defaultInit: DragEventInit - } - | { - EventType: 'Event' - defaultInit: EventInit - } - | { - EventType: 'FocusEvent' - defaultInit: FocusEventInit - } - | { - EventType: 'KeyboardEvent' - defaultInit: LegacyKeyboardEventInit - } - | { - EventType: 'InputEvent' - defaultInit: InputEventInit - } - | { - EventType: 'MouseEvent' - defaultInit: MouseEventInit - } - | { - EventType: 'PointerEvent' - defaultInit: PointerEventInit - } - | { - EventType: 'PopStateEvent' - defaultInit: PopStateEventInit - } - | { - EventType: 'ProgressEvent' - defaultInit: ProgressEventInit - } - | { - EventType: 'TouchEvent' - defaultInit: TouchEventInit - } - | { - EventType: 'TransitionEvent' - defaultInit: TransitionEventInit - } - | { - EventType: 'UIEvent' - defaultInit: UIEventInit - } - | { - EventType: 'WheelEvent' - defaultInit: WheelEventInit - } -export declare const eventMap: Record -export declare const eventAliasMap: Record -export {} + charCode?: number; +} & KeyboardEventInit; +declare type EventMapValue = { + EventType: 'AnimationEvent'; + defaultInit: AnimationEventInit; +} | { + EventType: 'ClipboardEvent'; + defaultInit: ClipboardEventInit; +} | { + EventType: 'CompositionEvent'; + defaultInit: CompositionEventInit; +} | { + EventType: 'DragEvent'; + defaultInit: DragEventInit; +} | { + EventType: 'Event'; + defaultInit: EventInit; +} | { + EventType: 'FocusEvent'; + defaultInit: FocusEventInit; +} | { + EventType: 'KeyboardEvent'; + defaultInit: LegacyKeyboardEventInit; +} | { + EventType: 'InputEvent'; + defaultInit: InputEventInit; +} | { + EventType: 'MouseEvent'; + defaultInit: MouseEventInit; +} | { + EventType: 'PointerEvent'; + defaultInit: PointerEventInit; +} | { + EventType: 'PopStateEvent'; + defaultInit: PopStateEventInit; +} | { + EventType: 'ProgressEvent'; + defaultInit: ProgressEventInit; +} | { + EventType: 'TouchEvent'; + defaultInit: TouchEventInit; +} | { + EventType: 'TransitionEvent'; + defaultInit: TransitionEventInit; +} | { + EventType: 'UIEvent'; + defaultInit: UIEventInit; +} | { + EventType: 'WheelEvent'; + defaultInit: WheelEventInit; +}; +export declare const eventMap: Record; +export declare const eventAliasMap: Record; +export {}; diff --git a/types/matches.d.ts b/types/matches.d.ts index 4200b734..84b0ad66 100644 --- a/types/matches.d.ts +++ b/types/matches.d.ts @@ -1,39 +1,23 @@ -export declare type MatcherFunction = ( - content: string, - element: HTMLElement, -) => boolean -export declare type Matcher = string | RegExp | MatcherFunction -export declare type NormalizerFn = (text: string) => string +export declare type MatcherFunction = (content: string, element: HTMLElement) => boolean; +export declare type Matcher = string | RegExp | MatcherFunction; +export declare type NormalizerFn = (text: string) => string; export interface MatcherOptions { - exact?: boolean - /** Use normalizer with getDefaultNormalizer instead */ - trim?: boolean - /** Use normalizer with getDefaultNormalizer instead */ - collapseWhitespace?: boolean - normalizer?: NormalizerFn - /** suppress suggestions for a specific query */ - suggest?: boolean + exact?: boolean; + /** Use normalizer with getDefaultNormalizer instead */ + trim?: boolean; + /** Use normalizer with getDefaultNormalizer instead */ + collapseWhitespace?: boolean; + normalizer?: NormalizerFn; + /** suppress suggestions for a specific query */ + suggest?: boolean; } -declare function fuzzyMatches( - textToMatch: string, - node: HTMLElement | null, - matcher: Matcher, - normalizer: NormalizerFn, -): boolean -declare function matches( - textToMatch: string, - node: HTMLElement | null, - matcher: Matcher, - normalizer: NormalizerFn, -): boolean +declare function fuzzyMatches(textToMatch: string, node: HTMLElement | null, matcher: Matcher, normalizer: NormalizerFn): boolean; +declare function matches(textToMatch: string, node: HTMLElement | null, matcher: Matcher, normalizer: NormalizerFn): boolean; export interface DefaultNormalizerOptions { - trim?: boolean - collapseWhitespace?: boolean + trim?: boolean; + collapseWhitespace?: boolean; } -declare function getDefaultNormalizer({ - trim, - collapseWhitespace, -}?: DefaultNormalizerOptions): NormalizerFn +declare function getDefaultNormalizer({ trim, collapseWhitespace, }?: DefaultNormalizerOptions): NormalizerFn; /** * Constructs a normalizer to pass to functions in matches.js * @param {boolean|undefined} trim The user-specified value for `trim`, without @@ -43,13 +27,9 @@ declare function getDefaultNormalizer({ * @param {Function|undefined} normalizer The user-specified normalizer * @returns {Function} A normalizer */ -declare function makeNormalizer({ - trim, - collapseWhitespace, - normalizer, -}: { - trim: any - collapseWhitespace: any - normalizer: any -}): NormalizerFn -export {fuzzyMatches, matches, getDefaultNormalizer, makeNormalizer} +declare function makeNormalizer({ trim, collapseWhitespace, normalizer }: { + trim: any; + collapseWhitespace: any; + normalizer: any; +}): NormalizerFn; +export { fuzzyMatches, matches, getDefaultNormalizer, makeNormalizer }; From c9340dd311cbe4126a1d413f6daba58c3e9e4736 Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Wed, 10 Jun 2020 21:05:41 +0200 Subject: [PATCH 05/16] Format the 'types' directory --- .prettierignore | 1 - package.json | 2 +- types/config.d.ts | 16 +- types/event-map.d.ts | 126 +++++----- types/events.d.ts | 189 ++++++++------- types/get-node-text.d.ts | 4 +- types/get-queries-for-element.d.ts | 49 ++-- types/index.d.ts | 42 ++-- types/matches.d.ts | 64 +++-- types/pretty-dom.d.ts | 14 +- types/queries.d.ts | 271 ++++++++++++---------- types/query-helpers.d.ts | 4 +- types/role-helpers.d.ts | 8 +- types/screen.d.ts | 28 +-- types/tslint.json | 3 +- types/wait-for-dom-change.d.ts | 4 +- types/wait-for-element-to-be-removed.d.ts | 8 +- types/wait-for-element.d.ts | 7 +- types/wait.d.ts | 12 +- 19 files changed, 478 insertions(+), 374 deletions(-) diff --git a/.prettierignore b/.prettierignore index e09c4562..9c628283 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,3 @@ node_modules coverage dist -types diff --git a/package.json b/package.json index 3c75817c..ff789973 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "jest-serializer-ansi": "^1.0.3", "jest-watch-select-projects": "^2.0.0", "jsdom": "^16.2.2", - "kcd-scripts": "^6.2.0", + "kcd-scripts": "^6.2.3", "typescript": "^3.9.5" }, "eslintConfig": { diff --git a/types/config.d.ts b/types/config.d.ts index a1fa9fe1..0e623b4e 100644 --- a/types/config.d.ts +++ b/types/config.d.ts @@ -1,14 +1,14 @@ export interface Config { - testIdAttribute: string; - asyncWrapper(cb: (...args: any[]) => any): Promise; - eventWrapper(cb: (...args: any[]) => any): void; - asyncUtilTimeout: number; - defaultHidden: boolean; - throwSuggestions: boolean; + testIdAttribute: string + asyncWrapper(cb: (...args: any[]) => any): Promise + eventWrapper(cb: (...args: any[]) => any): void + asyncUtilTimeout: number + defaultHidden: boolean + throwSuggestions: boolean } export interface ConfigFn { - (existingConfig: Config): Partial; + (existingConfig: Config): Partial } -export function configure(configDelta: Partial | ConfigFn): void; +export function configure(configDelta: Partial | ConfigFn): void diff --git a/types/event-map.d.ts b/types/event-map.d.ts index 08d06811..d9ea5eef 100644 --- a/types/event-map.d.ts +++ b/types/event-map.d.ts @@ -1,56 +1,72 @@ -declare type EventMapKey = string; +declare type EventMapKey = string declare type LegacyKeyboardEventInit = { - charCode?: number; -} & KeyboardEventInit; -declare type EventMapValue = { - EventType: 'AnimationEvent'; - defaultInit: AnimationEventInit; -} | { - EventType: 'ClipboardEvent'; - defaultInit: ClipboardEventInit; -} | { - EventType: 'CompositionEvent'; - defaultInit: CompositionEventInit; -} | { - EventType: 'DragEvent'; - defaultInit: DragEventInit; -} | { - EventType: 'Event'; - defaultInit: EventInit; -} | { - EventType: 'FocusEvent'; - defaultInit: FocusEventInit; -} | { - EventType: 'KeyboardEvent'; - defaultInit: LegacyKeyboardEventInit; -} | { - EventType: 'InputEvent'; - defaultInit: InputEventInit; -} | { - EventType: 'MouseEvent'; - defaultInit: MouseEventInit; -} | { - EventType: 'PointerEvent'; - defaultInit: PointerEventInit; -} | { - EventType: 'PopStateEvent'; - defaultInit: PopStateEventInit; -} | { - EventType: 'ProgressEvent'; - defaultInit: ProgressEventInit; -} | { - EventType: 'TouchEvent'; - defaultInit: TouchEventInit; -} | { - EventType: 'TransitionEvent'; - defaultInit: TransitionEventInit; -} | { - EventType: 'UIEvent'; - defaultInit: UIEventInit; -} | { - EventType: 'WheelEvent'; - defaultInit: WheelEventInit; -}; -export declare const eventMap: Record; -export declare const eventAliasMap: Record; -export {}; + charCode?: number +} & KeyboardEventInit +declare type EventMapValue = + | { + EventType: 'AnimationEvent' + defaultInit: AnimationEventInit + } + | { + EventType: 'ClipboardEvent' + defaultInit: ClipboardEventInit + } + | { + EventType: 'CompositionEvent' + defaultInit: CompositionEventInit + } + | { + EventType: 'DragEvent' + defaultInit: DragEventInit + } + | { + EventType: 'Event' + defaultInit: EventInit + } + | { + EventType: 'FocusEvent' + defaultInit: FocusEventInit + } + | { + EventType: 'KeyboardEvent' + defaultInit: LegacyKeyboardEventInit + } + | { + EventType: 'InputEvent' + defaultInit: InputEventInit + } + | { + EventType: 'MouseEvent' + defaultInit: MouseEventInit + } + | { + EventType: 'PointerEvent' + defaultInit: PointerEventInit + } + | { + EventType: 'PopStateEvent' + defaultInit: PopStateEventInit + } + | { + EventType: 'ProgressEvent' + defaultInit: ProgressEventInit + } + | { + EventType: 'TouchEvent' + defaultInit: TouchEventInit + } + | { + EventType: 'TransitionEvent' + defaultInit: TransitionEventInit + } + | { + EventType: 'UIEvent' + defaultInit: UIEventInit + } + | { + EventType: 'WheelEvent' + defaultInit: WheelEventInit + } +export declare const eventMap: Record +export declare const eventAliasMap: Record +export {} diff --git a/types/events.d.ts b/types/events.d.ts index d9c50cb7..50f95145 100644 --- a/types/events.d.ts +++ b/types/events.d.ts @@ -1,95 +1,104 @@ export type EventType = - | 'copy' - | 'cut' - | 'paste' - | 'compositionEnd' - | 'compositionStart' - | 'compositionUpdate' - | 'keyDown' - | 'keyPress' - | 'keyUp' - | 'focus' - | 'blur' - | 'focusIn' - | 'focusOut' - | 'change' - | 'input' - | 'invalid' - | 'submit' - | 'reset' - | 'click' - | 'contextMenu' - | 'dblClick' - | 'drag' - | 'dragEnd' - | 'dragEnter' - | 'dragExit' - | 'dragLeave' - | 'dragOver' - | 'dragStart' - | 'drop' - | 'mouseDown' - | 'mouseEnter' - | 'mouseLeave' - | 'mouseMove' - | 'mouseOut' - | 'mouseOver' - | 'mouseUp' - | 'popState' - | 'select' - | 'touchCancel' - | 'touchEnd' - | 'touchMove' - | 'touchStart' - | 'scroll' - | 'wheel' - | 'abort' - | 'canPlay' - | 'canPlayThrough' - | 'durationChange' - | 'emptied' - | 'encrypted' - | 'ended' - | 'loadedData' - | 'loadedMetadata' - | 'loadStart' - | 'pause' - | 'play' - | 'playing' - | 'progress' - | 'rateChange' - | 'seeked' - | 'seeking' - | 'stalled' - | 'suspend' - | 'timeUpdate' - | 'volumeChange' - | 'waiting' - | 'load' - | 'error' - | 'animationStart' - | 'animationEnd' - | 'animationIteration' - | 'transitionEnd' - | 'doubleClick' - | 'pointerOver' - | 'pointerEnter' - | 'pointerDown' - | 'pointerMove' - | 'pointerUp' - | 'pointerCancel' - | 'pointerOut' - | 'pointerLeave' - | 'gotPointerCapture' - | 'lostPointerCapture'; + | 'copy' + | 'cut' + | 'paste' + | 'compositionEnd' + | 'compositionStart' + | 'compositionUpdate' + | 'keyDown' + | 'keyPress' + | 'keyUp' + | 'focus' + | 'blur' + | 'focusIn' + | 'focusOut' + | 'change' + | 'input' + | 'invalid' + | 'submit' + | 'reset' + | 'click' + | 'contextMenu' + | 'dblClick' + | 'drag' + | 'dragEnd' + | 'dragEnter' + | 'dragExit' + | 'dragLeave' + | 'dragOver' + | 'dragStart' + | 'drop' + | 'mouseDown' + | 'mouseEnter' + | 'mouseLeave' + | 'mouseMove' + | 'mouseOut' + | 'mouseOver' + | 'mouseUp' + | 'popState' + | 'select' + | 'touchCancel' + | 'touchEnd' + | 'touchMove' + | 'touchStart' + | 'scroll' + | 'wheel' + | 'abort' + | 'canPlay' + | 'canPlayThrough' + | 'durationChange' + | 'emptied' + | 'encrypted' + | 'ended' + | 'loadedData' + | 'loadedMetadata' + | 'loadStart' + | 'pause' + | 'play' + | 'playing' + | 'progress' + | 'rateChange' + | 'seeked' + | 'seeking' + | 'stalled' + | 'suspend' + | 'timeUpdate' + | 'volumeChange' + | 'waiting' + | 'load' + | 'error' + | 'animationStart' + | 'animationEnd' + | 'animationIteration' + | 'transitionEnd' + | 'doubleClick' + | 'pointerOver' + | 'pointerEnter' + | 'pointerDown' + | 'pointerMove' + | 'pointerUp' + | 'pointerCancel' + | 'pointerOut' + | 'pointerLeave' + | 'gotPointerCapture' + | 'lostPointerCapture' -export type FireFunction = (element: Document | Element | Window | Node, event: Event) => boolean; +export type FireFunction = ( + element: Document | Element | Window | Node, + event: Event, +) => boolean export type FireObject = { - [K in EventType]: (element: Document | Element | Window | Node, options?: {}) => boolean; -}; + [K in EventType]: ( + element: Document | Element | Window | Node, + options?: {}, + ) => boolean +} export type CreateObject = { - [K in EventType]: (element: Document | Element | Window | Node, options?: {}) => Event; -}; + [K in EventType]: ( + element: Document | Element | Window | Node, + options?: {}, + ) => Event +} -export const createEvent: CreateObject; -export const fireEvent: FireFunction & FireObject; +export const createEvent: CreateObject +export const fireEvent: FireFunction & FireObject diff --git a/types/get-node-text.d.ts b/types/get-node-text.d.ts index dd40d013..7e0defa9 100644 --- a/types/get-node-text.d.ts +++ b/types/get-node-text.d.ts @@ -1,2 +1,2 @@ -declare function getNodeText(node: HTMLElement): string; -export { getNodeText }; +declare function getNodeText(node: HTMLElement): string +export {getNodeText} diff --git a/types/get-queries-for-element.d.ts b/types/get-queries-for-element.d.ts index b93adfe1..79abde82 100644 --- a/types/get-queries-for-element.d.ts +++ b/types/get-queries-for-element.d.ts @@ -1,29 +1,40 @@ -import * as queries from './queries'; +import * as queries from './queries' export type BoundFunction = T extends ( - attribute: string, - element: HTMLElement, - text: infer P, - options: infer Q, + attribute: string, + element: HTMLElement, + text: infer P, + options: infer Q, ) => infer R - ? (text: P, options?: Q) => R - : T extends (a1: any, text: infer P, options: infer Q, waitForElementOptions: infer W) => infer R - ? (text: P, options?: Q, waitForElementOptions?: W) => R - : T extends (a1: any, text: infer P, options: infer Q) => infer R - ? (text: P, options?: Q) => R - : never; -export type BoundFunctions = { [P in keyof T]: BoundFunction }; + ? (text: P, options?: Q) => R + : T extends ( + a1: any, + text: infer P, + options: infer Q, + waitForElementOptions: infer W, + ) => infer R + ? (text: P, options?: Q, waitForElementOptions?: W) => R + : T extends (a1: any, text: infer P, options: infer Q) => infer R + ? (text: P, options?: Q) => R + : never +export type BoundFunctions = {[P in keyof T]: BoundFunction} export type Query = ( - container: HTMLElement, - ...args: any[] -) => Error | Promise | Promise | HTMLElement[] | HTMLElement | null; + container: HTMLElement, + ...args: any[] +) => + | Error + | Promise + | Promise + | HTMLElement[] + | HTMLElement + | null export interface Queries { - [T: string]: Query; + [T: string]: Query } export function getQueriesForElement( - element: HTMLElement, - queriesToBind?: T, -): BoundFunctions; + element: HTMLElement, + queriesToBind?: T, +): BoundFunctions diff --git a/types/index.d.ts b/types/index.d.ts index 5b199dcf..38830ff4 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,25 +1,25 @@ // TypeScript Version: 3.8 -import { getQueriesForElement } from './get-queries-for-element'; -import * as queries from './queries'; -import * as queryHelpers from './query-helpers'; +import {getQueriesForElement} from './get-queries-for-element' +import * as queries from './queries' +import * as queryHelpers from './query-helpers' -declare const within: typeof getQueriesForElement; -export { queries, queryHelpers, within }; +declare const within: typeof getQueriesForElement +export {queries, queryHelpers, within} -export * from './queries'; -export * from './query-helpers'; -export * from './screen'; -export * from './wait'; -export * from './wait-for'; -export * from './wait-for-dom-change'; -export * from './wait-for-element'; -export * from './wait-for-element-to-be-removed'; -export * from './matches'; -export * from './get-node-text'; -export * from './events'; -export * from './get-queries-for-element'; -export * from './pretty-dom'; -export * from './role-helpers'; -export * from './config'; -export * from './suggestions'; +export * from './queries' +export * from './query-helpers' +export * from './screen' +export * from './wait' +export * from './wait-for' +export * from './wait-for-dom-change' +export * from './wait-for-element' +export * from './wait-for-element-to-be-removed' +export * from './matches' +export * from './get-node-text' +export * from './events' +export * from './get-queries-for-element' +export * from './pretty-dom' +export * from './role-helpers' +export * from './config' +export * from './suggestions' diff --git a/types/matches.d.ts b/types/matches.d.ts index 84b0ad66..4200b734 100644 --- a/types/matches.d.ts +++ b/types/matches.d.ts @@ -1,23 +1,39 @@ -export declare type MatcherFunction = (content: string, element: HTMLElement) => boolean; -export declare type Matcher = string | RegExp | MatcherFunction; -export declare type NormalizerFn = (text: string) => string; +export declare type MatcherFunction = ( + content: string, + element: HTMLElement, +) => boolean +export declare type Matcher = string | RegExp | MatcherFunction +export declare type NormalizerFn = (text: string) => string export interface MatcherOptions { - exact?: boolean; - /** Use normalizer with getDefaultNormalizer instead */ - trim?: boolean; - /** Use normalizer with getDefaultNormalizer instead */ - collapseWhitespace?: boolean; - normalizer?: NormalizerFn; - /** suppress suggestions for a specific query */ - suggest?: boolean; + exact?: boolean + /** Use normalizer with getDefaultNormalizer instead */ + trim?: boolean + /** Use normalizer with getDefaultNormalizer instead */ + collapseWhitespace?: boolean + normalizer?: NormalizerFn + /** suppress suggestions for a specific query */ + suggest?: boolean } -declare function fuzzyMatches(textToMatch: string, node: HTMLElement | null, matcher: Matcher, normalizer: NormalizerFn): boolean; -declare function matches(textToMatch: string, node: HTMLElement | null, matcher: Matcher, normalizer: NormalizerFn): boolean; +declare function fuzzyMatches( + textToMatch: string, + node: HTMLElement | null, + matcher: Matcher, + normalizer: NormalizerFn, +): boolean +declare function matches( + textToMatch: string, + node: HTMLElement | null, + matcher: Matcher, + normalizer: NormalizerFn, +): boolean export interface DefaultNormalizerOptions { - trim?: boolean; - collapseWhitespace?: boolean; + trim?: boolean + collapseWhitespace?: boolean } -declare function getDefaultNormalizer({ trim, collapseWhitespace, }?: DefaultNormalizerOptions): NormalizerFn; +declare function getDefaultNormalizer({ + trim, + collapseWhitespace, +}?: DefaultNormalizerOptions): NormalizerFn /** * Constructs a normalizer to pass to functions in matches.js * @param {boolean|undefined} trim The user-specified value for `trim`, without @@ -27,9 +43,13 @@ declare function getDefaultNormalizer({ trim, collapseWhitespace, }?: DefaultNor * @param {Function|undefined} normalizer The user-specified normalizer * @returns {Function} A normalizer */ -declare function makeNormalizer({ trim, collapseWhitespace, normalizer }: { - trim: any; - collapseWhitespace: any; - normalizer: any; -}): NormalizerFn; -export { fuzzyMatches, matches, getDefaultNormalizer, makeNormalizer }; +declare function makeNormalizer({ + trim, + collapseWhitespace, + normalizer, +}: { + trim: any + collapseWhitespace: any + normalizer: any +}): NormalizerFn +export {fuzzyMatches, matches, getDefaultNormalizer, makeNormalizer} diff --git a/types/pretty-dom.d.ts b/types/pretty-dom.d.ts index bca6afb4..ccddb4f4 100644 --- a/types/pretty-dom.d.ts +++ b/types/pretty-dom.d.ts @@ -1,4 +1,12 @@ -import { OptionsReceived } from 'pretty-format'; +import {OptionsReceived} from 'pretty-format' -export function prettyDOM(dom?: Element | HTMLDocument, maxLength?: number, options?: OptionsReceived): string | false; -export function logDOM(dom?: Element | HTMLDocument, maxLength?: number, options?: OptionsReceived): void; +export function prettyDOM( + dom?: Element | HTMLDocument, + maxLength?: number, + options?: OptionsReceived, +): string | false +export function logDOM( + dom?: Element | HTMLDocument, + maxLength?: number, + options?: OptionsReceived, +): void diff --git a/types/queries.d.ts b/types/queries.d.ts index 92c1b946..a4c535cc 100644 --- a/types/queries.d.ts +++ b/types/queries.d.ts @@ -1,139 +1,174 @@ -import { Matcher, MatcherOptions } from './matches'; -import { SelectorMatcherOptions } from './query-helpers'; -import { waitForOptions } from './wait-for'; +import {Matcher, MatcherOptions} from './matches' +import {SelectorMatcherOptions} from './query-helpers' +import {waitForOptions} from './wait-for' export type QueryByBoundAttribute = ( - container: HTMLElement, - id: Matcher, - options?: MatcherOptions, -) => HTMLElement | null; + container: HTMLElement, + id: Matcher, + options?: MatcherOptions, +) => HTMLElement | null -export type AllByBoundAttribute = (container: HTMLElement, id: Matcher, options?: MatcherOptions) => HTMLElement[]; +export type AllByBoundAttribute = ( + container: HTMLElement, + id: Matcher, + options?: MatcherOptions, +) => HTMLElement[] export type FindAllByBoundAttribute = ( - container: HTMLElement, - id: Matcher, - options?: MatcherOptions, - waitForElementOptions?: waitForOptions, -) => Promise; - -export type GetByBoundAttribute = (container: HTMLElement, id: Matcher, options?: MatcherOptions) => HTMLElement; + container: HTMLElement, + id: Matcher, + options?: MatcherOptions, + waitForElementOptions?: waitForOptions, +) => Promise + +export type GetByBoundAttribute = ( + container: HTMLElement, + id: Matcher, + options?: MatcherOptions, +) => HTMLElement export type FindByBoundAttribute = ( - container: HTMLElement, - id: Matcher, - options?: MatcherOptions, - waitForElementOptions?: waitForOptions, -) => Promise; - -export type QueryByText = (container: HTMLElement, id: Matcher, options?: SelectorMatcherOptions) => HTMLElement | null; - -export type AllByText = (container: HTMLElement, id: Matcher, options?: SelectorMatcherOptions) => HTMLElement[]; + container: HTMLElement, + id: Matcher, + options?: MatcherOptions, + waitForElementOptions?: waitForOptions, +) => Promise + +export type QueryByText = ( + container: HTMLElement, + id: Matcher, + options?: SelectorMatcherOptions, +) => HTMLElement | null + +export type AllByText = ( + container: HTMLElement, + id: Matcher, + options?: SelectorMatcherOptions, +) => HTMLElement[] export type FindAllByText = ( - container: HTMLElement, - id: Matcher, - options?: SelectorMatcherOptions, - waitForElementOptions?: waitForOptions, -) => Promise; - -export type GetByText = (container: HTMLElement, id: Matcher, options?: SelectorMatcherOptions) => HTMLElement; + container: HTMLElement, + id: Matcher, + options?: SelectorMatcherOptions, + waitForElementOptions?: waitForOptions, +) => Promise + +export type GetByText = ( + container: HTMLElement, + id: Matcher, + options?: SelectorMatcherOptions, +) => HTMLElement export type FindByText = ( - container: HTMLElement, - id: Matcher, - options?: SelectorMatcherOptions, - waitForElementOptions?: waitForOptions, -) => Promise; + container: HTMLElement, + id: Matcher, + options?: SelectorMatcherOptions, + waitForElementOptions?: waitForOptions, +) => Promise export interface ByRoleOptions extends MatcherOptions { - /** - * If true includes elements in the query set that are usually excluded from - * the accessibility tree. `role="none"` or `role="presentation"` are included - * in either case. - */ - hidden?: boolean; - /** - * If true only includes elements in the query set that are marked as - * selected in the accessibility tree, i.e., `aria-selected="true"` - */ - selected?: boolean; - /** - * Includes every role used in the `role` attribute - * For example *ByRole('progressbar', {queryFallbacks: true})` will find
`. - */ - queryFallbacks?: boolean; - /** - * Only considers elements with the specified accessible name. - */ - name?: string | RegExp | ((accessibleName: string, element: Element) => boolean); + /** + * If true includes elements in the query set that are usually excluded from + * the accessibility tree. `role="none"` or `role="presentation"` are included + * in either case. + */ + hidden?: boolean + /** + * If true only includes elements in the query set that are marked as + * selected in the accessibility tree, i.e., `aria-selected="true"` + */ + selected?: boolean + /** + * Includes every role used in the `role` attribute + * For example *ByRole('progressbar', {queryFallbacks: true})` will find
`. + */ + queryFallbacks?: boolean + /** + * Only considers elements with the specified accessible name. + */ + name?: + | string + | RegExp + | ((accessibleName: string, element: Element) => boolean) } -export type AllByRole = (container: HTMLElement, role: Matcher, options?: ByRoleOptions) => HTMLElement[]; +export type AllByRole = ( + container: HTMLElement, + role: Matcher, + options?: ByRoleOptions, +) => HTMLElement[] -export type GetByRole = (container: HTMLElement, role: Matcher, options?: ByRoleOptions) => HTMLElement; +export type GetByRole = ( + container: HTMLElement, + role: Matcher, + options?: ByRoleOptions, +) => HTMLElement -export type QueryByRole = (container: HTMLElement, role: Matcher, options?: ByRoleOptions) => HTMLElement | null; +export type QueryByRole = ( + container: HTMLElement, + role: Matcher, + options?: ByRoleOptions, +) => HTMLElement | null export type FindByRole = ( - container: HTMLElement, - role: Matcher, - options?: ByRoleOptions, - waitForElementOptions?: waitForOptions, -) => Promise; + container: HTMLElement, + role: Matcher, + options?: ByRoleOptions, + waitForElementOptions?: waitForOptions, +) => Promise export type FindAllByRole = ( - container: HTMLElement, - role: Matcher, - options?: ByRoleOptions, - waitForElementOptions?: waitForOptions, -) => Promise; - -export const getByLabelText: GetByText; -export const getAllByLabelText: AllByText; -export const queryByLabelText: QueryByText; -export const queryAllByLabelText: AllByText; -export const findByLabelText: FindByText; -export const findAllByLabelText: FindAllByText; -export const getByPlaceholderText: GetByBoundAttribute; -export const getAllByPlaceholderText: AllByBoundAttribute; -export const queryByPlaceholderText: QueryByBoundAttribute; -export const queryAllByPlaceholderText: AllByBoundAttribute; -export const findByPlaceholderText: FindByBoundAttribute; -export const findAllByPlaceholderText: FindAllByBoundAttribute; -export const getByText: GetByText; -export const getAllByText: AllByText; -export const queryByText: QueryByText; -export const queryAllByText: AllByText; -export const findByText: FindByText; -export const findAllByText: FindAllByText; -export const getByAltText: GetByBoundAttribute; -export const getAllByAltText: AllByBoundAttribute; -export const queryByAltText: QueryByBoundAttribute; -export const queryAllByAltText: AllByBoundAttribute; -export const findByAltText: FindByBoundAttribute; -export const findAllByAltText: FindAllByBoundAttribute; -export const getByTitle: GetByBoundAttribute; -export const getAllByTitle: AllByBoundAttribute; -export const queryByTitle: QueryByBoundAttribute; -export const queryAllByTitle: AllByBoundAttribute; -export const findByTitle: FindByBoundAttribute; -export const findAllByTitle: FindAllByBoundAttribute; -export const getByDisplayValue: GetByBoundAttribute; -export const getAllByDisplayValue: AllByBoundAttribute; -export const queryByDisplayValue: QueryByBoundAttribute; -export const queryAllByDisplayValue: AllByBoundAttribute; -export const findByDisplayValue: FindByBoundAttribute; -export const findAllByDisplayValue: FindAllByBoundAttribute; -export const getByRole: GetByRole; -export const getAllByRole: AllByRole; -export const queryByRole: QueryByRole; -export const queryAllByRole: AllByRole; -export const findByRole: FindByRole; -export const findAllByRole: FindAllByRole; -export const getByTestId: GetByBoundAttribute; -export const getAllByTestId: AllByBoundAttribute; -export const queryByTestId: QueryByBoundAttribute; -export const queryAllByTestId: AllByBoundAttribute; -export const findByTestId: FindByBoundAttribute; -export const findAllByTestId: FindAllByBoundAttribute; + container: HTMLElement, + role: Matcher, + options?: ByRoleOptions, + waitForElementOptions?: waitForOptions, +) => Promise + +export const getByLabelText: GetByText +export const getAllByLabelText: AllByText +export const queryByLabelText: QueryByText +export const queryAllByLabelText: AllByText +export const findByLabelText: FindByText +export const findAllByLabelText: FindAllByText +export const getByPlaceholderText: GetByBoundAttribute +export const getAllByPlaceholderText: AllByBoundAttribute +export const queryByPlaceholderText: QueryByBoundAttribute +export const queryAllByPlaceholderText: AllByBoundAttribute +export const findByPlaceholderText: FindByBoundAttribute +export const findAllByPlaceholderText: FindAllByBoundAttribute +export const getByText: GetByText +export const getAllByText: AllByText +export const queryByText: QueryByText +export const queryAllByText: AllByText +export const findByText: FindByText +export const findAllByText: FindAllByText +export const getByAltText: GetByBoundAttribute +export const getAllByAltText: AllByBoundAttribute +export const queryByAltText: QueryByBoundAttribute +export const queryAllByAltText: AllByBoundAttribute +export const findByAltText: FindByBoundAttribute +export const findAllByAltText: FindAllByBoundAttribute +export const getByTitle: GetByBoundAttribute +export const getAllByTitle: AllByBoundAttribute +export const queryByTitle: QueryByBoundAttribute +export const queryAllByTitle: AllByBoundAttribute +export const findByTitle: FindByBoundAttribute +export const findAllByTitle: FindAllByBoundAttribute +export const getByDisplayValue: GetByBoundAttribute +export const getAllByDisplayValue: AllByBoundAttribute +export const queryByDisplayValue: QueryByBoundAttribute +export const queryAllByDisplayValue: AllByBoundAttribute +export const findByDisplayValue: FindByBoundAttribute +export const findAllByDisplayValue: FindAllByBoundAttribute +export const getByRole: GetByRole +export const getAllByRole: AllByRole +export const queryByRole: QueryByRole +export const queryAllByRole: AllByRole +export const findByRole: FindByRole +export const findAllByRole: FindAllByRole +export const getByTestId: GetByBoundAttribute +export const getAllByTestId: AllByBoundAttribute +export const queryByTestId: QueryByBoundAttribute +export const queryAllByTestId: AllByBoundAttribute +export const findByTestId: FindByBoundAttribute +export const findAllByTestId: FindAllByBoundAttribute diff --git a/types/query-helpers.d.ts b/types/query-helpers.d.ts index de50a2d3..2c848f29 100644 --- a/types/query-helpers.d.ts +++ b/types/query-helpers.d.ts @@ -1,5 +1,5 @@ -import { Matcher, MatcherOptions } from './matches' -import { waitForOptions } from './wait-for' +import {Matcher, MatcherOptions} from './matches' +import {waitForOptions} from './wait-for' export interface SelectorMatcherOptions extends MatcherOptions { selector?: string diff --git a/types/role-helpers.d.ts b/types/role-helpers.d.ts index 3dd35b78..06565f7f 100644 --- a/types/role-helpers.d.ts +++ b/types/role-helpers.d.ts @@ -1,6 +1,8 @@ -export function logRoles(container: HTMLElement): string; -export function getRoles(container: HTMLElement): { [index: string]: HTMLElement[] }; +export function logRoles(container: HTMLElement): string +export function getRoles( + container: HTMLElement, +): {[index: string]: HTMLElement[]} /** * https://testing-library.com/docs/dom-testing-library/api-helpers#isinaccessible */ -export function isInaccessible(element: Element): boolean; +export function isInaccessible(element: Element): boolean diff --git a/types/screen.d.ts b/types/screen.d.ts index 2594f5be..dca6cb86 100644 --- a/types/screen.d.ts +++ b/types/screen.d.ts @@ -1,17 +1,17 @@ -import { BoundFunctions, Queries } from './get-queries-for-element'; -import * as queries from './queries'; -import { OptionsReceived } from 'pretty-format'; +import {BoundFunctions, Queries} from './get-queries-for-element' +import * as queries from './queries' +import {OptionsReceived} from 'pretty-format' export type Screen = BoundFunctions & { - /** - * Convenience function for `pretty-dom` which also allows an array - * of elements - */ - debug: ( - element?: Element | HTMLDocument | Array, - maxLength?: number, - options?: OptionsReceived, - ) => void; -}; + /** + * Convenience function for `pretty-dom` which also allows an array + * of elements + */ + debug: ( + element?: Element | HTMLDocument | Array, + maxLength?: number, + options?: OptionsReceived, + ) => void +} -export const screen: Screen; +export const screen: Screen diff --git a/types/tslint.json b/types/tslint.json index a3f71e09..98c28a67 100644 --- a/types/tslint.json +++ b/types/tslint.json @@ -5,6 +5,7 @@ "no-useless-files": false, "no-relative-import-in-test": false, "semicolon": false, - "strict-export-declare-modifiers": false + "strict-export-declare-modifiers": false, + "whitespace": false } } diff --git a/types/wait-for-dom-change.d.ts b/types/wait-for-dom-change.d.ts index 813437f4..dcd9d51f 100644 --- a/types/wait-for-dom-change.d.ts +++ b/types/wait-for-dom-change.d.ts @@ -1,3 +1,3 @@ -import { waitForOptions } from "./wait-for"; +import {waitForOptions} from './wait-for' -export function waitForDomChange(options?: waitForOptions): Promise; +export function waitForDomChange(options?: waitForOptions): Promise diff --git a/types/wait-for-element-to-be-removed.d.ts b/types/wait-for-element-to-be-removed.d.ts index b6b1e1bb..f86e6315 100644 --- a/types/wait-for-element-to-be-removed.d.ts +++ b/types/wait-for-element-to-be-removed.d.ts @@ -1,6 +1,6 @@ -import { waitForOptions } from "./wait-for"; +import {waitForOptions} from './wait-for' export function waitForElementToBeRemoved( - callback: (() => T) | T, - options?: waitForOptions, -): Promise; + callback: (() => T) | T, + options?: waitForOptions, +): Promise diff --git a/types/wait-for-element.d.ts b/types/wait-for-element.d.ts index 4fe1de0e..04028f6d 100644 --- a/types/wait-for-element.d.ts +++ b/types/wait-for-element.d.ts @@ -1,3 +1,6 @@ -import { waitForOptions } from "./wait-for"; +import {waitForOptions} from './wait-for' -export function waitForElement(callback: () => T, options?: waitForOptions): Promise; +export function waitForElement( + callback: () => T, + options?: waitForOptions, +): Promise diff --git a/types/wait.d.ts b/types/wait.d.ts index 3763e7bd..cb102637 100644 --- a/types/wait.d.ts +++ b/types/wait.d.ts @@ -1,7 +1,7 @@ export function wait( - callback?: () => void, - options?: { - timeout?: number; - interval?: number; - }, -): Promise; + callback?: () => void, + options?: { + timeout?: number + interval?: number + }, +): Promise From 83cf94ef15df17fbfad1c9ad9ba3b01e122cf740 Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Fri, 12 Jun 2020 22:36:11 +0200 Subject: [PATCH 06/16] helper.ts --- src/{helpers.js => helpers.ts} | 2 +- types/helpers.d.ts | 14 ++++++++++++++ types/tslint.json | 1 + 3 files changed, 16 insertions(+), 1 deletion(-) rename src/{helpers.js => helpers.ts} (97%) create mode 100644 types/helpers.d.ts diff --git a/src/helpers.js b/src/helpers.ts similarity index 97% rename from src/helpers.js rename to src/helpers.ts index 64031562..cf9f1e99 100644 --- a/src/helpers.js +++ b/src/helpers.ts @@ -4,7 +4,7 @@ const globalObj = typeof window === 'undefined' ? global : window function runWithRealTimers(callback) { const usingJestFakeTimers = globalObj.setTimeout && - globalObj.setTimeout._isMockFunction && + (globalObj.setTimeout as any)._isMockFunction && typeof jest !== 'undefined' if (usingJestFakeTimers) { diff --git a/types/helpers.d.ts b/types/helpers.d.ts new file mode 100644 index 00000000..51fdb07c --- /dev/null +++ b/types/helpers.d.ts @@ -0,0 +1,14 @@ +declare function runWithRealTimers(callback: any): any +declare const clearTimeoutFn: any, setImmediateFn: any, setTimeoutFn: any +declare function getDocument(): Document +declare function getWindowFromNode(node: any): any +declare function checkContainerType(container: any): void +export { + getWindowFromNode, + getDocument, + clearTimeoutFn as clearTimeout, + setImmediateFn as setImmediate, + setTimeoutFn as setTimeout, + runWithRealTimers, + checkContainerType, +} diff --git a/types/tslint.json b/types/tslint.json index 98c28a67..dcebd4f9 100644 --- a/types/tslint.json +++ b/types/tslint.json @@ -1,6 +1,7 @@ { "extends": ["dtslint/dtslint.json"], "rules": { + "one-variable-per-declaration": false, "no-redundant-jsdoc": false, "no-useless-files": false, "no-relative-import-in-test": false, From ecfb903ddf84c13764209c4e944f62c976d021fb Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Fri, 12 Jun 2020 23:04:17 +0200 Subject: [PATCH 07/16] pretty-dom.ts --- src/helpers.ts | 2 +- src/{pretty-dom.js => pretty-dom.ts} | 39 ++++++++++++++++++++++------ tsconfig.json | 3 ++- types/helpers.d.ts | 2 +- types/pretty-dom.d.ts | 19 +++++++++----- types/tslint.json | 1 + 6 files changed, 49 insertions(+), 17 deletions(-) rename src/{pretty-dom.js => pretty-dom.ts} (61%) diff --git a/src/helpers.ts b/src/helpers.ts index cf9f1e99..7237084d 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -46,7 +46,7 @@ function getDocument() { } return window.document } -function getWindowFromNode(node) { +function getWindowFromNode(node): Window { // istanbul ignore next I'm not sure what could cause the final else so we'll leave it uncovered. if (node.defaultView) { // node is document diff --git a/src/pretty-dom.js b/src/pretty-dom.ts similarity index 61% rename from src/pretty-dom.js rename to src/pretty-dom.ts index 56e8e90d..ee264eef 100644 --- a/src/pretty-dom.js +++ b/src/pretty-dom.ts @@ -1,6 +1,15 @@ -import prettyFormat from 'pretty-format' +import prettyFormat, {OptionsReceived} from 'pretty-format' import {getDocument} from './helpers' +// Declare the potential Cypress variable +declare global { + namespace NodeJS { + interface Global { + Cypress?: any + } + } +} + function inCypress(dom) { const window = (dom.ownerDocument && dom.ownerDocument.defaultView) || undefined @@ -15,14 +24,24 @@ const inNode = () => process.versions !== undefined && process.versions.node !== undefined -const getMaxLength = dom => +const getMaxLength = (dom): number => inCypress(dom) ? 0 - : (typeof process !== 'undefined' && process.env.DEBUG_PRINT_LIMIT) || 7000 + : (typeof process !== 'undefined' && + parseInt(process.env.DEBUG_PRINT_LIMIT, 10)) || + 7000 const {DOMElement, DOMCollection} = prettyFormat.plugins -function prettyDOM(dom, maxLength, options) { +function isDocument(dom?: Element | Document): dom is Document { + return (dom as Document).documentElement !== undefined +} + +function prettyDOM( + dom?: Element | Document, + maxLength?: number, + options?: OptionsReceived, +) { if (!dom) { dom = getDocument().body } @@ -33,16 +52,16 @@ function prettyDOM(dom, maxLength, options) { if (maxLength === 0) { return '' } - if (dom.documentElement) { + if (isDocument(dom)) { dom = dom.documentElement } - let domTypeName = typeof dom + let domTypeName: string = typeof dom if (domTypeName === 'object') { domTypeName = dom.constructor.name } else { // To don't fall with `in` operator - dom = {} + dom = {} as Element } if (!('outerHTML' in dom)) { throw new TypeError( @@ -61,6 +80,10 @@ function prettyDOM(dom, maxLength, options) { : debugContent } -const logDOM = (...args) => console.log(prettyDOM(...args)) +const logDOM = ( + dom?: Element | HTMLDocument, + maxLength?: number, + options?: OptionsReceived, +) => console.log(prettyDOM(dom, maxLength, options)) export {prettyDOM, logDOM} diff --git a/tsconfig.json b/tsconfig.json index a968ea95..16dbfc70 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,7 +3,8 @@ "outDir": "./types/", "allowJs": true, "declaration": true, - "emitDeclarationOnly": true + "emitDeclarationOnly": true, + "allowSyntheticDefaultImports": true }, "include": ["./src/**/*.ts"] } diff --git a/types/helpers.d.ts b/types/helpers.d.ts index 51fdb07c..625fab73 100644 --- a/types/helpers.d.ts +++ b/types/helpers.d.ts @@ -1,7 +1,7 @@ declare function runWithRealTimers(callback: any): any declare const clearTimeoutFn: any, setImmediateFn: any, setTimeoutFn: any declare function getDocument(): Document -declare function getWindowFromNode(node: any): any +declare function getWindowFromNode(node: any): Window declare function checkContainerType(container: any): void export { getWindowFromNode, diff --git a/types/pretty-dom.d.ts b/types/pretty-dom.d.ts index ccddb4f4..fe2b658e 100644 --- a/types/pretty-dom.d.ts +++ b/types/pretty-dom.d.ts @@ -1,12 +1,19 @@ import {OptionsReceived} from 'pretty-format' - -export function prettyDOM( - dom?: Element | HTMLDocument, +declare global { + namespace NodeJS { + interface Global { + Cypress?: any + } + } +} +declare function prettyDOM( + dom?: Element | Document, maxLength?: number, options?: OptionsReceived, -): string | false -export function logDOM( +): string +declare const logDOM: ( dom?: Element | HTMLDocument, maxLength?: number, options?: OptionsReceived, -): void +) => void +export {prettyDOM, logDOM} diff --git a/types/tslint.json b/types/tslint.json index dcebd4f9..c5f38421 100644 --- a/types/tslint.json +++ b/types/tslint.json @@ -5,6 +5,7 @@ "no-redundant-jsdoc": false, "no-useless-files": false, "no-relative-import-in-test": false, + "prefer-declare-function": false, "semicolon": false, "strict-export-declare-modifiers": false, "whitespace": false From 01134b6af0ee9e274fb4e2819b989d44709780d5 Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Fri, 12 Jun 2020 23:18:00 +0200 Subject: [PATCH 08/16] config.ts --- src/{config.js => config.ts} | 23 +++++++++++++++++++++-- types/config.d.ts | 15 ++++++++++++--- 2 files changed, 33 insertions(+), 5 deletions(-) rename src/{config.js => config.ts} (76%) diff --git a/src/config.js b/src/config.ts similarity index 76% rename from src/config.js rename to src/config.ts index 44b51146..f012b8a4 100644 --- a/src/config.js +++ b/src/config.ts @@ -1,9 +1,24 @@ import {prettyDOM} from './pretty-dom' +export interface Config { + testIdAttribute: string + asyncWrapper(cb: (...args: any[]) => any): Promise + eventWrapper(cb: (...args: any[]) => any): void + getElementError: (message: string, container: Element) => Error + asyncUtilTimeout: number + defaultHidden: boolean + showOriginalStackTrace: boolean + throwSuggestions: boolean +} + +interface InternalConfig { + _disableExpensiveErrorDiagnostics: boolean +} + // It would be cleaner for this to live inside './queries', but // other parts of the code assume that all exports from // './queries' are query functions. -let config = { +let config: Config & InternalConfig = { testIdAttribute: 'data-testid', asyncUtilTimeout: 1000, // this is to support React's async `act` function. @@ -44,7 +59,11 @@ export function runWithExpensiveErrorDiagnosticsDisabled(callback) { } } -export function configure(newConfig) { +export interface ConfigFn { + (existingConfig: Config): Partial +} + +export function configure(newConfig: Partial | ConfigFn): void { if (typeof newConfig === 'function') { // Pass the existing config out to the provided function // and accept a delta in return diff --git a/types/config.d.ts b/types/config.d.ts index 0e623b4e..f06d5928 100644 --- a/types/config.d.ts +++ b/types/config.d.ts @@ -2,13 +2,22 @@ export interface Config { testIdAttribute: string asyncWrapper(cb: (...args: any[]) => any): Promise eventWrapper(cb: (...args: any[]) => any): void + getElementError: (message: string, container: Element) => Error asyncUtilTimeout: number defaultHidden: boolean + showOriginalStackTrace: boolean throwSuggestions: boolean } - +interface InternalConfig { + _disableExpensiveErrorDiagnostics: boolean +} +export declare const DEFAULT_IGNORE_TAGS = 'script, style' +export declare function runWithExpensiveErrorDiagnosticsDisabled( + callback: any, +): any export interface ConfigFn { (existingConfig: Config): Partial } - -export function configure(configDelta: Partial | ConfigFn): void +export declare function configure(newConfig: Partial | ConfigFn): void +export declare function getConfig(): Config & InternalConfig +export {} From d771b65c618026e3aaf96de5dd0544be137f11d9 Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Thu, 16 Jul 2020 21:22:05 +0200 Subject: [PATCH 09/16] events.ts / event-map.ts --- src/event-map.ts | 89 ++++++++++++++++++++++++- src/{events.js => events.ts} | 61 ++++++++++++++---- types/event-map.d.ts | 88 ++++++++++++++++++++++++- types/events.d.ts | 122 ++++++----------------------------- types/tslint.json | 1 + 5 files changed, 244 insertions(+), 117 deletions(-) rename src/{events.js => events.ts} (66%) diff --git a/src/event-map.ts b/src/event-map.ts index 9ca36b90..29348eb1 100644 --- a/src/event-map.ts +++ b/src/event-map.ts @@ -1,4 +1,86 @@ -type EventMapKey = string +export type EventMapKey = + | 'copy' + | 'cut' + | 'paste' + | 'compositionEnd' + | 'compositionStart' + | 'compositionUpdate' + | 'keyDown' + | 'keyPress' + | 'keyUp' + | 'focus' + | 'blur' + | 'focusIn' + | 'focusOut' + | 'change' + | 'input' + | 'invalid' + | 'submit' + | 'reset' + | 'click' + | 'contextMenu' + | 'dblClick' + | 'drag' + | 'dragEnd' + | 'dragEnter' + | 'dragExit' + | 'dragLeave' + | 'dragOver' + | 'dragStart' + | 'drop' + | 'mouseDown' + | 'mouseEnter' + | 'mouseLeave' + | 'mouseMove' + | 'mouseOut' + | 'mouseOver' + | 'mouseUp' + | 'popState' + | 'select' + | 'touchCancel' + | 'touchEnd' + | 'touchMove' + | 'touchStart' + | 'scroll' + | 'wheel' + | 'abort' + | 'canPlay' + | 'canPlayThrough' + | 'durationChange' + | 'emptied' + | 'encrypted' + | 'ended' + | 'loadedData' + | 'loadedMetadata' + | 'loadStart' + | 'pause' + | 'play' + | 'playing' + | 'progress' + | 'rateChange' + | 'seeked' + | 'seeking' + | 'stalled' + | 'suspend' + | 'timeUpdate' + | 'volumeChange' + | 'waiting' + | 'load' + | 'error' + | 'animationStart' + | 'animationEnd' + | 'animationIteration' + | 'transitionEnd' + | 'pointerOver' + | 'pointerEnter' + | 'pointerDown' + | 'pointerMove' + | 'pointerUp' + | 'pointerCancel' + | 'pointerOut' + | 'pointerLeave' + | 'gotPointerCapture' + | 'lostPointerCapture' type LegacyKeyboardEventInit = { // lib.dom.ts marks 'charCode' as deprecated in KeyboardEvent and does not include it in KeyboardEventInit @@ -370,6 +452,9 @@ export const eventMap: Record = { }, } -export const eventAliasMap: Record = { +type EventAliasMapKey = 'doubleClick' +export const eventAliasMap: Record = { doubleClick: 'dblClick', } + +export type EventType = EventMapKey | EventAliasMapKey diff --git a/src/events.js b/src/events.ts similarity index 66% rename from src/events.js rename to src/events.ts index 6d19c1fa..d50fd7ab 100644 --- a/src/events.js +++ b/src/events.ts @@ -1,8 +1,16 @@ import {getConfig} from './config' import {getWindowFromNode} from './helpers' -import {eventMap, eventAliasMap} from './event-map' +import {eventMap, EventMapKey, eventAliasMap, EventType} from './event-map' -function fireEvent(element, event) { +declare global { + // FIXME we should not augment the interface here + interface Window { + DataTransfer: () => void + Event: () => void + } +} + +function internalfireEvent(element: EventTarget, event: Event) { return getConfig().eventWrapper(() => { if (!event) { throw new Error( @@ -18,9 +26,26 @@ function fireEvent(element, event) { }) } -const createEvent = {} +function isDragEventInit(eventInit: unknown): eventInit is DragEventInit { + return typeof (eventInit as DragEventInit).dataTransfer === 'object' +} + +type EventTargetWithFiles = HTMLInputElement +type EventTargetWithValue = + | HTMLInputElement + | HTMLButtonElement + | HTMLOutputElement + +type CreateObject = { + [K in EventType]: ( + //element: Document | Element | Window | Node, + element: EventTarget, + options?: {}, + ) => Event +} +const createEvent = {} as CreateObject -Object.keys(eventMap).forEach(key => { +Object.keys(eventMap).forEach((key: EventMapKey) => { const {EventType, defaultInit} = eventMap[key] const eventName = key.toLowerCase() @@ -30,8 +55,11 @@ Object.keys(eventMap).forEach(key => { `Unable to fire a "${key}" event - please provide a DOM element.`, ) } - const eventInit = {...defaultInit, ...init} - const {target: {value, files, ...targetProperties} = {}} = eventInit + const eventInit: EventInit = {...defaultInit, ...init} + const {target = {}} = eventInit as Event + const {value, files, ...targetProperties} = target as Partial< + EventTargetWithValue & EventTargetWithFiles + > if (value !== undefined) { setNativeValue(node, value) } @@ -56,15 +84,17 @@ Object.keys(eventMap).forEach(key => { } else { // IE11 polyfill from https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill event = window.document.createEvent(EventType) - const {bubbles, cancelable, detail, ...otherInit} = eventInit + const {bubbles, cancelable, detail, ...otherInit} = eventInit as Partial< + UIEvent + > event.initEvent(eventName, bubbles, cancelable, detail) Object.keys(otherInit).forEach(eventKey => { event[eventKey] = otherInit[eventKey] }) } - const {dataTransfer} = eventInit - if (typeof dataTransfer === 'object') { + if (isDragEventInit(eventInit)) { + const {dataTransfer} = eventInit // DataTransfer is not supported in jsdom: https://github.com/jsdom/jsdom/issues/1568 /* istanbul ignore if */ if (typeof window.DataTransfer === 'function') { @@ -80,7 +110,8 @@ Object.keys(eventMap).forEach(key => { return event } - fireEvent[key] = (node, init) => fireEvent(node, createEvent[key](node, init)) + internalfireEvent[key] = (node: EventTarget, init) => + internalfireEvent(node, createEvent[key](node, init)) }) // function written after some investigation here: @@ -102,9 +133,17 @@ function setNativeValue(element, value) { Object.keys(eventAliasMap).forEach(aliasKey => { const key = eventAliasMap[aliasKey] - fireEvent[aliasKey] = (...args) => fireEvent[key](...args) + internalfireEvent[aliasKey] = (...args) => fireEvent[key](...args) }) +type FireEventAsFunction = (element: EventTarget, event: Event) => boolean +type FireEventAsHelper = Record< + EventType, + (element: EventTarget, init?: unknown) => boolean +> +type FireEvent = FireEventAsFunction & FireEventAsHelper + +const fireEvent = internalfireEvent as FireEvent export {fireEvent, createEvent} /* eslint complexity:["error", 9] */ diff --git a/types/event-map.d.ts b/types/event-map.d.ts index d9ea5eef..4dd9c4ae 100644 --- a/types/event-map.d.ts +++ b/types/event-map.d.ts @@ -1,4 +1,86 @@ -declare type EventMapKey = string +export declare type EventMapKey = + | 'copy' + | 'cut' + | 'paste' + | 'compositionEnd' + | 'compositionStart' + | 'compositionUpdate' + | 'keyDown' + | 'keyPress' + | 'keyUp' + | 'focus' + | 'blur' + | 'focusIn' + | 'focusOut' + | 'change' + | 'input' + | 'invalid' + | 'submit' + | 'reset' + | 'click' + | 'contextMenu' + | 'dblClick' + | 'drag' + | 'dragEnd' + | 'dragEnter' + | 'dragExit' + | 'dragLeave' + | 'dragOver' + | 'dragStart' + | 'drop' + | 'mouseDown' + | 'mouseEnter' + | 'mouseLeave' + | 'mouseMove' + | 'mouseOut' + | 'mouseOver' + | 'mouseUp' + | 'popState' + | 'select' + | 'touchCancel' + | 'touchEnd' + | 'touchMove' + | 'touchStart' + | 'scroll' + | 'wheel' + | 'abort' + | 'canPlay' + | 'canPlayThrough' + | 'durationChange' + | 'emptied' + | 'encrypted' + | 'ended' + | 'loadedData' + | 'loadedMetadata' + | 'loadStart' + | 'pause' + | 'play' + | 'playing' + | 'progress' + | 'rateChange' + | 'seeked' + | 'seeking' + | 'stalled' + | 'suspend' + | 'timeUpdate' + | 'volumeChange' + | 'waiting' + | 'load' + | 'error' + | 'animationStart' + | 'animationEnd' + | 'animationIteration' + | 'transitionEnd' + | 'pointerOver' + | 'pointerEnter' + | 'pointerDown' + | 'pointerMove' + | 'pointerUp' + | 'pointerCancel' + | 'pointerOut' + | 'pointerLeave' + | 'gotPointerCapture' + | 'lostPointerCapture' declare type LegacyKeyboardEventInit = { charCode?: number } & KeyboardEventInit @@ -68,5 +150,7 @@ declare type EventMapValue = defaultInit: WheelEventInit } export declare const eventMap: Record -export declare const eventAliasMap: Record +declare type EventAliasMapKey = 'doubleClick' +export declare const eventAliasMap: Record +export declare type EventType = EventMapKey | EventAliasMapKey export {} diff --git a/types/events.d.ts b/types/events.d.ts index 50f95145..3b84289f 100644 --- a/types/events.d.ts +++ b/types/events.d.ts @@ -1,104 +1,22 @@ -export type EventType = - | 'copy' - | 'cut' - | 'paste' - | 'compositionEnd' - | 'compositionStart' - | 'compositionUpdate' - | 'keyDown' - | 'keyPress' - | 'keyUp' - | 'focus' - | 'blur' - | 'focusIn' - | 'focusOut' - | 'change' - | 'input' - | 'invalid' - | 'submit' - | 'reset' - | 'click' - | 'contextMenu' - | 'dblClick' - | 'drag' - | 'dragEnd' - | 'dragEnter' - | 'dragExit' - | 'dragLeave' - | 'dragOver' - | 'dragStart' - | 'drop' - | 'mouseDown' - | 'mouseEnter' - | 'mouseLeave' - | 'mouseMove' - | 'mouseOut' - | 'mouseOver' - | 'mouseUp' - | 'popState' - | 'select' - | 'touchCancel' - | 'touchEnd' - | 'touchMove' - | 'touchStart' - | 'scroll' - | 'wheel' - | 'abort' - | 'canPlay' - | 'canPlayThrough' - | 'durationChange' - | 'emptied' - | 'encrypted' - | 'ended' - | 'loadedData' - | 'loadedMetadata' - | 'loadStart' - | 'pause' - | 'play' - | 'playing' - | 'progress' - | 'rateChange' - | 'seeked' - | 'seeking' - | 'stalled' - | 'suspend' - | 'timeUpdate' - | 'volumeChange' - | 'waiting' - | 'load' - | 'error' - | 'animationStart' - | 'animationEnd' - | 'animationIteration' - | 'transitionEnd' - | 'doubleClick' - | 'pointerOver' - | 'pointerEnter' - | 'pointerDown' - | 'pointerMove' - | 'pointerUp' - | 'pointerCancel' - | 'pointerOut' - | 'pointerLeave' - | 'gotPointerCapture' - | 'lostPointerCapture' - -export type FireFunction = ( - element: Document | Element | Window | Node, - event: Event, -) => boolean -export type FireObject = { - [K in EventType]: ( - element: Document | Element | Window | Node, - options?: {}, - ) => boolean +import {EventType} from './event-map' +declare global { + interface Window { + DataTransfer: () => void + Event: () => void + } } -export type CreateObject = { - [K in EventType]: ( - element: Document | Element | Window | Node, - options?: {}, - ) => Event +declare type CreateObject = { + [K in EventType]: (element: EventTarget, options?: {}) => Event } - -export const createEvent: CreateObject -export const fireEvent: FireFunction & FireObject +declare const createEvent: CreateObject +declare type FireEventAsFunction = ( + element: EventTarget, + event: Event, +) => boolean +declare type FireEventAsHelper = Record< + EventType, + (element: EventTarget, init?: unknown) => boolean +> +declare type FireEvent = FireEventAsFunction & FireEventAsHelper +declare const fireEvent: FireEvent +export {fireEvent, createEvent} diff --git a/types/tslint.json b/types/tslint.json index c5f38421..a439c551 100644 --- a/types/tslint.json +++ b/types/tslint.json @@ -2,6 +2,7 @@ "extends": ["dtslint/dtslint.json"], "rules": { "one-variable-per-declaration": false, + "max-line-length": false, "no-redundant-jsdoc": false, "no-useless-files": false, "no-relative-import-in-test": false, From 8a79b4ce756abaa7e4d275897810e39ec7558839 Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Thu, 16 Jul 2020 22:33:30 +0200 Subject: [PATCH 10/16] wait-for.ts --- src/{wait-for.js => wait-for.ts} | 32 +++++++++++++++++++++++++------- types/index.d.ts | 1 - types/queries.d.ts | 14 +++++++------- types/wait-for.d.ts | 22 +++++++++++++++------- types/wait.d.ts | 7 ------- 5 files changed, 47 insertions(+), 29 deletions(-) rename src/{wait-for.js => wait-for.ts} (81%) delete mode 100644 types/wait.d.ts diff --git a/src/wait-for.js b/src/wait-for.ts similarity index 81% rename from src/wait-for.js rename to src/wait-for.ts index b271a00d..db468ea8 100644 --- a/src/wait-for.js +++ b/src/wait-for.ts @@ -17,7 +17,7 @@ function copyStackTrace(target, source) { function waitFor( callback, { - container = getDocument(), + container = getDocument() as Node, timeout = getConfig().asyncUtilTimeout, showOriginalStackTrace = getConfig().showOriginalStackTrace, stackTraceError, @@ -27,7 +27,7 @@ function waitFor( childList: true, attributes: true, characterData: true, - }, + } as MutationObserverInit, }, ) { if (typeof callback !== 'function') { @@ -40,7 +40,9 @@ function waitFor( const overallTimeoutTimer = setTimeout(onTimeout, timeout) const intervalId = setInterval(checkCallback, interval) - const {MutationObserver} = getWindowFromNode(container) + const {MutationObserver} = (getWindowFromNode(container) as unknown) as { + MutationObserver: (callback: MutationCallback) => void + } const observer = new MutationObserver(checkCallback) runWithRealTimers(() => observer.observe(container, mutationObserverOptions), @@ -90,7 +92,15 @@ function waitFor( }) } -function waitForWrapper(callback, options) { +export interface WaitForOptions { + container?: Node + timeout?: number + interval?: number + mutationObserverOptions?: MutationObserverInit + showOriginalStackTrace?: boolean +} + +function waitForWrapper(callback, options?: WaitForOptions) { // create the error here so its stack trace is as close to the // calling code as possible const stackTraceError = new Error('STACK_TRACE_MESSAGE') @@ -103,16 +113,24 @@ let hasWarned = false // deprecated... TODO: remove this method. We renamed this to `waitFor` so the // code people write reads more clearly. -function wait(...args) { +interface WaitOptions { + container?: Node + timeout?: number + interval?: number + mutationObserverOptions?: MutationObserverInit +} +function wait( + first: () => void = () => {}, + options?: WaitOptions, +): Promise { // istanbul ignore next - const [first = () => {}, ...rest] = args if (!hasWarned) { hasWarned = true console.warn( `\`wait\` has been deprecated and replaced by \`waitFor\` instead. In most cases you should be able to find/replace \`wait\` with \`waitFor\`. Learn more: https://testing-library.com/docs/dom-testing-library/api-async#waitfor.`, ) } - return waitForWrapper(first, ...rest) + return waitForWrapper(first, options) } export {waitForWrapper as waitFor, wait} diff --git a/types/index.d.ts b/types/index.d.ts index 38830ff4..8cbe6d33 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -10,7 +10,6 @@ export {queries, queryHelpers, within} export * from './queries' export * from './query-helpers' export * from './screen' -export * from './wait' export * from './wait-for' export * from './wait-for-dom-change' export * from './wait-for-element' diff --git a/types/queries.d.ts b/types/queries.d.ts index a4c535cc..e38df0a6 100644 --- a/types/queries.d.ts +++ b/types/queries.d.ts @@ -1,6 +1,6 @@ import {Matcher, MatcherOptions} from './matches' import {SelectorMatcherOptions} from './query-helpers' -import {waitForOptions} from './wait-for' +import {WaitForOptions} from './wait-for' export type QueryByBoundAttribute = ( container: HTMLElement, @@ -18,7 +18,7 @@ export type FindAllByBoundAttribute = ( container: HTMLElement, id: Matcher, options?: MatcherOptions, - waitForElementOptions?: waitForOptions, + waitForElementOptions?: WaitForOptions, ) => Promise export type GetByBoundAttribute = ( @@ -31,7 +31,7 @@ export type FindByBoundAttribute = ( container: HTMLElement, id: Matcher, options?: MatcherOptions, - waitForElementOptions?: waitForOptions, + waitForElementOptions?: WaitForOptions, ) => Promise export type QueryByText = ( @@ -50,7 +50,7 @@ export type FindAllByText = ( container: HTMLElement, id: Matcher, options?: SelectorMatcherOptions, - waitForElementOptions?: waitForOptions, + waitForElementOptions?: WaitForOptions, ) => Promise export type GetByText = ( @@ -63,7 +63,7 @@ export type FindByText = ( container: HTMLElement, id: Matcher, options?: SelectorMatcherOptions, - waitForElementOptions?: waitForOptions, + waitForElementOptions?: WaitForOptions, ) => Promise export interface ByRoleOptions extends MatcherOptions { @@ -114,14 +114,14 @@ export type FindByRole = ( container: HTMLElement, role: Matcher, options?: ByRoleOptions, - waitForElementOptions?: waitForOptions, + waitForElementOptions?: WaitForOptions, ) => Promise export type FindAllByRole = ( container: HTMLElement, role: Matcher, options?: ByRoleOptions, - waitForElementOptions?: waitForOptions, + waitForElementOptions?: WaitForOptions, ) => Promise export const getByLabelText: GetByText diff --git a/types/wait-for.d.ts b/types/wait-for.d.ts index 0fd0e56a..9e863eab 100644 --- a/types/wait-for.d.ts +++ b/types/wait-for.d.ts @@ -1,11 +1,19 @@ -export interface waitForOptions { - container?: HTMLElement +export interface WaitForOptions { + container?: Node timeout?: number interval?: number mutationObserverOptions?: MutationObserverInit + showOriginalStackTrace?: boolean } - -export function waitFor( - callback: () => T extends Promise ? never : T, - options?: waitForOptions, -): Promise +declare function waitForWrapper( + callback: any, + options?: WaitForOptions, +): Promise +interface WaitOptions { + container?: Node + timeout?: number + interval?: number + mutationObserverOptions?: MutationObserverInit +} +declare function wait(first?: () => void, options?: WaitOptions): Promise +export {waitForWrapper as waitFor, wait} diff --git a/types/wait.d.ts b/types/wait.d.ts deleted file mode 100644 index cb102637..00000000 --- a/types/wait.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -export function wait( - callback?: () => void, - options?: { - timeout?: number - interval?: number - }, -): Promise From f8becd75c527fb40dcfe77916901bbc3aaa4763e Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Thu, 16 Jul 2020 23:25:23 +0200 Subject: [PATCH 11/16] wait-for-element.ts --- src/{wait-for-element.js => wait-for-element.ts} | 7 +++++-- src/wait-for.ts | 5 ++++- types/query-helpers.d.ts | 6 +++--- types/wait-for-dom-change.d.ts | 4 ++-- types/wait-for-element-to-be-removed.d.ts | 4 ++-- types/wait-for-element.d.ts | 10 +++++----- types/wait-for.d.ts | 6 +++--- 7 files changed, 24 insertions(+), 18 deletions(-) rename src/{wait-for-element.js => wait-for-element.ts} (82%) diff --git a/src/wait-for-element.js b/src/wait-for-element.ts similarity index 82% rename from src/wait-for-element.js rename to src/wait-for-element.ts index 060f17be..8bc585d9 100644 --- a/src/wait-for-element.js +++ b/src/wait-for-element.ts @@ -1,11 +1,14 @@ -import {waitFor} from './wait-for' +import {waitFor, WaitForOptions} from './wait-for' let hasWarned = false // deprecated... TODO: remove this method. People should use a find* query or // wait instead the reasoning is that this doesn't really do anything useful // that you can't get from using find* or wait. -async function waitForElement(callback, options) { +async function waitForElement( + callback: () => T extends Promise ? never : T, + options?: WaitForOptions, +): Promise { if (!hasWarned) { hasWarned = true console.warn( diff --git a/src/wait-for.ts b/src/wait-for.ts index db468ea8..7a25f6ef 100644 --- a/src/wait-for.ts +++ b/src/wait-for.ts @@ -100,7 +100,10 @@ export interface WaitForOptions { showOriginalStackTrace?: boolean } -function waitForWrapper(callback, options?: WaitForOptions) { +function waitForWrapper( + callback: () => T extends Promise ? never : T, + options?: WaitForOptions, +): Promise { // create the error here so its stack trace is as close to the // calling code as possible const stackTraceError = new Error('STACK_TRACE_MESSAGE') diff --git a/types/query-helpers.d.ts b/types/query-helpers.d.ts index 2c848f29..931bc27d 100644 --- a/types/query-helpers.d.ts +++ b/types/query-helpers.d.ts @@ -1,5 +1,5 @@ import {Matcher, MatcherOptions} from './matches' -import {waitForOptions} from './wait-for' +import {WaitForOptions} from './wait-for' export interface SelectorMatcherOptions extends MatcherOptions { selector?: string @@ -39,12 +39,12 @@ export type GetAllBy = QueryMethod< HTMLElement[] > export type FindAllBy = QueryMethod< - [Arguments[0], Arguments[1], waitForOptions], + [Arguments[0], Arguments[1], WaitForOptions], Promise > export type GetBy = QueryMethod export type FindBy = QueryMethod< - [Arguments[0], Arguments[1], waitForOptions], + [Arguments[0], Arguments[1], WaitForOptions], Promise > diff --git a/types/wait-for-dom-change.d.ts b/types/wait-for-dom-change.d.ts index dcd9d51f..5d3cd4c9 100644 --- a/types/wait-for-dom-change.d.ts +++ b/types/wait-for-dom-change.d.ts @@ -1,3 +1,3 @@ -import {waitForOptions} from './wait-for' +import {WaitForOptions} from './wait-for' -export function waitForDomChange(options?: waitForOptions): Promise +export function waitForDomChange(options?: WaitForOptions): Promise diff --git a/types/wait-for-element-to-be-removed.d.ts b/types/wait-for-element-to-be-removed.d.ts index f86e6315..c7cd94e6 100644 --- a/types/wait-for-element-to-be-removed.d.ts +++ b/types/wait-for-element-to-be-removed.d.ts @@ -1,6 +1,6 @@ -import {waitForOptions} from './wait-for' +import {WaitForOptions} from './wait-for' export function waitForElementToBeRemoved( callback: (() => T) | T, - options?: waitForOptions, + options?: WaitForOptions, ): Promise diff --git a/types/wait-for-element.d.ts b/types/wait-for-element.d.ts index 04028f6d..751565da 100644 --- a/types/wait-for-element.d.ts +++ b/types/wait-for-element.d.ts @@ -1,6 +1,6 @@ -import {waitForOptions} from './wait-for' - -export function waitForElement( - callback: () => T, - options?: waitForOptions, +import {WaitForOptions} from './wait-for' +declare function waitForElement( + callback: () => T extends Promise ? never : T, + options?: WaitForOptions, ): Promise +export {waitForElement} diff --git a/types/wait-for.d.ts b/types/wait-for.d.ts index 9e863eab..1747c58f 100644 --- a/types/wait-for.d.ts +++ b/types/wait-for.d.ts @@ -5,10 +5,10 @@ export interface WaitForOptions { mutationObserverOptions?: MutationObserverInit showOriginalStackTrace?: boolean } -declare function waitForWrapper( - callback: any, +declare function waitForWrapper( + callback: () => T extends Promise ? never : T, options?: WaitForOptions, -): Promise +): Promise interface WaitOptions { container?: Node timeout?: number From 62b98d898bfa440530fc272cff314b30402f4c6f Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Fri, 24 Jul 2020 15:45:41 +0200 Subject: [PATCH 12/16] wait-for-element-to-be-removed --- ...ed.js => wait-for-element-to-be-removed.ts} | 18 ++++++++++++------ types/wait-for-element-to-be-removed.d.ts | 8 ++++---- 2 files changed, 16 insertions(+), 10 deletions(-) rename src/{wait-for-element-to-be-removed.js => wait-for-element-to-be-removed.ts} (75%) diff --git a/src/wait-for-element-to-be-removed.js b/src/wait-for-element-to-be-removed.ts similarity index 75% rename from src/wait-for-element-to-be-removed.js rename to src/wait-for-element-to-be-removed.ts index 0703b575..4a2a38b8 100644 --- a/src/wait-for-element-to-be-removed.js +++ b/src/wait-for-element-to-be-removed.ts @@ -1,4 +1,4 @@ -import {waitFor} from './wait-for' +import {waitFor, WaitForOptions} from './wait-for' const isRemoved = result => !result || (Array.isArray(result) && !result.length) @@ -12,26 +12,32 @@ function initialCheck(elements) { } } -async function waitForElementToBeRemoved(callback, options) { +async function waitForElementToBeRemoved( + callback: (() => T | T[]) | T | T[], + options?: WaitForOptions, +) { // created here so we get a nice stacktrace const timeoutError = new Error('Timed out in waitForElementToBeRemoved.') + let cb if (typeof callback !== 'function') { initialCheck(callback) - const elements = Array.isArray(callback) ? callback : [callback] + const elements: Array = Array.isArray(callback) ? callback : [callback] const getRemainingElements = elements.map(element => { let parent = element.parentElement while (parent.parentElement) parent = parent.parentElement return () => (parent.contains(element) ? element : null) }) - callback = () => getRemainingElements.map(c => c()).filter(Boolean) + cb = () => getRemainingElements.map(c => c()).filter(Boolean) + } else { + cb = callback } - initialCheck(callback()) + initialCheck(cb()) return waitFor(() => { let result try { - result = callback() + result = cb() } catch (error) { if (error.name === 'TestingLibraryElementError') { return true diff --git a/types/wait-for-element-to-be-removed.d.ts b/types/wait-for-element-to-be-removed.d.ts index c7cd94e6..df3139e0 100644 --- a/types/wait-for-element-to-be-removed.d.ts +++ b/types/wait-for-element-to-be-removed.d.ts @@ -1,6 +1,6 @@ import {WaitForOptions} from './wait-for' - -export function waitForElementToBeRemoved( - callback: (() => T) | T, +declare function waitForElementToBeRemoved( + callback: (() => T | T[]) | T | T[], options?: WaitForOptions, -): Promise +): Promise +export {waitForElementToBeRemoved} From 28e4b181fcc708b1ab24c7cde15d278d6ae62a02 Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Fri, 24 Jul 2020 16:49:40 +0200 Subject: [PATCH 13/16] role-helpers --- src/{role-helpers.js => role-helpers.ts} | 24 +++++---- types/role-helpers.d.ts | 69 +++++++++++++++++++++--- 2 files changed, 78 insertions(+), 15 deletions(-) rename src/{role-helpers.js => role-helpers.ts} (89%) diff --git a/src/role-helpers.js b/src/role-helpers.ts similarity index 89% rename from src/role-helpers.js rename to src/role-helpers.ts index f42e3e14..4992a21a 100644 --- a/src/role-helpers.js +++ b/src/role-helpers.ts @@ -8,7 +8,7 @@ const elementRoleList = buildElementRoleList(elementRoles) * @param {Element} element - * @returns {boolean} - `true` if `element` and its subtree are inaccessible */ -function isSubtreeInaccessible(element) { +function isSubtreeInaccessible(element: HTMLElement): boolean { if (element.hidden === true) { return true } @@ -25,6 +25,9 @@ function isSubtreeInaccessible(element) { return false } +interface IsInaccessibleOptions { + isSubtreeInaccessible?: typeof isSubtreeInaccessible +} /** * Partial implementation https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion * which should only be used for elements with a non-presentational role i.e. @@ -39,7 +42,10 @@ function isSubtreeInaccessible(element) { * can be used to return cached results from previous isSubtreeInaccessible calls * @returns {boolean} true if excluded, otherwise false */ -function isInaccessible(element, options = {}) { +function isInaccessible( + element: HTMLElement, + options: IsInaccessibleOptions = {}, +): boolean { const { isSubtreeInaccessible: isSubtreeInaccessibleImpl = isSubtreeInaccessible, } = options @@ -118,8 +124,8 @@ function buildElementRoleList(elementRolesMap) { return result.sort(bySelectorSpecificity) } -function getRoles(container, {hidden = false} = {}) { - function flattenDOM(node) { +function getRoles(container, {hidden = false} = {}): Record { + function flattenDOM(node: ParentNode) { return [ node, ...Array.from(node.children).reduce( @@ -133,8 +139,8 @@ function getRoles(container, {hidden = false} = {}) { .filter(element => { return hidden === false ? isInaccessible(element) === false : true }) - .reduce((acc, node) => { - let roles = [] + .reduce((acc, node: Element) => { + let roles: Array = [] // TODO: This violates html-aria which does not allow any role on every element if (node.hasAttribute('role')) { roles = node.getAttribute('role').split(' ').slice(0, 1) @@ -152,7 +158,7 @@ function getRoles(container, {hidden = false} = {}) { }, {}) } -function prettyRoles(dom, {hidden}) { +function prettyRoles(dom: HTMLElement, {hidden}) { const roles = getRoles(dom, {hidden}) return Object.entries(roles) @@ -161,7 +167,7 @@ function prettyRoles(dom, {hidden}) { const elementsString = elements .map(el => { const nameString = `Name "${computeAccessibleName(el)}":\n` - const domString = prettyDOM(el.cloneNode(false)) + const domString = prettyDOM(el.cloneNode(false) as Element) return `${nameString}${domString}` }) .join('\n\n') @@ -171,7 +177,7 @@ function prettyRoles(dom, {hidden}) { .join('\n') } -const logRoles = (dom, {hidden = false} = {}) => +const logRoles = (dom: HTMLElement, {hidden = false} = {}) => console.log(prettyRoles(dom, {hidden})) /** diff --git a/types/role-helpers.d.ts b/types/role-helpers.d.ts index 06565f7f..94b588fe 100644 --- a/types/role-helpers.d.ts +++ b/types/role-helpers.d.ts @@ -1,8 +1,65 @@ -export function logRoles(container: HTMLElement): string -export function getRoles( - container: HTMLElement, -): {[index: string]: HTMLElement[]} /** - * https://testing-library.com/docs/dom-testing-library/api-helpers#isinaccessible + * @param {Element} element - + * @returns {boolean} - `true` if `element` and its subtree are inaccessible */ -export function isInaccessible(element: Element): boolean +declare function isSubtreeInaccessible(element: HTMLElement): boolean +interface IsInaccessibleOptions { + isSubtreeInaccessible?: typeof isSubtreeInaccessible +} +/** + * Partial implementation https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion + * which should only be used for elements with a non-presentational role i.e. + * `role="none"` and `role="presentation"` will not be excluded. + * + * Implements aria-hidden semantics (i.e. parent overrides child) + * Ignores "Child Presentational: True" characteristics + * + * @param {Element} element - + * @param {object} [options] - + * @param {function (element: Element): boolean} options.isSubtreeInaccessible - + * can be used to return cached results from previous isSubtreeInaccessible calls + * @returns {boolean} true if excluded, otherwise false + */ +declare function isInaccessible( + element: HTMLElement, + options?: IsInaccessibleOptions, +): boolean +declare function getImplicitAriaRoles(currentNode: any): any[] +declare function getRoles( + container: any, + { + hidden, + }?: { + hidden?: boolean + }, +): Record +declare function prettyRoles( + dom: HTMLElement, + { + hidden, + }: { + hidden: any + }, +): string +declare const logRoles: ( + dom: HTMLElement, + { + hidden, + }?: { + hidden?: boolean + }, +) => void +/** + * @param {Element} element - + * @returns {boolean | undefined} - false/true if (not)selected, undefined if not selectable + */ +declare function computeAriaSelected(element: any): any +export { + getRoles, + logRoles, + getImplicitAriaRoles, + isSubtreeInaccessible, + prettyRoles, + isInaccessible, + computeAriaSelected, +} From b4e8342253b7391daf8589e521c292eeceafc357 Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Fri, 24 Jul 2020 17:06:11 +0200 Subject: [PATCH 14/16] suggestions --- src/{suggestions.js => suggestions.ts} | 45 ++++++++++++++++++++++---- types/suggestions.d.ts | 6 ++-- 2 files changed, 42 insertions(+), 9 deletions(-) rename src/{suggestions.js => suggestions.ts} (69%) diff --git a/src/suggestions.js b/src/suggestions.ts similarity index 69% rename from src/suggestions.js rename to src/suggestions.ts index ff960d68..88e7098b 100644 --- a/src/suggestions.js +++ b/src/suggestions.ts @@ -6,10 +6,19 @@ import {getImplicitAriaRoles} from './role-helpers' const normalize = getDefaultNormalizer() -function getLabelTextFor(element) { - let label = - element.labels && - Array.from(element.labels).find(el => Boolean(normalize(el.textContent))) +function isElementWithLabels( + element: HTMLElement, +): element is HTMLInputElement { + // We cast with HTMLInputElement, but it could be a HTMLSelectElement + return (element as HTMLInputElement).labels !== undefined +} + +function getLabelTextFor(element: HTMLElement): string | undefined { + let label: HTMLLabelElement | undefined = + isElementWithLabels(element) && + Array.from(element.labels).find((el: HTMLLabelElement) => + Boolean(normalize(el.textContent)), + ) // non form elements that are using aria-labelledby won't be included in `element.labels` if (!label) { @@ -30,7 +39,16 @@ function escapeRegExp(string) { return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&') // $& means the whole matched string } -function makeSuggestion(queryName, content, {variant = 'get', name}) { +interface MakeSuggestionOptions { + variant?: string + name?: string +} + +function makeSuggestion( + queryName, + content, + {variant = 'get', name}: MakeSuggestionOptions, +) { const queryArgs = [content] if (name) { @@ -55,7 +73,20 @@ function makeSuggestion(queryName, content, {variant = 'get', name}) { } } -export function getSuggestedQuery(element, variant) { +function isElementWithValue(element: HTMLElement): element is HTMLInputElement { + // We cast with HTMLInputElement, but it could be a HTMLSelectElement + return Boolean((element as HTMLInputElement).value) +} + +export interface Suggestion { + queryName: string + toString(): string +} + +export function getSuggestedQuery( + element: HTMLElement, + variant?: string, +): Suggestion | undefined { const role = element.getAttribute('role') ?? getImplicitAriaRoles(element)?.[0] if (role) { @@ -80,7 +111,7 @@ export function getSuggestedQuery(element, variant) { return makeSuggestion('Text', textContent, {variant}) } - if (element.value) { + if (isElementWithValue(element)) { return makeSuggestion('DisplayValue', normalize(element.value), {variant}) } diff --git a/types/suggestions.d.ts b/types/suggestions.d.ts index f574f344..05c13cca 100644 --- a/types/suggestions.d.ts +++ b/types/suggestions.d.ts @@ -2,5 +2,7 @@ export interface Suggestion { queryName: string toString(): string } - -export function getSuggestedQuery(element: HTMLElement): Suggestion | undefined +export declare function getSuggestedQuery( + element: HTMLElement, + variant?: string, +): Suggestion | undefined From 385625e33497de4e240a1015297cf9b8a85b5928 Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Fri, 24 Jul 2020 18:53:59 +0200 Subject: [PATCH 15/16] Migrate the rest of src (not stable yet) --- src/get-queries-for-element.js | 25 --- .../get-queries-for-element.ts | 23 ++- src/{index.js => index.ts} | 0 src/matches.ts | 2 +- src/queries/{all-utils.js => all-utils.ts} | 0 src/queries/{alt-text.js => alt-text.ts} | 21 ++- .../{display-value.js => display-value.ts} | 21 ++- src/queries/{index.js => index.ts} | 0 src/queries/{label-text.js => label-text.ts} | 27 ++- ...laceholder-text.js => placeholder-text.ts} | 17 +- src/queries/{role.js => role.ts} | 47 ++++- src/queries/{test-id.js => test-id.ts} | 18 +- src/queries/{text.js => text.ts} | 20 +- src/queries/{title.js => title.ts} | 12 +- src/{query-helpers.js => query-helpers.ts} | 89 +++++++-- src/{screen.js => screen.ts} | 0 ...r-dom-change.js => wait-for-dom-change.ts} | 9 +- types/config.d.ts | 23 --- types/event-map.d.ts | 156 ---------------- types/events.d.ts | 22 --- types/get-node-text.d.ts | 2 - types/helpers.d.ts | 14 -- types/index.d.ts | 24 --- types/matches.d.ts | 55 ------ types/pretty-dom.d.ts | 19 -- types/queries.d.ts | 174 ------------------ types/query-helpers.d.ts | 62 ------- types/role-helpers.d.ts | 65 ------- types/screen.d.ts | 17 -- types/suggestions.d.ts | 8 - types/wait-for-dom-change.d.ts | 3 - types/wait-for-element-to-be-removed.d.ts | 6 - types/wait-for-element.d.ts | 6 - types/wait-for.d.ts | 19 -- 34 files changed, 235 insertions(+), 771 deletions(-) delete mode 100644 src/get-queries-for-element.js rename types/get-queries-for-element.d.ts => src/get-queries-for-element.ts (56%) rename src/{index.js => index.ts} (100%) rename src/queries/{all-utils.js => all-utils.ts} (100%) rename src/queries/{alt-text.js => alt-text.ts} (73%) rename src/queries/{display-value.js => display-value.ts} (74%) rename src/queries/{index.js => index.ts} (100%) rename src/queries/{label-text.js => label-text.ts} (92%) rename src/queries/{placeholder-text.js => placeholder-text.ts} (73%) rename src/queries/{role.js => role.ts} (78%) rename src/queries/{test-id.js => test-id.ts} (71%) rename src/queries/{text.js => text.ts} (80%) rename src/queries/{title.js => title.ts} (86%) rename src/{query-helpers.js => query-helpers.ts} (67%) rename src/{screen.js => screen.ts} (100%) rename src/{wait-for-dom-change.js => wait-for-dom-change.ts} (85%) delete mode 100644 types/config.d.ts delete mode 100644 types/event-map.d.ts delete mode 100644 types/events.d.ts delete mode 100644 types/get-node-text.d.ts delete mode 100644 types/helpers.d.ts delete mode 100644 types/index.d.ts delete mode 100644 types/matches.d.ts delete mode 100644 types/pretty-dom.d.ts delete mode 100644 types/queries.d.ts delete mode 100644 types/query-helpers.d.ts delete mode 100644 types/role-helpers.d.ts delete mode 100644 types/screen.d.ts delete mode 100644 types/suggestions.d.ts delete mode 100644 types/wait-for-dom-change.d.ts delete mode 100644 types/wait-for-element-to-be-removed.d.ts delete mode 100644 types/wait-for-element.d.ts delete mode 100644 types/wait-for.d.ts diff --git a/src/get-queries-for-element.js b/src/get-queries-for-element.js deleted file mode 100644 index cc81578b..00000000 --- a/src/get-queries-for-element.js +++ /dev/null @@ -1,25 +0,0 @@ -import * as defaultQueries from './queries' - -/** - * @typedef {{[key: string]: Function}} FuncMap - */ - -/** - * @param {HTMLElement} element container - * @param {FuncMap} queries object of functions - * @param {Object} initialValue for reducer - * @returns {FuncMap} returns object of functions bound to container - */ -function getQueriesForElement( - element, - queries = defaultQueries, - initialValue = {}, -) { - return Object.keys(queries).reduce((helpers, key) => { - const fn = queries[key] - helpers[key] = fn.bind(null, element) - return helpers - }, initialValue) -} - -export {getQueriesForElement} diff --git a/types/get-queries-for-element.d.ts b/src/get-queries-for-element.ts similarity index 56% rename from types/get-queries-for-element.d.ts rename to src/get-queries-for-element.ts index 79abde82..10e8a3a6 100644 --- a/types/get-queries-for-element.d.ts +++ b/src/get-queries-for-element.ts @@ -1,4 +1,4 @@ -import * as queries from './queries' +import * as defaultQueries from './queries' export type BoundFunction = T extends ( attribute: string, @@ -34,7 +34,22 @@ export interface Queries { [T: string]: Query } -export function getQueriesForElement( +/** + * @param {HTMLElement} element container + * @param {FuncMap} queries object of functions + * @param {Object} initialValue for reducer + * @returns {FuncMap} returns object of functions bound to container + */ +function getQueriesForElement( element: HTMLElement, - queriesToBind?: T, -): BoundFunctions + queries: Queries = defaultQueries, + initialValue = {}, +): BoundFunctions { + return Object.keys(queries).reduce((helpers, key) => { + const fn: Query = queries[key] + helpers[key] = fn.bind(null, element) + return helpers + }, initialValue) as BoundFunctions +} + +export {getQueriesForElement} diff --git a/src/index.js b/src/index.ts similarity index 100% rename from src/index.js rename to src/index.ts diff --git a/src/matches.ts b/src/matches.ts index e135b42c..30ddaea1 100644 --- a/src/matches.ts +++ b/src/matches.ts @@ -36,7 +36,7 @@ function fuzzyMatches( } function matches( - textToMatch: string, + textToMatch: string | undefined, node: HTMLElement | null, matcher: Matcher, normalizer: NormalizerFn, diff --git a/src/queries/all-utils.js b/src/queries/all-utils.ts similarity index 100% rename from src/queries/all-utils.js rename to src/queries/all-utils.ts diff --git a/src/queries/alt-text.js b/src/queries/alt-text.ts similarity index 73% rename from src/queries/alt-text.js rename to src/queries/alt-text.ts index a31c5164..c4e9a3e4 100644 --- a/src/queries/alt-text.js +++ b/src/queries/alt-text.ts @@ -1,18 +1,27 @@ import {wrapAllByQueryWithSuggestion} from '../query-helpers' import {checkContainerType} from '../helpers' -import {matches, fuzzyMatches, makeNormalizer, buildQueries} from './all-utils' +import { + matches, + fuzzyMatches, + makeNormalizer, + buildQueries, + MatcherOptions, + Matcher, +} from './all-utils' function queryAllByAltText( - container, - alt, - {exact = true, collapseWhitespace, trim, normalizer} = {}, + container: HTMLElement, + alt: Matcher, + {exact = true, collapseWhitespace, trim, normalizer}: MatcherOptions = {}, ) { checkContainerType(container) const matcher = exact ? matches : fuzzyMatches const matchNormalizer = makeNormalizer({collapseWhitespace, trim, normalizer}) - return Array.from(container.querySelectorAll('img,input,area')).filter(node => + return Array.from( + container.querySelectorAll('img,input,area'), + ).filter((node: HTMLElement) => matcher(node.getAttribute('alt'), node, alt, matchNormalizer), - ) + ) as HTMLElement[] } const getMultipleError = (c, alt) => diff --git a/src/queries/display-value.js b/src/queries/display-value.ts similarity index 74% rename from src/queries/display-value.js rename to src/queries/display-value.ts index 75ab083f..190db702 100644 --- a/src/queries/display-value.js +++ b/src/queries/display-value.ts @@ -6,30 +6,37 @@ import { fuzzyMatches, makeNormalizer, buildQueries, + Matcher, + MatcherOptions, } from './all-utils' +function getElementValue(element: Element): string | undefined { + return (element as any).value +} + function queryAllByDisplayValue( - container, - value, - {exact = true, collapseWhitespace, trim, normalizer} = {}, + container: HTMLElement, + value: Matcher, + {exact = true, collapseWhitespace, trim, normalizer}: MatcherOptions = {}, ) { checkContainerType(container) const matcher = exact ? matches : fuzzyMatches const matchNormalizer = makeNormalizer({collapseWhitespace, trim, normalizer}) return Array.from(container.querySelectorAll(`input,textarea,select`)).filter( - node => { + (node: HTMLElement) => { if (node.tagName === 'SELECT') { - const selectedOptions = Array.from(node.options).filter( + const selectElement = node as HTMLSelectElement + const selectedOptions = Array.from(selectElement.options).filter( option => option.selected, ) return selectedOptions.some(optionNode => matcher(getNodeText(optionNode), optionNode, value, matchNormalizer), ) } else { - return matcher(node.value, node, value, matchNormalizer) + return matcher(getElementValue(node), node, value, matchNormalizer) } }, - ) + ) as HTMLElement[] } const getMultipleError = (c, value) => diff --git a/src/queries/index.js b/src/queries/index.ts similarity index 100% rename from src/queries/index.js rename to src/queries/index.ts diff --git a/src/queries/label-text.js b/src/queries/label-text.ts similarity index 92% rename from src/queries/label-text.js rename to src/queries/label-text.ts index e7eda117..d571d18c 100644 --- a/src/queries/label-text.js +++ b/src/queries/label-text.ts @@ -9,13 +9,16 @@ import { makeSingleQuery, wrapAllByQueryWithSuggestion, wrapSingleQueryWithSuggestion, + Matcher, + MatcherOptions, + SelectorMatcherOptions, } from './all-utils' import {queryAllByText} from './text' function queryAllLabelsByText( - container, - text, - {exact = true, trim, collapseWhitespace, normalizer} = {}, + container: HTMLElement, + text: Matcher, + {exact = true, trim, collapseWhitespace, normalizer}: MatcherOptions = {}, ) { const matcher = exact ? matches : fuzzyMatches const matchNormalizer = makeNormalizer({collapseWhitespace, trim, normalizer}) @@ -35,13 +38,19 @@ function queryAllLabelsByText( }) return matcher(textToMatch, label, text, matchNormalizer) - }) + }) as HTMLElement[] } function queryAllByLabelText( - container, - text, - {selector = '*', exact = true, collapseWhitespace, trim, normalizer} = {}, + container: HTMLElement, + text: Matcher, + { + selector = '*', + exact = true, + collapseWhitespace, + trim, + normalizer, + }: SelectorMatcherOptions = {}, ) { checkContainerType(container) @@ -51,7 +60,7 @@ function queryAllByLabelText( normalizer: matchNormalizer, }) const labelledElements = labels - .reduce((matchedElements, label) => { + .reduce((matchedElements, label: HTMLLabelElement) => { const elementsForLabel = [] if (label.control) { elementsForLabel.push(label.control) @@ -112,7 +121,7 @@ function queryAllByLabelText( return Array.from( new Set([...labelledElements, ...ariaLabelledElements]), - ).filter(element => element.matches(selector)) + ).filter(element => element.matches(selector)) as HTMLElement[] } // the getAll* query would normally look like this: diff --git a/src/queries/placeholder-text.js b/src/queries/placeholder-text.ts similarity index 73% rename from src/queries/placeholder-text.js rename to src/queries/placeholder-text.ts index bdea5945..7fc9a6d9 100644 --- a/src/queries/placeholder-text.js +++ b/src/queries/placeholder-text.ts @@ -1,10 +1,19 @@ import {wrapAllByQueryWithSuggestion} from '../query-helpers' import {checkContainerType} from '../helpers' -import {queryAllByAttribute, buildQueries} from './all-utils' +import { + queryAllByAttribute, + buildQueries, + Matcher, + MatcherOptions, +} from './all-utils' -function queryAllByPlaceholderText(...args) { - checkContainerType(...args) - return queryAllByAttribute('placeholder', ...args) +function queryAllByPlaceholderText( + container: HTMLElement, + placeholder: Matcher, + options?: MatcherOptions, +) { + checkContainerType(container) + return queryAllByAttribute('placeholder', container, placeholder, options) } const getMultipleError = (c, text) => `Found multiple elements with the placeholder text of: ${text}` diff --git a/src/queries/role.js b/src/queries/role.ts similarity index 78% rename from src/queries/role.js rename to src/queries/role.ts index 07fe0771..ab77e82d 100644 --- a/src/queries/role.js +++ b/src/queries/role.ts @@ -14,12 +14,40 @@ import { fuzzyMatches, getConfig, makeNormalizer, + Matcher, + MatcherOptions, matches, } from './all-utils' +export interface ByRoleOptions extends MatcherOptions { + /** + * If true includes elements in the query set that are usually excluded from + * the accessibility tree. `role="none"` or `role="presentation"` are included + * in either case. + */ + hidden?: boolean + /** + * If true only includes elements in the query set that are marked as + * selected in the accessibility tree, i.e., `aria-selected="true"` + */ + selected?: boolean + /** + * Includes every role used in the `role` attribute + * For example *ByRole('progressbar', {queryFallbacks: true})` will find
`. + */ + queryFallbacks?: boolean + /** + * Only considers elements with the specified accessible name. + */ + name?: + | string + | RegExp + | ((accessibleName: string, element: Element) => boolean) +} + function queryAllByRole( - container, - role, + container: HTMLElement, + role: Matcher, { exact = true, collapseWhitespace, @@ -29,7 +57,7 @@ function queryAllByRole( normalizer, queryFallbacks = false, selected, - } = {}, + }: ByRoleOptions = {}, ) { checkContainerType(container) const matcher = exact ? matches : fuzzyMatches @@ -52,7 +80,7 @@ function queryAllByRole( } return Array.from(container.querySelectorAll('*')) - .filter(node => { + .filter((node: HTMLElement) => { const isRoleSpecifiedExplicitly = node.hasAttribute('role') if (isRoleSpecifiedExplicitly) { @@ -85,14 +113,14 @@ function queryAllByRole( // don't care if aria attributes are unspecified return true }) - .filter(element => { + .filter((element: HTMLElement) => { return hidden === false ? isInaccessible(element, { isSubtreeInaccessible: cachedIsSubtreeInaccessible, }) === false : true }) - .filter(element => { + .filter((element: HTMLElement) => { if (name === undefined) { // Don't care return true @@ -104,7 +132,7 @@ function queryAllByRole( name, text => text, ) - }) + }) as HTMLElement[] } const getMultipleError = (c, role) => @@ -113,16 +141,17 @@ const getMultipleError = (c, role) => const getMissingError = ( container, role, - {hidden = getConfig().defaultHidden, name} = {}, + {hidden = getConfig().defaultHidden, name}: ByRoleOptions = {}, ) => { if (getConfig()._disableExpensiveErrorDiagnostics) { return `Unable to find role="${role}"` } let roles = '' - Array.from(container.children).forEach(childElement => { + Array.from(container.children).forEach((childElement: HTMLElement) => { roles += prettyRoles(childElement, { hidden, + // @ts-ignore FIXME remove this code? prettyRoles does not seem handle 'includeName' includeName: name !== undefined, }) }) diff --git a/src/queries/test-id.js b/src/queries/test-id.ts similarity index 71% rename from src/queries/test-id.js rename to src/queries/test-id.ts index f2ef5a9d..2ab618d5 100644 --- a/src/queries/test-id.js +++ b/src/queries/test-id.ts @@ -1,12 +1,22 @@ import {checkContainerType} from '../helpers' import {wrapAllByQueryWithSuggestion} from '../query-helpers' -import {queryAllByAttribute, getConfig, buildQueries} from './all-utils' +import { + queryAllByAttribute, + getConfig, + buildQueries, + Matcher, + MatcherOptions, +} from './all-utils' const getTestIdAttribute = () => getConfig().testIdAttribute -function queryAllByTestId(...args) { - checkContainerType(...args) - return queryAllByAttribute(getTestIdAttribute(), ...args) +function queryAllByTestId( + container: HTMLElement, + testId: Matcher, + options?: MatcherOptions, +) { + checkContainerType(container) + return queryAllByAttribute(getTestIdAttribute(), container, testId, options) } const getMultipleError = (c, id) => diff --git a/src/queries/text.js b/src/queries/text.ts similarity index 80% rename from src/queries/text.js rename to src/queries/text.ts index 903bba25..5cbdfe46 100644 --- a/src/queries/text.js +++ b/src/queries/text.ts @@ -1,4 +1,7 @@ -import {wrapAllByQueryWithSuggestion} from '../query-helpers' +import { + SelectorMatcherOptions, + wrapAllByQueryWithSuggestion, +} from '../query-helpers' import {checkContainerType} from '../helpers' import {DEFAULT_IGNORE_TAGS} from '../config' import { @@ -7,11 +10,16 @@ import { makeNormalizer, getNodeText, buildQueries, + Matcher, } from './all-utils' +interface ByTextSelectorMatcherOptions extends SelectorMatcherOptions { + ignore?: string +} + function queryAllByText( - container, - text, + container: HTMLElement, + text: Matcher, { selector = '*', exact = true, @@ -19,7 +27,7 @@ function queryAllByText( trim, ignore = DEFAULT_IGNORE_TAGS, normalizer, - } = {}, + }: ByTextSelectorMatcherOptions = {}, ) { checkContainerType(container) const matcher = exact ? matches : fuzzyMatches @@ -30,7 +38,9 @@ function queryAllByText( } return [...baseArray, ...Array.from(container.querySelectorAll(selector))] .filter(node => !ignore || !node.matches(ignore)) - .filter(node => matcher(getNodeText(node), node, text, matchNormalizer)) + .filter(node => + matcher(getNodeText(node), node, text, matchNormalizer), + ) as HTMLElement[] } const getMultipleError = (c, text) => diff --git a/src/queries/title.js b/src/queries/title.ts similarity index 86% rename from src/queries/title.js rename to src/queries/title.ts index ee304466..f10e740f 100644 --- a/src/queries/title.js +++ b/src/queries/title.ts @@ -6,21 +6,23 @@ import { makeNormalizer, getNodeText, buildQueries, + Matcher, + MatcherOptions, } from './all-utils' function queryAllByTitle( - container, - text, - {exact = true, collapseWhitespace, trim, normalizer} = {}, + container: HTMLElement, + text: Matcher, + {exact = true, collapseWhitespace, trim, normalizer}: MatcherOptions = {}, ) { checkContainerType(container) const matcher = exact ? matches : fuzzyMatches const matchNormalizer = makeNormalizer({collapseWhitespace, trim, normalizer}) return Array.from(container.querySelectorAll('[title], svg > title')).filter( - node => + (node: HTMLElement) => matcher(node.getAttribute('title'), node, text, matchNormalizer) || matcher(getNodeText(node), node, text, matchNormalizer), - ) + ) as HTMLElement[] } const getMultipleError = (c, title) => diff --git a/src/query-helpers.js b/src/query-helpers.ts similarity index 67% rename from src/query-helpers.js rename to src/query-helpers.ts index cd4c3481..8a090385 100644 --- a/src/query-helpers.js +++ b/src/query-helpers.ts @@ -1,13 +1,27 @@ import {getSuggestedQuery} from './suggestions' -import {fuzzyMatches, matches, makeNormalizer} from './matches' -import {waitFor} from './wait-for' +import { + fuzzyMatches, + matches, + makeNormalizer, + Matcher, + MatcherOptions, +} from './matches' +import {waitFor, WaitForOptions} from './wait-for' import {getConfig} from './config' -function getElementError(message, container) { +export interface SelectorMatcherOptions extends MatcherOptions { + ignore?: string + selector?: string +} + +function getElementError(message: string, container: HTMLElement): Error { return getConfig().getElementError(message, container) } -function getMultipleElementsFoundError(message, container) { +function getMultipleElementsFoundError( + message: string, + container: HTMLElement, +): Error { return getElementError( `${message}\n\n(If this is intentional, then use the \`*AllBy*\` variant of the query (like \`queryAllByText\`, \`getAllByText\`, or \`findAllByText\`)).`, container, @@ -15,20 +29,30 @@ function getMultipleElementsFoundError(message, container) { } function queryAllByAttribute( - attribute, - container, - text, - {exact = true, collapseWhitespace, trim, normalizer} = {}, -) { + attribute: string, + container: HTMLElement, + text: Matcher, + {exact = true, collapseWhitespace, trim, normalizer}: MatcherOptions = {}, +): HTMLElement[] { const matcher = exact ? matches : fuzzyMatches const matchNormalizer = makeNormalizer({collapseWhitespace, trim, normalizer}) return Array.from(container.querySelectorAll(`[${attribute}]`)).filter(node => - matcher(node.getAttribute(attribute), node, text, matchNormalizer), - ) + matcher( + node.getAttribute(attribute), + node as HTMLElement, + text, + matchNormalizer, + ), + ) as HTMLElement[] } -function queryByAttribute(attribute, container, text, ...args) { - const els = queryAllByAttribute(attribute, container, text, ...args) +function queryByAttribute( + attribute: string, + container: HTMLElement, + text: Matcher, + options?: MatcherOptions, +): HTMLElement | null { + const els = queryAllByAttribute(attribute, container, text, options) if (els.length > 1) { throw getMultipleElementsFoundError( `Found multiple elements by [${attribute}=${text}]`, @@ -115,6 +139,7 @@ const wrapAllByQueryWithSuggestion = (query, queryAllByName, variant) => ( // get a unique list of all suggestion messages. We are only going to make a suggestion if // all the suggestions are the same const uniqueSuggestionMessages = [ + // @ts-ignore FIXME with the right tsconfig settings ...new Set( els.map(element => getSuggestedQuery(element, variant)?.toString()), ), @@ -132,7 +157,43 @@ const wrapAllByQueryWithSuggestion = (query, queryAllByName, variant) => ( return els } -function buildQueries(queryAllBy, getMultipleError, getMissingError) { +/** + * query methods have a common call signature. Only the return type differs. + */ +export type QueryMethod = ( + container: HTMLElement, + ...args: Arguments +) => Return +export type QueryBy = QueryMethod< + Arguments, + HTMLElement | null +> +export type GetAllBy = QueryMethod< + Arguments, + HTMLElement[] +> +export type FindAllBy = QueryMethod< + [Arguments[0], Arguments[1], WaitForOptions], + Promise +> +export type GetBy = QueryMethod +export type FindBy = QueryMethod< + [Arguments[0], Arguments[1], WaitForOptions], + Promise +> +export type BuiltQueryMethods = [ + QueryBy, + GetAllBy, + GetBy, + FindAllBy, + FindBy, +] + +function buildQueries( + queryAllBy: GetAllBy, + getMultipleError: (container: HTMLElement, ...args: Arguments) => string, + getMissingError: (container: HTMLElement, ...args: Arguments) => string, +): BuiltQueryMethods { const queryBy = wrapSingleQueryWithSuggestion( makeSingleQuery(queryAllBy, getMultipleError), queryAllBy.name, diff --git a/src/screen.js b/src/screen.ts similarity index 100% rename from src/screen.js rename to src/screen.ts diff --git a/src/wait-for-dom-change.js b/src/wait-for-dom-change.ts similarity index 85% rename from src/wait-for-dom-change.js rename to src/wait-for-dom-change.ts index 1344db9d..97076388 100644 --- a/src/wait-for-dom-change.js +++ b/src/wait-for-dom-change.ts @@ -7,6 +7,7 @@ import { runWithRealTimers, } from './helpers' import {getConfig} from './config' +import {WaitForOptions} from './wait-for' let hasWarned = false @@ -22,7 +23,7 @@ function waitForDomChange({ attributes: true, characterData: true, }, -} = {}) { +}: WaitForOptions = {}) { if (!hasWarned) { hasWarned = true console.warn( @@ -31,7 +32,9 @@ function waitForDomChange({ } return new Promise((resolve, reject) => { const timer = setTimeout(onTimeout, timeout) - const {MutationObserver} = getWindowFromNode(container) + const {MutationObserver} = getWindowFromNode(container) as Window & { + MutationObserver: (callback: MutationCallback) => void + } const observer = new MutationObserver(onMutation) runWithRealTimers(() => observer.observe(container, mutationObserverOptions), @@ -47,7 +50,7 @@ function waitForDomChange({ } } - function onMutation(mutationsList) { + function onMutation(mutationsList: MutationRecord[]) { onDone(null, mutationsList) } diff --git a/types/config.d.ts b/types/config.d.ts deleted file mode 100644 index f06d5928..00000000 --- a/types/config.d.ts +++ /dev/null @@ -1,23 +0,0 @@ -export interface Config { - testIdAttribute: string - asyncWrapper(cb: (...args: any[]) => any): Promise - eventWrapper(cb: (...args: any[]) => any): void - getElementError: (message: string, container: Element) => Error - asyncUtilTimeout: number - defaultHidden: boolean - showOriginalStackTrace: boolean - throwSuggestions: boolean -} -interface InternalConfig { - _disableExpensiveErrorDiagnostics: boolean -} -export declare const DEFAULT_IGNORE_TAGS = 'script, style' -export declare function runWithExpensiveErrorDiagnosticsDisabled( - callback: any, -): any -export interface ConfigFn { - (existingConfig: Config): Partial -} -export declare function configure(newConfig: Partial | ConfigFn): void -export declare function getConfig(): Config & InternalConfig -export {} diff --git a/types/event-map.d.ts b/types/event-map.d.ts deleted file mode 100644 index 4dd9c4ae..00000000 --- a/types/event-map.d.ts +++ /dev/null @@ -1,156 +0,0 @@ -export declare type EventMapKey = - | 'copy' - | 'cut' - | 'paste' - | 'compositionEnd' - | 'compositionStart' - | 'compositionUpdate' - | 'keyDown' - | 'keyPress' - | 'keyUp' - | 'focus' - | 'blur' - | 'focusIn' - | 'focusOut' - | 'change' - | 'input' - | 'invalid' - | 'submit' - | 'reset' - | 'click' - | 'contextMenu' - | 'dblClick' - | 'drag' - | 'dragEnd' - | 'dragEnter' - | 'dragExit' - | 'dragLeave' - | 'dragOver' - | 'dragStart' - | 'drop' - | 'mouseDown' - | 'mouseEnter' - | 'mouseLeave' - | 'mouseMove' - | 'mouseOut' - | 'mouseOver' - | 'mouseUp' - | 'popState' - | 'select' - | 'touchCancel' - | 'touchEnd' - | 'touchMove' - | 'touchStart' - | 'scroll' - | 'wheel' - | 'abort' - | 'canPlay' - | 'canPlayThrough' - | 'durationChange' - | 'emptied' - | 'encrypted' - | 'ended' - | 'loadedData' - | 'loadedMetadata' - | 'loadStart' - | 'pause' - | 'play' - | 'playing' - | 'progress' - | 'rateChange' - | 'seeked' - | 'seeking' - | 'stalled' - | 'suspend' - | 'timeUpdate' - | 'volumeChange' - | 'waiting' - | 'load' - | 'error' - | 'animationStart' - | 'animationEnd' - | 'animationIteration' - | 'transitionEnd' - | 'pointerOver' - | 'pointerEnter' - | 'pointerDown' - | 'pointerMove' - | 'pointerUp' - | 'pointerCancel' - | 'pointerOut' - | 'pointerLeave' - | 'gotPointerCapture' - | 'lostPointerCapture' -declare type LegacyKeyboardEventInit = { - charCode?: number -} & KeyboardEventInit -declare type EventMapValue = - | { - EventType: 'AnimationEvent' - defaultInit: AnimationEventInit - } - | { - EventType: 'ClipboardEvent' - defaultInit: ClipboardEventInit - } - | { - EventType: 'CompositionEvent' - defaultInit: CompositionEventInit - } - | { - EventType: 'DragEvent' - defaultInit: DragEventInit - } - | { - EventType: 'Event' - defaultInit: EventInit - } - | { - EventType: 'FocusEvent' - defaultInit: FocusEventInit - } - | { - EventType: 'KeyboardEvent' - defaultInit: LegacyKeyboardEventInit - } - | { - EventType: 'InputEvent' - defaultInit: InputEventInit - } - | { - EventType: 'MouseEvent' - defaultInit: MouseEventInit - } - | { - EventType: 'PointerEvent' - defaultInit: PointerEventInit - } - | { - EventType: 'PopStateEvent' - defaultInit: PopStateEventInit - } - | { - EventType: 'ProgressEvent' - defaultInit: ProgressEventInit - } - | { - EventType: 'TouchEvent' - defaultInit: TouchEventInit - } - | { - EventType: 'TransitionEvent' - defaultInit: TransitionEventInit - } - | { - EventType: 'UIEvent' - defaultInit: UIEventInit - } - | { - EventType: 'WheelEvent' - defaultInit: WheelEventInit - } -export declare const eventMap: Record -declare type EventAliasMapKey = 'doubleClick' -export declare const eventAliasMap: Record -export declare type EventType = EventMapKey | EventAliasMapKey -export {} diff --git a/types/events.d.ts b/types/events.d.ts deleted file mode 100644 index 3b84289f..00000000 --- a/types/events.d.ts +++ /dev/null @@ -1,22 +0,0 @@ -import {EventType} from './event-map' -declare global { - interface Window { - DataTransfer: () => void - Event: () => void - } -} -declare type CreateObject = { - [K in EventType]: (element: EventTarget, options?: {}) => Event -} -declare const createEvent: CreateObject -declare type FireEventAsFunction = ( - element: EventTarget, - event: Event, -) => boolean -declare type FireEventAsHelper = Record< - EventType, - (element: EventTarget, init?: unknown) => boolean -> -declare type FireEvent = FireEventAsFunction & FireEventAsHelper -declare const fireEvent: FireEvent -export {fireEvent, createEvent} diff --git a/types/get-node-text.d.ts b/types/get-node-text.d.ts deleted file mode 100644 index 7e0defa9..00000000 --- a/types/get-node-text.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -declare function getNodeText(node: HTMLElement): string -export {getNodeText} diff --git a/types/helpers.d.ts b/types/helpers.d.ts deleted file mode 100644 index 625fab73..00000000 --- a/types/helpers.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -declare function runWithRealTimers(callback: any): any -declare const clearTimeoutFn: any, setImmediateFn: any, setTimeoutFn: any -declare function getDocument(): Document -declare function getWindowFromNode(node: any): Window -declare function checkContainerType(container: any): void -export { - getWindowFromNode, - getDocument, - clearTimeoutFn as clearTimeout, - setImmediateFn as setImmediate, - setTimeoutFn as setTimeout, - runWithRealTimers, - checkContainerType, -} diff --git a/types/index.d.ts b/types/index.d.ts deleted file mode 100644 index 8cbe6d33..00000000 --- a/types/index.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -// TypeScript Version: 3.8 - -import {getQueriesForElement} from './get-queries-for-element' -import * as queries from './queries' -import * as queryHelpers from './query-helpers' - -declare const within: typeof getQueriesForElement -export {queries, queryHelpers, within} - -export * from './queries' -export * from './query-helpers' -export * from './screen' -export * from './wait-for' -export * from './wait-for-dom-change' -export * from './wait-for-element' -export * from './wait-for-element-to-be-removed' -export * from './matches' -export * from './get-node-text' -export * from './events' -export * from './get-queries-for-element' -export * from './pretty-dom' -export * from './role-helpers' -export * from './config' -export * from './suggestions' diff --git a/types/matches.d.ts b/types/matches.d.ts deleted file mode 100644 index 4200b734..00000000 --- a/types/matches.d.ts +++ /dev/null @@ -1,55 +0,0 @@ -export declare type MatcherFunction = ( - content: string, - element: HTMLElement, -) => boolean -export declare type Matcher = string | RegExp | MatcherFunction -export declare type NormalizerFn = (text: string) => string -export interface MatcherOptions { - exact?: boolean - /** Use normalizer with getDefaultNormalizer instead */ - trim?: boolean - /** Use normalizer with getDefaultNormalizer instead */ - collapseWhitespace?: boolean - normalizer?: NormalizerFn - /** suppress suggestions for a specific query */ - suggest?: boolean -} -declare function fuzzyMatches( - textToMatch: string, - node: HTMLElement | null, - matcher: Matcher, - normalizer: NormalizerFn, -): boolean -declare function matches( - textToMatch: string, - node: HTMLElement | null, - matcher: Matcher, - normalizer: NormalizerFn, -): boolean -export interface DefaultNormalizerOptions { - trim?: boolean - collapseWhitespace?: boolean -} -declare function getDefaultNormalizer({ - trim, - collapseWhitespace, -}?: DefaultNormalizerOptions): NormalizerFn -/** - * Constructs a normalizer to pass to functions in matches.js - * @param {boolean|undefined} trim The user-specified value for `trim`, without - * any defaulting having been applied - * @param {boolean|undefined} collapseWhitespace The user-specified value for - * `collapseWhitespace`, without any defaulting having been applied - * @param {Function|undefined} normalizer The user-specified normalizer - * @returns {Function} A normalizer - */ -declare function makeNormalizer({ - trim, - collapseWhitespace, - normalizer, -}: { - trim: any - collapseWhitespace: any - normalizer: any -}): NormalizerFn -export {fuzzyMatches, matches, getDefaultNormalizer, makeNormalizer} diff --git a/types/pretty-dom.d.ts b/types/pretty-dom.d.ts deleted file mode 100644 index fe2b658e..00000000 --- a/types/pretty-dom.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -import {OptionsReceived} from 'pretty-format' -declare global { - namespace NodeJS { - interface Global { - Cypress?: any - } - } -} -declare function prettyDOM( - dom?: Element | Document, - maxLength?: number, - options?: OptionsReceived, -): string -declare const logDOM: ( - dom?: Element | HTMLDocument, - maxLength?: number, - options?: OptionsReceived, -) => void -export {prettyDOM, logDOM} diff --git a/types/queries.d.ts b/types/queries.d.ts deleted file mode 100644 index e38df0a6..00000000 --- a/types/queries.d.ts +++ /dev/null @@ -1,174 +0,0 @@ -import {Matcher, MatcherOptions} from './matches' -import {SelectorMatcherOptions} from './query-helpers' -import {WaitForOptions} from './wait-for' - -export type QueryByBoundAttribute = ( - container: HTMLElement, - id: Matcher, - options?: MatcherOptions, -) => HTMLElement | null - -export type AllByBoundAttribute = ( - container: HTMLElement, - id: Matcher, - options?: MatcherOptions, -) => HTMLElement[] - -export type FindAllByBoundAttribute = ( - container: HTMLElement, - id: Matcher, - options?: MatcherOptions, - waitForElementOptions?: WaitForOptions, -) => Promise - -export type GetByBoundAttribute = ( - container: HTMLElement, - id: Matcher, - options?: MatcherOptions, -) => HTMLElement - -export type FindByBoundAttribute = ( - container: HTMLElement, - id: Matcher, - options?: MatcherOptions, - waitForElementOptions?: WaitForOptions, -) => Promise - -export type QueryByText = ( - container: HTMLElement, - id: Matcher, - options?: SelectorMatcherOptions, -) => HTMLElement | null - -export type AllByText = ( - container: HTMLElement, - id: Matcher, - options?: SelectorMatcherOptions, -) => HTMLElement[] - -export type FindAllByText = ( - container: HTMLElement, - id: Matcher, - options?: SelectorMatcherOptions, - waitForElementOptions?: WaitForOptions, -) => Promise - -export type GetByText = ( - container: HTMLElement, - id: Matcher, - options?: SelectorMatcherOptions, -) => HTMLElement - -export type FindByText = ( - container: HTMLElement, - id: Matcher, - options?: SelectorMatcherOptions, - waitForElementOptions?: WaitForOptions, -) => Promise - -export interface ByRoleOptions extends MatcherOptions { - /** - * If true includes elements in the query set that are usually excluded from - * the accessibility tree. `role="none"` or `role="presentation"` are included - * in either case. - */ - hidden?: boolean - /** - * If true only includes elements in the query set that are marked as - * selected in the accessibility tree, i.e., `aria-selected="true"` - */ - selected?: boolean - /** - * Includes every role used in the `role` attribute - * For example *ByRole('progressbar', {queryFallbacks: true})` will find
`. - */ - queryFallbacks?: boolean - /** - * Only considers elements with the specified accessible name. - */ - name?: - | string - | RegExp - | ((accessibleName: string, element: Element) => boolean) -} - -export type AllByRole = ( - container: HTMLElement, - role: Matcher, - options?: ByRoleOptions, -) => HTMLElement[] - -export type GetByRole = ( - container: HTMLElement, - role: Matcher, - options?: ByRoleOptions, -) => HTMLElement - -export type QueryByRole = ( - container: HTMLElement, - role: Matcher, - options?: ByRoleOptions, -) => HTMLElement | null - -export type FindByRole = ( - container: HTMLElement, - role: Matcher, - options?: ByRoleOptions, - waitForElementOptions?: WaitForOptions, -) => Promise - -export type FindAllByRole = ( - container: HTMLElement, - role: Matcher, - options?: ByRoleOptions, - waitForElementOptions?: WaitForOptions, -) => Promise - -export const getByLabelText: GetByText -export const getAllByLabelText: AllByText -export const queryByLabelText: QueryByText -export const queryAllByLabelText: AllByText -export const findByLabelText: FindByText -export const findAllByLabelText: FindAllByText -export const getByPlaceholderText: GetByBoundAttribute -export const getAllByPlaceholderText: AllByBoundAttribute -export const queryByPlaceholderText: QueryByBoundAttribute -export const queryAllByPlaceholderText: AllByBoundAttribute -export const findByPlaceholderText: FindByBoundAttribute -export const findAllByPlaceholderText: FindAllByBoundAttribute -export const getByText: GetByText -export const getAllByText: AllByText -export const queryByText: QueryByText -export const queryAllByText: AllByText -export const findByText: FindByText -export const findAllByText: FindAllByText -export const getByAltText: GetByBoundAttribute -export const getAllByAltText: AllByBoundAttribute -export const queryByAltText: QueryByBoundAttribute -export const queryAllByAltText: AllByBoundAttribute -export const findByAltText: FindByBoundAttribute -export const findAllByAltText: FindAllByBoundAttribute -export const getByTitle: GetByBoundAttribute -export const getAllByTitle: AllByBoundAttribute -export const queryByTitle: QueryByBoundAttribute -export const queryAllByTitle: AllByBoundAttribute -export const findByTitle: FindByBoundAttribute -export const findAllByTitle: FindAllByBoundAttribute -export const getByDisplayValue: GetByBoundAttribute -export const getAllByDisplayValue: AllByBoundAttribute -export const queryByDisplayValue: QueryByBoundAttribute -export const queryAllByDisplayValue: AllByBoundAttribute -export const findByDisplayValue: FindByBoundAttribute -export const findAllByDisplayValue: FindAllByBoundAttribute -export const getByRole: GetByRole -export const getAllByRole: AllByRole -export const queryByRole: QueryByRole -export const queryAllByRole: AllByRole -export const findByRole: FindByRole -export const findAllByRole: FindAllByRole -export const getByTestId: GetByBoundAttribute -export const getAllByTestId: AllByBoundAttribute -export const queryByTestId: QueryByBoundAttribute -export const queryAllByTestId: AllByBoundAttribute -export const findByTestId: FindByBoundAttribute -export const findAllByTestId: FindAllByBoundAttribute diff --git a/types/query-helpers.d.ts b/types/query-helpers.d.ts deleted file mode 100644 index 931bc27d..00000000 --- a/types/query-helpers.d.ts +++ /dev/null @@ -1,62 +0,0 @@ -import {Matcher, MatcherOptions} from './matches' -import {WaitForOptions} from './wait-for' - -export interface SelectorMatcherOptions extends MatcherOptions { - selector?: string -} - -export type QueryByAttribute = ( - attribute: string, - container: HTMLElement, - id: Matcher, - options?: MatcherOptions, -) => HTMLElement | null - -export type AllByAttribute = ( - attribute: string, - container: HTMLElement, - id: Matcher, - options?: MatcherOptions, -) => HTMLElement[] - -export const queryByAttribute: QueryByAttribute -export const queryAllByAttribute: AllByAttribute -export function getElementError(message: string, container: HTMLElement): Error - -/** - * query methods have a common call signature. Only the return type differs. - */ -export type QueryMethod = ( - container: HTMLElement, - ...args: Arguments -) => Return -export type QueryBy = QueryMethod< - Arguments, - HTMLElement | null -> -export type GetAllBy = QueryMethod< - Arguments, - HTMLElement[] -> -export type FindAllBy = QueryMethod< - [Arguments[0], Arguments[1], WaitForOptions], - Promise -> -export type GetBy = QueryMethod -export type FindBy = QueryMethod< - [Arguments[0], Arguments[1], WaitForOptions], - Promise -> - -export type BuiltQueryMethods = [ - QueryBy, - GetAllBy, - GetBy, - FindAllBy, - FindBy, -] -export function buildQueries( - queryByAll: GetAllBy, - getMultipleError: (container: HTMLElement, ...args: Arguments) => string, - getMissingError: (container: HTMLElement, ...args: Arguments) => string, -): BuiltQueryMethods diff --git a/types/role-helpers.d.ts b/types/role-helpers.d.ts deleted file mode 100644 index 94b588fe..00000000 --- a/types/role-helpers.d.ts +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @param {Element} element - - * @returns {boolean} - `true` if `element` and its subtree are inaccessible - */ -declare function isSubtreeInaccessible(element: HTMLElement): boolean -interface IsInaccessibleOptions { - isSubtreeInaccessible?: typeof isSubtreeInaccessible -} -/** - * Partial implementation https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion - * which should only be used for elements with a non-presentational role i.e. - * `role="none"` and `role="presentation"` will not be excluded. - * - * Implements aria-hidden semantics (i.e. parent overrides child) - * Ignores "Child Presentational: True" characteristics - * - * @param {Element} element - - * @param {object} [options] - - * @param {function (element: Element): boolean} options.isSubtreeInaccessible - - * can be used to return cached results from previous isSubtreeInaccessible calls - * @returns {boolean} true if excluded, otherwise false - */ -declare function isInaccessible( - element: HTMLElement, - options?: IsInaccessibleOptions, -): boolean -declare function getImplicitAriaRoles(currentNode: any): any[] -declare function getRoles( - container: any, - { - hidden, - }?: { - hidden?: boolean - }, -): Record -declare function prettyRoles( - dom: HTMLElement, - { - hidden, - }: { - hidden: any - }, -): string -declare const logRoles: ( - dom: HTMLElement, - { - hidden, - }?: { - hidden?: boolean - }, -) => void -/** - * @param {Element} element - - * @returns {boolean | undefined} - false/true if (not)selected, undefined if not selectable - */ -declare function computeAriaSelected(element: any): any -export { - getRoles, - logRoles, - getImplicitAriaRoles, - isSubtreeInaccessible, - prettyRoles, - isInaccessible, - computeAriaSelected, -} diff --git a/types/screen.d.ts b/types/screen.d.ts deleted file mode 100644 index dca6cb86..00000000 --- a/types/screen.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -import {BoundFunctions, Queries} from './get-queries-for-element' -import * as queries from './queries' -import {OptionsReceived} from 'pretty-format' - -export type Screen = BoundFunctions & { - /** - * Convenience function for `pretty-dom` which also allows an array - * of elements - */ - debug: ( - element?: Element | HTMLDocument | Array, - maxLength?: number, - options?: OptionsReceived, - ) => void -} - -export const screen: Screen diff --git a/types/suggestions.d.ts b/types/suggestions.d.ts deleted file mode 100644 index 05c13cca..00000000 --- a/types/suggestions.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -export interface Suggestion { - queryName: string - toString(): string -} -export declare function getSuggestedQuery( - element: HTMLElement, - variant?: string, -): Suggestion | undefined diff --git a/types/wait-for-dom-change.d.ts b/types/wait-for-dom-change.d.ts deleted file mode 100644 index 5d3cd4c9..00000000 --- a/types/wait-for-dom-change.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import {WaitForOptions} from './wait-for' - -export function waitForDomChange(options?: WaitForOptions): Promise diff --git a/types/wait-for-element-to-be-removed.d.ts b/types/wait-for-element-to-be-removed.d.ts deleted file mode 100644 index df3139e0..00000000 --- a/types/wait-for-element-to-be-removed.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -import {WaitForOptions} from './wait-for' -declare function waitForElementToBeRemoved( - callback: (() => T | T[]) | T | T[], - options?: WaitForOptions, -): Promise -export {waitForElementToBeRemoved} diff --git a/types/wait-for-element.d.ts b/types/wait-for-element.d.ts deleted file mode 100644 index 751565da..00000000 --- a/types/wait-for-element.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -import {WaitForOptions} from './wait-for' -declare function waitForElement( - callback: () => T extends Promise ? never : T, - options?: WaitForOptions, -): Promise -export {waitForElement} diff --git a/types/wait-for.d.ts b/types/wait-for.d.ts deleted file mode 100644 index 1747c58f..00000000 --- a/types/wait-for.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -export interface WaitForOptions { - container?: Node - timeout?: number - interval?: number - mutationObserverOptions?: MutationObserverInit - showOriginalStackTrace?: boolean -} -declare function waitForWrapper( - callback: () => T extends Promise ? never : T, - options?: WaitForOptions, -): Promise -interface WaitOptions { - container?: Node - timeout?: number - interval?: number - mutationObserverOptions?: MutationObserverInit -} -declare function wait(first?: () => void, options?: WaitOptions): Promise -export {waitForWrapper as waitFor, wait} From 3e8c451b8becd7d4256ec4917f0c0c131360d73b Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Fri, 24 Jul 2020 19:17:57 +0200 Subject: [PATCH 16/16] Generate types during the build target --- README.md | 1 + package.json | 7 ++++--- src/__tests__/events.js | 26 +++++++++++++++----------- src/__tests__/role.js | 4 +++- src/wait-for.ts | 5 +---- tsconfig.build.json | 7 +++++++ tsconfig.json | 2 +- 7 files changed, 32 insertions(+), 20 deletions(-) create mode 100644 tsconfig.build.json diff --git a/README.md b/README.md index b24c136e..d42d601f 100644 --- a/README.md +++ b/README.md @@ -267,6 +267,7 @@ Thanks goes to these people ([emoji key][emojis]): + This project follows the [all-contributors][all-contributors] specification. diff --git a/package.json b/package.json index ff789973..8858bf60 100644 --- a/package.json +++ b/package.json @@ -24,15 +24,16 @@ "node": ">=10" }, "scripts": { - "build": "kcd-scripts build --ignore \"**/__tests__/**,**/__node_tests__/**,**/__mocks__/**\" && kcd-scripts build --bundle --no-clean", + "build": "npm run build:bundles ; npm run build:types", + "build:bundles": "kcd-scripts build --ignore \"**/__tests__/**,**/__node_tests__/**,**/__mocks__/**\" && kcd-scripts build --bundle --no-clean", + "build:types": "tsc --build tsconfig.build.json", "lint": "kcd-scripts lint", "setup": "npm install && npm run validate -s", "test": "kcd-scripts test", "test:debug": "node --inspect-brk ./node_modules/.bin/jest --watch --runInBand", "test:update": "npm test -- --updateSnapshot --coverage", "validate": "kcd-scripts validate", - "generate-types": "tsc", - "typecheck": "dtslint ./types/" + "typecheck-DISABLED": "dtslint ./types/" }, "files": [ "dist", diff --git a/src/__tests__/events.js b/src/__tests__/events.js index f2f8d2a9..37b62c10 100644 --- a/src/__tests__/events.js +++ b/src/__tests__/events.js @@ -140,17 +140,21 @@ const eventTypes = [ const allEvents = Object.keys(eventMap) -const bubblingEvents = allEvents - .filter(eventName => eventMap[eventName].defaultInit.bubbles) +const bubblingEvents = allEvents.filter( + eventName => eventMap[eventName].defaultInit.bubbles, +) -const composedEvents = allEvents - .filter(eventName => eventMap[eventName].defaultInit.composed) +const composedEvents = allEvents.filter( + eventName => eventMap[eventName].defaultInit.composed, +) -const nonBubblingEvents = allEvents - .filter(eventName => !bubblingEvents.includes(eventName)) +const nonBubblingEvents = allEvents.filter( + eventName => !bubblingEvents.includes(eventName), +) -const nonComposedEvents = allEvents - .filter(eventName => !composedEvents.includes(eventName)) +const nonComposedEvents = allEvents.filter( + eventName => !composedEvents.includes(eventName), +) eventTypes.forEach(({type, events, elementType}) => { describe(`${type} Events`, () => { @@ -203,7 +207,7 @@ describe(`Composed Events`, () => { const spy = jest.fn() node.addEventListener(event.toLowerCase(), spy) - const shadowRoot = node.attachShadow({ mode: 'closed' }) + const shadowRoot = node.attachShadow({mode: 'closed'}) const innerNode = document.createElement('div') shadowRoot.appendChild(innerNode) @@ -218,7 +222,7 @@ describe(`Composed Events`, () => { const spy = jest.fn() node.addEventListener(event.toLowerCase(), spy) - const shadowRoot = node.attachShadow({ mode: 'closed' }) + const shadowRoot = node.attachShadow({mode: 'closed'}) const innerNode = document.createElement('div') shadowRoot.appendChild(innerNode) @@ -234,7 +238,7 @@ describe(`Aliased Events`, () => { const node = document.createElement('div') const spy = jest.fn() node.addEventListener(eventAliasMap[eventAlias].toLowerCase(), spy) - + fireEvent[eventAlias](node) expect(spy).toHaveBeenCalledTimes(1) }) diff --git a/src/__tests__/role.js b/src/__tests__/role.js index a187a77b..7e3164ba 100644 --- a/src/__tests__/role.js +++ b/src/__tests__/role.js @@ -346,7 +346,9 @@ Here are the accessible roles: test('has no useful error message in findBy', async () => { const {findByRole} = render(`
  • `) - await expect(findByRole('option', {timeout: 1})).rejects.toThrow('Unable to find role="option"') + await expect(findByRole('option', {timeout: 1})).rejects.toThrow( + 'Unable to find role="option"', + ) }) test('explicit role is most specific', () => { diff --git a/src/wait-for.ts b/src/wait-for.ts index 7a25f6ef..c77a54c2 100644 --- a/src/wait-for.ts +++ b/src/wait-for.ts @@ -122,10 +122,7 @@ interface WaitOptions { interval?: number mutationObserverOptions?: MutationObserverInit } -function wait( - first: () => void = () => {}, - options?: WaitOptions, -): Promise { +function wait(first: () => void, options?: WaitOptions): Promise { // istanbul ignore next if (!hasWarned) { hasWarned = true diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 00000000..3325a603 --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": false, + "emitDeclarationOnly": true + } +} diff --git a/tsconfig.json b/tsconfig.json index 16dbfc70..406ef8e6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,7 +3,7 @@ "outDir": "./types/", "allowJs": true, "declaration": true, - "emitDeclarationOnly": true, + "noEmit": true, "allowSyntheticDefaultImports": true }, "include": ["./src/**/*.ts"]