Skip to content

feat: migrate some files to typescript #848

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"node": ">=10"
},
"scripts": {
"build": "kcd-scripts build --ignore \"**/__tests__/**,**/__node_tests__/**,**/__mocks__/**\" && kcd-scripts build --bundle --no-clean",
"build": "kcd-scripts build --no-ts-defs --ignore \"**/__tests__/**,**/__node_tests__/**,**/__mocks__/**\" && kcd-scripts build --no-ts-defs --bundle --no-clean",
"lint": "kcd-scripts lint",
"setup": "npm install && npm run validate -s",
"test": "kcd-scripts test",
Expand Down Expand Up @@ -53,7 +53,7 @@
"jest-serializer-ansi": "^1.0.3",
"jest-watch-select-projects": "^2.0.0",
"jsdom": "^16.4.0",
"kcd-scripts": "^7.5.1",
"kcd-scripts": "^7.5.3",
"typescript": "^4.1.2"
},
"eslintConfig": {
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {configure, getConfig} from '../config'
import {configure, getConfig} from '../config.ts'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting. Is the extension required? I didn't think it was and would prefer to not have to specify it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like too, but I didn't find a way to not specify it. eslint gave me some trouble.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can deal with that later. Not a ship stopper.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll leave the point open, maybe someone could help


describe('configuration API', () => {
let originalConfig
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/element-queries.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {configure} from '../config'
import {configure} from '../config.ts'
import {render, renderIntoDocument} from './helpers/test-utils'

beforeEach(() => {
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/get-by-errors.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import cases from 'jest-in-case'
import {screen} from '../'
import {configure, getConfig} from '../config'
import {configure, getConfig} from '../config.ts'
import {render} from './helpers/test-utils'

const originalConfig = getConfig()
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/matches.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {fuzzyMatches, matches} from '../matches'
import {fuzzyMatches, matches} from '../matches.ts'

// unit tests for text match utils

Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/query-helper.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as queryHelpers from '../query-helpers'
import {configure, getConfig} from '../config'
import {configure, getConfig} from '../config.ts'

const originalConfig = getConfig()
beforeEach(() => {
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/role.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {configure, getConfig} from '../config'
import {configure, getConfig} from '../config.ts'
import {getQueriesForElement} from '../get-queries-for-element'
import {render, renderIntoDocument} from './helpers/test-utils'

Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/suggestions.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {configure} from '../config'
import {configure} from '../config.ts'
import {screen, getSuggestedQuery} from '..'
import {renderIntoDocument, render} from './helpers/test-utils'

Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/wait-for.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {waitFor} from '../'
import {configure, getConfig} from '../config'
import {configure, getConfig} from '../config.ts'
import {renderIntoDocument} from './helpers/test-utils'

function deferred() {
Expand Down
14 changes: 11 additions & 3 deletions src/config.js → src/config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import {Config, ConfigFn} from '../types/config'
import {Callback} from '../types/utils'
import {prettyDOM} from './pretty-dom'

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.
Expand Down Expand Up @@ -36,7 +42,9 @@ let config = {
}

export const DEFAULT_IGNORE_TAGS = 'script, style'
export function runWithExpensiveErrorDiagnosticsDisabled(callback) {
export function runWithExpensiveErrorDiagnosticsDisabled<T>(
callback: Callback<T>,
) {
try {
config._disableExpensiveErrorDiagnostics = true
return callback()
Expand All @@ -45,7 +53,7 @@ export function runWithExpensiveErrorDiagnosticsDisabled(callback) {
}
}

export function configure(newConfig) {
export function configure(newConfig: Partial<Config> | ConfigFn) {
if (typeof newConfig === 'function') {
// Pass the existing config out to the provided function
// and accept a delta in return
Expand Down
17 changes: 10 additions & 7 deletions src/events.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {getConfig} from './config'
import {getConfig} from './config.ts'
import {getWindowFromNode} from './helpers'
import {eventMap, eventAliasMap} from './event-map'

Expand Down Expand Up @@ -71,12 +71,15 @@ function createEvent(
/* istanbul ignore if */
if (typeof window.DataTransfer === 'function') {
Object.defineProperty(event, dataTransferKey, {
value: Object
.getOwnPropertyNames(dataTransferValue)
.reduce((acc, propName) => {
Object.defineProperty(acc, propName, {value: dataTransferValue[propName]});
return acc;
}, new window.DataTransfer())
value: Object.getOwnPropertyNames(dataTransferValue).reduce(
(acc, propName) => {
Object.defineProperty(acc, propName, {
value: dataTransferValue[propName],
})
return acc
},
new window.DataTransfer(),
),
})
} else {
Object.defineProperty(event, dataTransferKey, {
Expand Down
4 changes: 2 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ export * from './wait-for'
export * from './wait-for-element'
export * from './wait-for-element-to-be-removed'
export * from './wait-for-dom-change'
export {getDefaultNormalizer} from './matches'
export {getDefaultNormalizer} from './matches.ts'
export * from './get-node-text'
export * from './events'
export * from './get-queries-for-element'
export * from './screen'
export * from './query-helpers'
export {getRoles, logRoles, isInaccessible} from './role-helpers'
export * from './pretty-dom'
export {configure, getConfig} from './config'
export {configure, getConfig} from './config.ts'
export * from './suggestions'

export {
Expand Down
43 changes: 36 additions & 7 deletions src/matches.js → src/matches.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,35 @@
function assertNotNullOrUndefined(matcher) {
if (matcher == null) {
import {
Matcher,
NormalizerFn,
NormalizerOptions,
DefaultNormalizerOptions,
} from '../types'
import {Nullish} from '../types/utils'

function assertNotNullOrUndefined<T>(
matcher: T,
): asserts matcher is NonNullable<T> {
if (matcher === null || matcher === undefined) {
throw new Error(
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
`It looks like ${matcher} was passed instead of a matcher. Did you do something like getByText(${matcher})?`,
)
}
}

function fuzzyMatches(textToMatch, node, matcher, normalizer) {
function fuzzyMatches(
textToMatch: Nullish<string>,
node: Nullish<Element>,
matcher: Nullish<Matcher>,
normalizer: NormalizerFn,
) {
if (typeof textToMatch !== 'string') {
return false
}

assertNotNullOrUndefined(matcher)

const normalizedText = normalizer(textToMatch)

if (typeof matcher === 'string') {
return normalizedText.toLowerCase().includes(matcher.toLowerCase())
} else if (typeof matcher === 'function') {
Expand All @@ -23,7 +39,12 @@ function fuzzyMatches(textToMatch, node, matcher, normalizer) {
}
}

function matches(textToMatch, node, matcher, normalizer) {
function matches(
textToMatch: Nullish<string>,
node: Nullish<Element>,
matcher: Nullish<Matcher>,
normalizer: NormalizerFn,
) {
if (typeof textToMatch !== 'string') {
return false
}
Expand All @@ -40,7 +61,10 @@ function matches(textToMatch, node, matcher, normalizer) {
}
}

function getDefaultNormalizer({trim = true, collapseWhitespace = true} = {}) {
function getDefaultNormalizer({
trim = true,
collapseWhitespace = true,
}: DefaultNormalizerOptions = {}): NormalizerFn {
return text => {
let normalizedText = text
normalizedText = trim ? normalizedText.trim() : normalizedText
Expand All @@ -60,7 +84,12 @@ 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,
}: NormalizerOptions) {
if (normalizer) {
// User has specified a custom normalizer
if (
Expand Down
4 changes: 2 additions & 2 deletions src/queries/all-utils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export * from '../matches'
export * from '../matches.ts'
export * from '../get-node-text'
export * from '../query-helpers'
export * from '../config'
export * from '../config.ts'
2 changes: 1 addition & 1 deletion src/queries/label-text.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {getConfig} from '../config'
import {getConfig} from '../config.ts'
import {checkContainerType} from '../helpers'
import {getLabels, getRealLabels, getLabelContent} from '../label-helpers'
import {
Expand Down
2 changes: 1 addition & 1 deletion src/queries/text.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {wrapAllByQueryWithSuggestion} from '../query-helpers'
import {checkContainerType} from '../helpers'
import {DEFAULT_IGNORE_TAGS} from '../config'
import {DEFAULT_IGNORE_TAGS} from '../config.ts'
import {
fuzzyMatches,
matches,
Expand Down
4 changes: 2 additions & 2 deletions src/query-helpers.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {getSuggestedQuery} from './suggestions'
import {fuzzyMatches, matches, makeNormalizer} from './matches'
import {fuzzyMatches, matches, makeNormalizer} from './matches.ts'
import {waitFor} from './wait-for'
import {getConfig} from './config'
import {getConfig} from './config.ts'

function getElementError(message, container) {
return getConfig().getElementError(message, container)
Expand Down
2 changes: 1 addition & 1 deletion src/role-helpers.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {elementRoles} from 'aria-query'
import {computeAccessibleName} from 'dom-accessibility-api'
import {prettyDOM} from './pretty-dom'
import {getConfig} from './config'
import {getConfig} from './config.ts'

const elementRoleList = buildElementRoleList(elementRoles)

Expand Down
4 changes: 2 additions & 2 deletions src/suggestions.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {computeAccessibleName} from 'dom-accessibility-api'
import {getDefaultNormalizer} from './matches'
import {getDefaultNormalizer} from './matches.ts'
import {getNodeText} from './get-node-text'
import {DEFAULT_IGNORE_TAGS, getConfig} from './config'
import {DEFAULT_IGNORE_TAGS, getConfig} from './config.ts'
import {getImplicitAriaRoles, isInaccessible} from './role-helpers'
import {getLabels} from './label-helpers'

Expand Down
2 changes: 1 addition & 1 deletion src/wait-for-dom-change.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
clearTimeout,
runWithRealTimers,
} from './helpers'
import {getConfig} from './config'
import {getConfig} from './config.ts'

let hasWarned = false

Expand Down
2 changes: 1 addition & 1 deletion src/wait-for.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
setTimeout,
clearTimeout,
} from './helpers'
import {getConfig, runWithExpensiveErrorDiagnosticsDisabled} from './config'
import {getConfig, runWithExpensiveErrorDiagnosticsDisabled} from './config.ts'

// This is so the stack trace the developer sees is one that's
// closer to their code (because async stack traces are hard to follow).
Expand Down
2 changes: 2 additions & 0 deletions tests/jest.config.dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ const baseConfig = require('kcd-scripts/jest')

module.exports = {
...baseConfig,
moduleFileExtensions: [...baseConfig.moduleFileExtensions, 'd.ts'],
moduleDirectories: [...baseConfig.moduleDirectories, 'types'],
rootDir: path.join(__dirname, '..'),
displayName: 'dom',
coveragePathIgnorePatterns: [
Expand Down
2 changes: 2 additions & 0 deletions tests/jest.config.node.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ const baseConfig = require('kcd-scripts/jest')

module.exports = {
...baseConfig,
moduleFileExtensions: [...baseConfig.moduleFileExtensions, 'd.ts'],
moduleDirectories: [...baseConfig.moduleDirectories, 'types'],
rootDir: path.join(__dirname, '..'),
displayName: 'node',
testEnvironment: 'jest-environment-node',
Expand Down
7 changes: 7 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "./node_modules/kcd-scripts/shared-tsconfig.json",
"compilerOptions": {
"allowJs": true
},
"include": ["./src", "./types"]
}
4 changes: 3 additions & 1 deletion types/config.d.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
export interface Config {
testIdAttribute: string
// eslint-disable-next-line @typescript-eslint/no-explicit-any
asyncWrapper(cb: (...args: any[]) => any): Promise<any>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
eventWrapper(cb: (...args: any[]) => any): void
asyncUtilTimeout: number
computedStyleSupportsPseudoElements: boolean
defaultHidden: boolean
showOriginalStackTrace: boolean
throwSuggestions: boolean
getElementError: (message: string, container: HTMLElement) => Error
getElementError: (message: string | null, container: Element) => Error
}

export interface ConfigFn {
Expand Down
12 changes: 10 additions & 2 deletions types/matches.d.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import {ARIARole} from 'aria-query'
import {Nullish} from './utils'

export type MatcherFunction = (content: string, element: HTMLElement) => boolean
export type Matcher = MatcherFunction | {}
export type MatcherFunction = (
content: string,
element: Nullish<Element>,
) => boolean
export type Matcher = MatcherFunction | RegExp | string

// Get autocomplete for ARIARole union types, while still supporting another string
// Ref: https://github.com/microsoft/TypeScript/issues/29729#issuecomment-505826972
export type ByRoleMatcher = ARIARole | MatcherFunction | {}

export type NormalizerFn = (text: string) => string

export type NormalizerOptions = DefaultNormalizerOptions & {
normalizer?: NormalizerFn
}

export interface MatcherOptions {
exact?: boolean
/** Use normalizer with getDefaultNormalizer instead */
Expand Down
3 changes: 1 addition & 2 deletions types/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
{
"extends": "../node_modules/kcd-scripts/shared-tsconfig.json",
"include": ["."]
"extends": "../tsconfig.json"
}
7 changes: 7 additions & 0 deletions types/utils.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export type Nullish<T> = T | null | undefined

export type Callback<T> = () => T

export function isNotNull<T>(arg: T): arg is NonNullable<T> {
return arg !== null
}