Skip to content

feat(queries): expose helper functions #66

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
merged 1 commit into from
Jul 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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