Skip to content

Commit

Permalink
feat(queries): expose helper functions (#66)
Browse files Browse the repository at this point in the history
These are useful for creating additional queries outside the library
  • Loading branch information
alexkrolick authored and Kent C. Dodds committed Jul 8, 2018
1 parent 2d98da2 commit 256f899
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 67 deletions.
9 changes: 5 additions & 4 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import {getQueriesForElement} from './get-queries-for-element'
import * as queries from './queries'

// exporting on the queries namespace as a convenience
// in addition to exporting the queries themselves
export {queries}
import * as queryHelpers from './query-helpers'

export * from './queries'
export * from './wait'
Expand All @@ -12,11 +9,15 @@ export * from './matches'
export * from './get-node-text'
export * from './events'
export * from './get-queries-for-element'
export * from './query-helpers'
export * from './pretty-dom'

export {
// The original name of bindElementToQueries was weird
// The new name is better. Remove this in the next major version bump.
getQueriesForElement as bindElementToQueries,
getQueriesForElement as within,
// export query utils under a namespace for convenience:
queries,
queryHelpers,
}
52 changes: 6 additions & 46 deletions src/queries.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,16 @@
import {fuzzyMatches, matches} from './matches'
import {getNodeText} from './get-node-text'
import {prettyDOM} from './pretty-dom'

function debugDOM(htmlElement) {
const limit = process.env.DEBUG_PRINT_LIMIT || 7000
const inNode = typeof process !== 'undefined' && process.versions !== undefined && process.versions.node !== undefined
const inCypress = typeof window !== 'undefined' && window.Cypress
/* istanbul ignore else */
if (inCypress) {
return ''
} else if (inNode) {
return prettyDOM(htmlElement, limit)
} else {
return prettyDOM(htmlElement, limit, {highlight: false})
}
}

function getElementError(message, container) {
return new Error([message, debugDOM(container)].filter(Boolean).join('\n\n'))
}
import {
getElementError,
firstResultOrNull,
queryAllByAttribute,
queryByAttribute,
} from './query-helpers'

// Here are the queries for the library.
// The queries here should only be things that are accessible to both users who are using a screen reader
// and those who are not using a screen reader (with the exception of the data-testid attribute query).

function firstResultOrNull(queryFunction, ...args) {
const result = queryFunction(...args)
if (result.length === 0) return null
return result[0]
}

function queryAllLabelsByText(
container,
text,
Expand Down Expand Up @@ -101,27 +82,6 @@ function queryByText(...args) {
return firstResultOrNull(queryAllByText, ...args)
}

// this is just a utility and not an exposed query.
// There are no plans to expose this.
function queryAllByAttribute(
attribute,
container,
text,
{exact = true, collapseWhitespace = true, trim = true} = {},
) {
const matcher = exact ? matches : fuzzyMatches
const matchOpts = {collapseWhitespace, trim}
return Array.from(container.querySelectorAll(`[${attribute}]`)).filter(node =>
matcher(node.getAttribute(attribute), node, text, matchOpts),
)
}

// this is just a utility and not an exposed query.
// There are no plans to expose this.
function queryByAttribute(...args) {
return firstResultOrNull(queryAllByAttribute, ...args)
}

const queryByPlaceholderText = queryByAttribute.bind(null, 'placeholder')
const queryAllByPlaceholderText = queryAllByAttribute.bind(null, 'placeholder')
const queryByTestId = queryByAttribute.bind(null, 'data-testid')
Expand Down
56 changes: 56 additions & 0 deletions src/query-helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import {prettyDOM} from './pretty-dom'
import {fuzzyMatches, matches} from './matches'

/* eslint-disable complexity */
function debugDOM(htmlElement) {
const limit = process.env.DEBUG_PRINT_LIMIT || 7000
const inNode =
typeof process !== 'undefined' &&
process.versions !== undefined &&
process.versions.node !== undefined
const inCypress = typeof window !== 'undefined' && window.Cypress
/* istanbul ignore else */
if (inCypress) {
return ''
} else if (inNode) {
return prettyDOM(htmlElement, limit)
} else {
return prettyDOM(htmlElement, limit, {highlight: false})
}
}
/* eslint-enable complexity */

function getElementError(message, container) {
return new Error([message, debugDOM(container)].filter(Boolean).join('\n\n'))
}

function firstResultOrNull(queryFunction, ...args) {
const result = queryFunction(...args)
if (result.length === 0) return null
return result[0]
}

function queryAllByAttribute(
attribute,
container,
text,
{exact = true, collapseWhitespace = true, trim = true} = {},
) {
const matcher = exact ? matches : fuzzyMatches
const matchOpts = {collapseWhitespace, trim}
return Array.from(container.querySelectorAll(`[${attribute}]`)).filter(node =>
matcher(node.getAttribute(attribute), node, text, matchOpts),
)
}

function queryByAttribute(...args) {
return firstResultOrNull(queryAllByAttribute, ...args)
}

export {
debugDOM,
getElementError,
firstResultOrNull,
queryAllByAttribute,
queryByAttribute,
}
4 changes: 3 additions & 1 deletion typings/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// TypeScript Version: 2.8
import * as queries from './queries'
import * as queryHelpers from './query-helpers'

export {queries}
export {queries, queryHelpers}

export * from './queries'
export * from './query-helpers'
export * from './wait'
export * from './wait-for-element'
export * from './matches'
Expand Down
21 changes: 5 additions & 16 deletions typings/queries.d.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,9 @@
import {Matcher, MatcherOptions} from './matches'

export interface SelectorMatcherOptions extends MatcherOptions {
selector?: string
}

export type QueryByAttribute = (
container: HTMLElement,
id: Matcher,
options?: MatcherOptions,
) => HTMLElement | null

export type AllByAttribute = (
container: HTMLElement,
id: Matcher,
options?: MatcherOptions,
) => HTMLElement[]
import {
QueryByAttribute,
AllByAttribute,
SelectorMatcherOptions,
} from './query-helpers'

export type GetByAttribute = (
container: HTMLElement,
Expand Down
28 changes: 28 additions & 0 deletions typings/query-helpers.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {Matcher, MatcherOptions} from './matches'

export interface SelectorMatcherOptions extends MatcherOptions {
selector?: string
}

export type QueryByAttribute = (
container: HTMLElement,
id: Matcher,
options?: MatcherOptions,
) => HTMLElement | null

export type AllByAttribute = (
container: HTMLElement,
id: Matcher,
options?: MatcherOptions,
) => HTMLElement[]

export const queryByAttribute: QueryByAttribute
export const queryAllByAttribute: AllByAttribute
export const firstResultOrNull: (
fn: AllByAttribute,
container?: HTMLElement,
id?: Matcher,
options?: MatcherOptions,
) => HTMLElement | null
export const debugDOM: (htmlElement: HTMLElement) => string
export const getElementError: (message: string, container: HTMLElement) => Error

0 comments on commit 256f899

Please sign in to comment.