From e398a08ca9fcbb380d0cddec670ad14d26df8808 Mon Sep 17 00:00:00 2001 From: Alex Krolick Date: Sun, 8 Jul 2018 10:54:02 -0700 Subject: [PATCH] feat(queries): expose helper functions These are useful for creating additional queries outside the library --- src/index.js | 9 +++--- src/queries.js | 52 ++++------------------------------- src/query-helpers.js | 56 ++++++++++++++++++++++++++++++++++++++ typings/index.d.ts | 4 ++- typings/queries.d.ts | 21 ++++---------- typings/query-helpers.d.ts | 28 +++++++++++++++++++ 6 files changed, 103 insertions(+), 67 deletions(-) create mode 100644 src/query-helpers.js create mode 100644 typings/query-helpers.d.ts diff --git a/src/index.js b/src/index.js index 90f93233..13b1bd49 100644 --- a/src/index.js +++ b/src/index.js @@ -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' @@ -12,6 +9,7 @@ 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 { @@ -19,4 +17,7 @@ export { // 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, } diff --git a/src/queries.js b/src/queries.js index 3b6f3aab..d57b3520 100644 --- a/src/queries.js +++ b/src/queries.js @@ -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, @@ -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') diff --git a/src/query-helpers.js b/src/query-helpers.js new file mode 100644 index 00000000..8a8e7751 --- /dev/null +++ b/src/query-helpers.js @@ -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, +} diff --git a/typings/index.d.ts b/typings/index.d.ts index 147bceff..a0efa634 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -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' diff --git a/typings/queries.d.ts b/typings/queries.d.ts index 4b02ebea..01bcab45 100644 --- a/typings/queries.d.ts +++ b/typings/queries.d.ts @@ -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, diff --git a/typings/query-helpers.d.ts b/typings/query-helpers.d.ts new file mode 100644 index 00000000..093574ea --- /dev/null +++ b/typings/query-helpers.d.ts @@ -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