From dc8cc2af0b9a53717866e48d99e50e001f91c87d Mon Sep 17 00:00:00 2001 From: Ali Nasserzadeh Date: Wed, 22 Apr 2020 13:30:55 +0200 Subject: [PATCH 1/9] Copied the newest .d.ts files from DefinitelyTyped --- types/config.d.ts | 12 ++ types/events.d.ts | 95 +++++++++++++++ types/get-node-text.d.ts | 1 + types/get-queries-for-element.d.ts | 30 +++++ types/index.d.ts | 34 ++++++ types/matches.d.ts | 29 +++++ types/pretty-dom.d.ts | 4 + types/queries.d.ts | 135 ++++++++++++++++++++++ types/query-helpers.d.ts | 46 ++++++++ types/role-helpers.d.ts | 7 ++ types/screen.d.ts | 17 +++ types/wait-for-dom-change.d.ts | 5 + types/wait-for-element-to-be-removed.d.ts | 8 ++ types/wait-for-element.d.ts | 7 ++ types/wait-for.d.ts | 9 ++ types/wait.d.ts | 7 ++ 16 files changed, 446 insertions(+) create mode 100644 types/config.d.ts create mode 100644 types/events.d.ts create mode 100644 types/get-node-text.d.ts create mode 100644 types/get-queries-for-element.d.ts create mode 100644 types/index.d.ts create mode 100644 types/matches.d.ts create mode 100644 types/pretty-dom.d.ts create mode 100644 types/queries.d.ts create mode 100644 types/query-helpers.d.ts create mode 100644 types/role-helpers.d.ts create mode 100644 types/screen.d.ts create mode 100644 types/wait-for-dom-change.d.ts create mode 100644 types/wait-for-element-to-be-removed.d.ts create mode 100644 types/wait-for-element.d.ts create mode 100644 types/wait-for.d.ts create mode 100644 types/wait.d.ts diff --git a/types/config.d.ts b/types/config.d.ts new file mode 100644 index 00000000..a2063d99 --- /dev/null +++ b/types/config.d.ts @@ -0,0 +1,12 @@ +export interface Config { + testIdAttribute: string; + asyncWrapper(cb: (...args: any[]) => any): Promise; + asyncUtilTimeout: number; + defaultHidden: boolean; +} + +export interface ConfigFn { + (existingConfig: Config): Partial; +} + +export function configure(configDelta: Partial | ConfigFn): void; diff --git a/types/events.d.ts b/types/events.d.ts new file mode 100644 index 00000000..d9c50cb7 --- /dev/null +++ b/types/events.d.ts @@ -0,0 +1,95 @@ +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; +}; +export type CreateObject = { + [K in EventType]: (element: Document | Element | Window | Node, options?: {}) => Event; +}; + +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 new file mode 100644 index 00000000..5c5654b5 --- /dev/null +++ b/types/get-node-text.d.ts @@ -0,0 +1 @@ +export function getNodeText(node: HTMLElement): string; diff --git a/types/get-queries-for-element.d.ts b/types/get-queries-for-element.d.ts new file mode 100644 index 00000000..90e5626d --- /dev/null +++ b/types/get-queries-for-element.d.ts @@ -0,0 +1,30 @@ +import { Matcher } from './matches'; +import * as queries from './queries'; + +export type BoundFunction = T extends ( + 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 }; + +export type Query = ( + container: HTMLElement, + ...args: any[] +) => Error | Promise | Promise | HTMLElement[] | HTMLElement | null; + +export interface Queries { + [T: string]: Query; +} + +export function getQueriesForElement( + element: HTMLElement, + queriesToBind?: T, +): BoundFunctions; diff --git a/types/index.d.ts b/types/index.d.ts new file mode 100644 index 00000000..dd1b2132 --- /dev/null +++ b/types/index.d.ts @@ -0,0 +1,34 @@ +// Type definitions for @testing-library/dom 7.0 +// Project: https://github.com/testing-library/dom-testing-library +// Definitions by: Alex Krolick +// Kent C Dodds +// Sebastian Silbermann +// Weyert de Boer +// Ronald Rey +// Justin Hall +// Wesley Tsai +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 3.1 + +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'; +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'; diff --git a/types/matches.d.ts b/types/matches.d.ts new file mode 100644 index 00000000..0b8dad4d --- /dev/null +++ b/types/matches.d.ts @@ -0,0 +1,29 @@ +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; +} + +export type Match = ( + textToMatch: string, + node: HTMLElement | null, + matcher: Matcher, + options?: MatcherOptions, +) => 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 diff --git a/types/pretty-dom.d.ts b/types/pretty-dom.d.ts new file mode 100644 index 00000000..bca6afb4 --- /dev/null +++ b/types/pretty-dom.d.ts @@ -0,0 +1,4 @@ +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; diff --git a/types/queries.d.ts b/types/queries.d.ts new file mode 100644 index 00000000..55abf3b2 --- /dev/null +++ b/types/queries.d.ts @@ -0,0 +1,135 @@ +import { Matcher, MatcherOptions } from './matches'; +import { SelectorMatcherOptions } from './query-helpers'; +import { WaitForElementOptions } from './wait-for-element'; + +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?: WaitForElementOptions, +) => Promise; + +export type GetByBoundAttribute = (container: HTMLElement, id: Matcher, options?: MatcherOptions) => HTMLElement; + +export type FindByBoundAttribute = ( + container: HTMLElement, + id: Matcher, + options?: MatcherOptions, + waitForElementOptions?: WaitForElementOptions, +) => 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?: WaitForElementOptions, +) => Promise; + +export type GetByText = (container: HTMLElement, id: Matcher, options?: SelectorMatcherOptions) => HTMLElement; + +export type FindByText = ( + container: HTMLElement, + id: Matcher, + options?: SelectorMatcherOptions, + waitForElementOptions?: WaitForElementOptions, +) => 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. + * @default false + */ + hidden?: 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?: WaitForElementOptions, +) => Promise; + +export type FindAllByRole = ( + container: HTMLElement, + role: Matcher, + options?: ByRoleOptions, + waitForElementOptions?: WaitForElementOptions, +) => 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 new file mode 100644 index 00000000..63a1f69b --- /dev/null +++ b/types/query-helpers.d.ts @@ -0,0 +1,46 @@ +import { Matcher, MatcherOptions } from './matches'; + +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; +export type GetAllBy = QueryMethod; +export type FindAllBy = QueryMethod>; +export type GetBy = QueryMethod; +export type FindBy = QueryMethod>; + +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 new file mode 100644 index 00000000..37abddd8 --- /dev/null +++ b/types/role-helpers.d.ts @@ -0,0 +1,7 @@ +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 + */ +export function isInaccessible(element: Element): boolean; diff --git a/types/screen.d.ts b/types/screen.d.ts new file mode 100644 index 00000000..906b59ef --- /dev/null +++ b/types/screen.d.ts @@ -0,0 +1,17 @@ +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/wait-for-dom-change.d.ts b/types/wait-for-dom-change.d.ts new file mode 100644 index 00000000..3b3f0de1 --- /dev/null +++ b/types/wait-for-dom-change.d.ts @@ -0,0 +1,5 @@ +export function waitForDomChange(options?: { + container?: HTMLElement; + timeout?: number; + mutationObserverOptions?: MutationObserverInit; +}): Promise; diff --git a/types/wait-for-element-to-be-removed.d.ts b/types/wait-for-element-to-be-removed.d.ts new file mode 100644 index 00000000..567bce8f --- /dev/null +++ b/types/wait-for-element-to-be-removed.d.ts @@ -0,0 +1,8 @@ +export function waitForElementToBeRemoved( + callback: (() => T) | T, + options?: { + container?: HTMLElement; + timeout?: number; + mutationObserverOptions?: MutationObserverInit; + }, +): Promise; diff --git a/types/wait-for-element.d.ts b/types/wait-for-element.d.ts new file mode 100644 index 00000000..6ab7009c --- /dev/null +++ b/types/wait-for-element.d.ts @@ -0,0 +1,7 @@ +export interface WaitForElementOptions { + container?: HTMLElement; + timeout?: number; + mutationObserverOptions?: MutationObserverInit; +} + +export function waitForElement(callback: () => T, options?: WaitForElementOptions): Promise; diff --git a/types/wait-for.d.ts b/types/wait-for.d.ts new file mode 100644 index 00000000..0c68bf24 --- /dev/null +++ b/types/wait-for.d.ts @@ -0,0 +1,9 @@ +export function waitFor( + callback: () => T, + options?: { + container?: HTMLElement; + timeout?: number; + interval?: number; + mutationObserverOptions?: MutationObserverInit; + }, +): Promise; diff --git a/types/wait.d.ts b/types/wait.d.ts new file mode 100644 index 00000000..3763e7bd --- /dev/null +++ b/types/wait.d.ts @@ -0,0 +1,7 @@ +export function wait( + callback?: () => void, + options?: { + timeout?: number; + interval?: number; + }, +): Promise; From 36c0231be05d365391e58b15bec2af19f66cf86e Mon Sep 17 00:00:00 2001 From: Ali Nasserzadeh Date: Wed, 22 Apr 2020 13:31:55 +0200 Subject: [PATCH 2/9] Adjusted package.json to include type files and removed @types dependency --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 49771b1e..747334b2 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "0.0.0-semantically-released", "description": "Simple and complete DOM testing utilities that encourage good testing practices.", "main": "dist/index.js", + "types": "types/index.d.ts", "module": "dist/@testing-library/dom.esm.js", "umd:main": "dist/@testing-library/dom.umd.js", "source": "src/index.js", @@ -32,11 +33,11 @@ "validate": "kcd-scripts validate" }, "files": [ - "dist" + "dist", + "types" ], "dependencies": { "@babel/runtime": "^7.9.2", - "@types/testing-library__dom": "^7.0.0", "aria-query": "^4.0.2", "dom-accessibility-api": "^0.4.2", "pretty-format": "^25.1.0" From f02757eed16d4aaf02163dc50e43e46cbad1606f Mon Sep 17 00:00:00 2001 From: Ali Nasserzadeh Date: Thu, 23 Apr 2020 21:24:40 +0200 Subject: [PATCH 3/9] Copied over DefinitelyTyped type tests --- types/__tests__/type-tests.ts | 122 ++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 types/__tests__/type-tests.ts diff --git a/types/__tests__/type-tests.ts b/types/__tests__/type-tests.ts new file mode 100644 index 00000000..a869671d --- /dev/null +++ b/types/__tests__/type-tests.ts @@ -0,0 +1,122 @@ +import { + fireEvent, + isInaccessible, + queries, + screen, + waitFor, + waitForElementToBeRemoved, +} from '../index' + +const { + getByText, + queryByText, + findByText, + getAllByText, + queryAllByText, + findAllByText, + queryAllByRole, + queryByRole, + findByRole, +} = queries + +async function testQueries() { + // element queries + const element = document.createElement('div') + getByText(element, 'foo') + queryByText(element, 'foo') + await findByText(element, 'foo') + await findByText(element, 'foo', undefined, {timeout: 10}) + getAllByText(element, 'bar') + queryAllByText(element, 'bar') + await findAllByText(element, 'bar') + await findAllByText(element, 'bar', undefined, {timeout: 10}) + + // screen queries + screen.getByText('foo') + screen.queryByText('foo') + await screen.findByText('foo') + await screen.findByText('foo', undefined, {timeout: 10}) + screen.debug(screen.getAllByText('bar')) + screen.queryAllByText('bar') + await screen.findAllByText('bar') + await screen.findAllByText('bar', undefined, {timeout: 10}) +} + +async function testByRole() { + const element = document.createElement('button') + element.setAttribute('aria-hidden', 'true') + + console.assert(queryByRole(element, 'button') === null) + console.assert(queryByRole(element, 'button', {hidden: true}) !== null) + + console.assert(screen.queryByRole('button') === null) + console.assert(screen.queryByRole('button', {hidden: true}) !== null) + + console.assert( + (await findByRole(element, 'button', undefined, {timeout: 10})) === null, + ) + console.assert( + (await findByRole(element, 'button', {hidden: true}, {timeout: 10})) !== + null, + ) + + console.assert( + queryAllByRole(document.body, 'progressbar', {queryFallbacks: true}) + .length === 1, + ) + + // `name` option + console.assert(queryByRole(element, 'button', {name: 'Logout'}) === null) + console.assert(queryByRole(element, 'button', {name: /^Log/}) === null) + console.assert( + queryByRole(element, 'button', { + name: (name, element) => + name === 'Login' && element.hasAttribute('disabled'), + }) === null, + ) +} + +function testA11yHelper() { + const element = document.createElement('svg') + console.assert(!isInaccessible(element)) +} + +function eventTest() { + fireEvent.popState(window, { + location: 'http://www.example.com/?page=1', + state: {page: 1}, + }) + + // HTMLElement + const element = document.createElement('div') + fireEvent.click(getByText(element, 'foo')) + + // ChildNode + const child = document.createElement('div') + element.appendChild(child) + if (!element.firstChild) { + // Narrow Type + throw new Error(`Can't find firstChild`) + } + fireEvent.click(element.firstChild) +} + +async function testWaitFors() { + const element = document.createElement('div') + + await waitFor(() => getByText(element, 'apple')) + await waitFor(() => getAllByText(element, 'apple')) + const result: HTMLSpanElement = await waitFor(() => + getByText(element, 'apple'), + ) + if (!result) { + // Use value + throw new Error(`Can't find result`) + } + + element.innerHTML = 'apple' + + await waitForElementToBeRemoved(() => getByText(element, 'apple')) + await waitForElementToBeRemoved(getByText(element, 'apple')) + await waitForElementToBeRemoved(getAllByText(element, 'apple')) +} From 4184bb923eb31b8f321c08c9184e92c52ce83989 Mon Sep 17 00:00:00 2001 From: Ali Nasserzadeh Date: Thu, 23 Apr 2020 21:25:18 +0200 Subject: [PATCH 4/9] Added dtslint to check the types and type-tests --- package.json | 5 ++++- types/tsconfig.json | 17 +++++++++++++++++ types/tslint.json | 8 ++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 types/tsconfig.json create mode 100644 types/tslint.json diff --git a/package.json b/package.json index 747334b2..ea10d708 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,8 @@ "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" + "validate": "npm run typecheck && kcd-scripts validate", + "typecheck": "dtslint ./types/" }, "files": [ "dist", @@ -44,6 +45,8 @@ }, "devDependencies": { "@testing-library/jest-dom": "^5.1.1", + "conditional-type-checks": "^1.0.5", + "dtslint": "^3.4.2", "jest-in-case": "^1.0.2", "jest-serializer-ansi": "^1.0.3", "jest-watch-select-projects": "^2.0.0", diff --git a/types/tsconfig.json b/types/tsconfig.json new file mode 100644 index 00000000..c4da27db --- /dev/null +++ b/types/tsconfig.json @@ -0,0 +1,17 @@ +// this additional tsconfig is required by dtslint +// see: https://github.com/Microsoft/dtslint#typestsconfigjson +{ + "compilerOptions": { + "module": "commonjs", + "lib": ["es6", "dom"], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "noEmit": true, + + // If the library is an external module (uses `export`), this allows your test file to import "mylib" instead of "./index". + // If the library is global (cannot be imported via `import` or `require`), leave this out. + "baseUrl": "." + } +} diff --git a/types/tslint.json b/types/tslint.json new file mode 100644 index 00000000..5d45232f --- /dev/null +++ b/types/tslint.json @@ -0,0 +1,8 @@ +{ + "extends": ["dtslint/dtslint.json"], + "rules": { + "no-useless-files": false, + "no-relative-import-in-test": false, + "semicolon": false + } +} From c876b1a7eda30555a1c6e743d2500b8f54cae424 Mon Sep 17 00:00:00 2001 From: Ali Nasserzadeh Date: Thu, 23 Apr 2020 21:25:56 +0200 Subject: [PATCH 5/9] Adjusted the types to pass dtslint (removed unneeded jsdoc) --- types/index.d.ts | 10 ---------- types/queries.d.ts | 1 - types/role-helpers.d.ts | 1 - 3 files changed, 12 deletions(-) diff --git a/types/index.d.ts b/types/index.d.ts index dd1b2132..14bab359 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,13 +1,3 @@ -// Type definitions for @testing-library/dom 7.0 -// Project: https://github.com/testing-library/dom-testing-library -// Definitions by: Alex Krolick -// Kent C Dodds -// Sebastian Silbermann -// Weyert de Boer -// Ronald Rey -// Justin Hall -// Wesley Tsai -// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 3.1 import { getQueriesForElement } from './get-queries-for-element'; diff --git a/types/queries.d.ts b/types/queries.d.ts index 55abf3b2..ee27b71b 100644 --- a/types/queries.d.ts +++ b/types/queries.d.ts @@ -51,7 +51,6 @@ 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. - * @default false */ hidden?: boolean; /** diff --git a/types/role-helpers.d.ts b/types/role-helpers.d.ts index 37abddd8..3dd35b78 100644 --- a/types/role-helpers.d.ts +++ b/types/role-helpers.d.ts @@ -2,6 +2,5 @@ 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 */ export function isInaccessible(element: Element): boolean; From 4330d347272094a6415df649c5eadfee002f9dbb Mon Sep 17 00:00:00 2001 From: Ali Nasserzadeh Date: Thu, 23 Apr 2020 22:33:20 +0200 Subject: [PATCH 6/9] Removed unneeded dependency 'conditional-type-check' --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index ea10d708..09fb87a8 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,6 @@ }, "devDependencies": { "@testing-library/jest-dom": "^5.1.1", - "conditional-type-checks": "^1.0.5", "dtslint": "^3.4.2", "jest-in-case": "^1.0.2", "jest-serializer-ansi": "^1.0.3", From 70d097505a75565c2074e8458358beb39acdea7d Mon Sep 17 00:00:00 2001 From: Ali Nasserzadeh Date: Fri, 24 Apr 2020 19:13:31 +0200 Subject: [PATCH 7/9] Unified all waitForOptions types to one single type --- types/queries.d.ts | 14 +++++++------- types/wait-for-dom-change.d.ts | 8 +++----- types/wait-for-element-to-be-removed.d.ts | 8 +++----- types/wait-for-element.d.ts | 8 ++------ types/wait-for.d.ts | 14 ++++++++------ 5 files changed, 23 insertions(+), 29 deletions(-) diff --git a/types/queries.d.ts b/types/queries.d.ts index ee27b71b..6f8633ce 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 { WaitForElementOptions } from './wait-for-element'; +import { waitForOptions } from 'wait-for'; export type QueryByBoundAttribute = ( container: HTMLElement, @@ -14,7 +14,7 @@ export type FindAllByBoundAttribute = ( container: HTMLElement, id: Matcher, options?: MatcherOptions, - waitForElementOptions?: WaitForElementOptions, + waitForElementOptions?: waitForOptions, ) => Promise; export type GetByBoundAttribute = (container: HTMLElement, id: Matcher, options?: MatcherOptions) => HTMLElement; @@ -23,7 +23,7 @@ export type FindByBoundAttribute = ( container: HTMLElement, id: Matcher, options?: MatcherOptions, - waitForElementOptions?: WaitForElementOptions, + waitForElementOptions?: waitForOptions, ) => Promise; export type QueryByText = (container: HTMLElement, id: Matcher, options?: SelectorMatcherOptions) => HTMLElement | null; @@ -34,7 +34,7 @@ export type FindAllByText = ( container: HTMLElement, id: Matcher, options?: SelectorMatcherOptions, - waitForElementOptions?: WaitForElementOptions, + waitForElementOptions?: waitForOptions, ) => Promise; export type GetByText = (container: HTMLElement, id: Matcher, options?: SelectorMatcherOptions) => HTMLElement; @@ -43,7 +43,7 @@ export type FindByText = ( container: HTMLElement, id: Matcher, options?: SelectorMatcherOptions, - waitForElementOptions?: WaitForElementOptions, + waitForElementOptions?: waitForOptions, ) => Promise; export interface ByRoleOptions extends MatcherOptions { @@ -74,14 +74,14 @@ export type FindByRole = ( container: HTMLElement, role: Matcher, options?: ByRoleOptions, - waitForElementOptions?: WaitForElementOptions, + waitForElementOptions?: waitForOptions, ) => Promise; export type FindAllByRole = ( container: HTMLElement, role: Matcher, options?: ByRoleOptions, - waitForElementOptions?: WaitForElementOptions, + waitForElementOptions?: waitForOptions, ) => Promise; export const getByLabelText: GetByText; diff --git a/types/wait-for-dom-change.d.ts b/types/wait-for-dom-change.d.ts index 3b3f0de1..2fe72c10 100644 --- a/types/wait-for-dom-change.d.ts +++ b/types/wait-for-dom-change.d.ts @@ -1,5 +1,3 @@ -export function waitForDomChange(options?: { - container?: HTMLElement; - timeout?: number; - mutationObserverOptions?: MutationObserverInit; -}): Promise; +import { waitForOptions } from "index"; + +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 567bce8f..42a891ac 100644 --- a/types/wait-for-element-to-be-removed.d.ts +++ b/types/wait-for-element-to-be-removed.d.ts @@ -1,8 +1,6 @@ +import { waitForOptions } from "wait-for"; + export function waitForElementToBeRemoved( callback: (() => T) | T, - options?: { - container?: HTMLElement; - timeout?: number; - mutationObserverOptions?: MutationObserverInit; - }, + options?: waitForOptions, ): Promise; diff --git a/types/wait-for-element.d.ts b/types/wait-for-element.d.ts index 6ab7009c..f21fb112 100644 --- a/types/wait-for-element.d.ts +++ b/types/wait-for-element.d.ts @@ -1,7 +1,3 @@ -export interface WaitForElementOptions { - container?: HTMLElement; - timeout?: number; - mutationObserverOptions?: MutationObserverInit; -} +import { waitForOptions } from "wait-for"; -export function waitForElement(callback: () => T, options?: WaitForElementOptions): Promise; +export function waitForElement(callback: () => T, options?: waitForOptions): Promise; diff --git a/types/wait-for.d.ts b/types/wait-for.d.ts index 0c68bf24..3c39073b 100644 --- a/types/wait-for.d.ts +++ b/types/wait-for.d.ts @@ -1,9 +1,11 @@ +export interface waitForOptions { + container?: HTMLElement; + timeout?: number; + interval?: number; + mutationObserverOptions?: MutationObserverInit; +} + export function waitFor( callback: () => T, - options?: { - container?: HTMLElement; - timeout?: number; - interval?: number; - mutationObserverOptions?: MutationObserverInit; - }, + options?: waitForOptions, ): Promise; From 82edc3670da330be274f7afdcc67d17b48538915 Mon Sep 17 00:00:00 2001 From: Ali Nasserzadeh Date: Fri, 24 Apr 2020 19:14:02 +0200 Subject: [PATCH 8/9] extended waitFor tests to better cover for the waitForOptions type --- types/__tests__/type-tests.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/__tests__/type-tests.ts b/types/__tests__/type-tests.ts index a869671d..5203434e 100644 --- a/types/__tests__/type-tests.ts +++ b/types/__tests__/type-tests.ts @@ -116,7 +116,7 @@ async function testWaitFors() { element.innerHTML = 'apple' - await waitForElementToBeRemoved(() => getByText(element, 'apple')) + await waitForElementToBeRemoved(() => getByText(element, 'apple'), {interval: 3000, container: element, timeout: 5000}) await waitForElementToBeRemoved(getByText(element, 'apple')) await waitForElementToBeRemoved(getAllByText(element, 'apple')) } From 430236ec91bcfd48a521ae0effd90ad721a9ef2b Mon Sep 17 00:00:00 2001 From: Ali Nasserzadeh Date: Tue, 5 May 2020 22:23:19 +0200 Subject: [PATCH 9/9] Rebased and bumped TypeScript version (stable) --- types/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/index.d.ts b/types/index.d.ts index 14bab359..406db91c 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,4 +1,4 @@ -// TypeScript Version: 3.1 +// TypeScript Version: 3.8 import { getQueriesForElement } from './get-queries-for-element'; import * as queries from './queries';