From 14468cbd097ceee88e795e5c0ffc5f6bea4fc2ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Gandecki?= Date: Sat, 5 May 2018 12:00:05 +0400 Subject: [PATCH 1/2] poc for getting/querying by title --- src/__tests__/element-queries.js | 13 +++++++++++++ src/queries.js | 30 ++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/__tests__/element-queries.js b/src/__tests__/element-queries.js index 2d646d77..51b08903 100644 --- a/src/__tests__/element-queries.js +++ b/src/__tests__/element-queries.js @@ -117,6 +117,19 @@ test('get element by its alt text', () => { expect(getByAltText(/fin.*nem.*poster$/i).src).toBe('/finding-nemo.png') }) +test('query/get element by its title', () => { + const {getByTitle, queryByTitle} = render(` +
+ + + +
+ `) + + expect(getByTitle('Delete').id).toEqual('2') + expect(queryByTitle('Delete').id).toEqual('2') +}) + test('can get elements by data-testid attribute', () => { const {queryByTestId} = render(`
`) expect(queryByTestId('firstName')).toBeInTheDOM() diff --git a/src/queries.js b/src/queries.js index 97b035f7..49913838 100644 --- a/src/queries.js +++ b/src/queries.js @@ -68,6 +68,32 @@ function queryByText(container, text, opts) { return firstResultOrNull(queryAllByText, container, text, opts) } +function queryAllByTitle(container, title, {selector = '*'} = {}) { + return Array.from(container.querySelectorAll(selector)).filter( + el => el.title === title, + ) +} + +function queryByTitle(container, title, opts) { + return firstResultOrNull(queryAllByTitle, container, title, opts) +} + +function getAllByTitle(container, title, ...rest) { + const els = queryAllByTitle(container, title, ...rest) + if (!els.length) { + throw new Error( + `Unable to find an element with the title: ${title}. \n\n${debugDOM( + container, + )}`, + ) + } + return els +} + +function getByTitle(...args) { + return firstResultOrNull(getAllByTitle, ...args) +} + // this is just a utility and not an exposed query. // There are no plans to expose this. function queryAllByAttribute(attribute, container, text, {exact = false} = {}) { @@ -215,6 +241,10 @@ export { queryAllByTestId, getByTestId, getAllByTestId, + queryByTitle, + queryAllByTitle, + getByTitle, + getAllByTitle, } /* eslint complexity:["error", 14] */ From fb20cfb694452f9f8cb49b374a3dfe7e364c0278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Gandecki?= Date: Sat, 5 May 2018 14:52:15 +0400 Subject: [PATCH 2/2] updated docs, tests, simplified implementation --- README.md | 10 ++++++++++ src/__tests__/__snapshots__/element-queries.js.snap | 8 ++++++++ src/__tests__/element-queries.js | 2 ++ src/queries.js | 12 ++++-------- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index cf790132..57fe9766 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,7 @@ when a real user uses it. * [`getByPlaceholderText(container: HTMLElement, text: TextMatch): HTMLElement`](#getbyplaceholdertextcontainer-htmlelement-text-textmatch-htmlelement) * [`getByText(container: HTMLElement, text: TextMatch): HTMLElement`](#getbytextcontainer-htmlelement-text-textmatch-htmlelement) * [`getByAltText(container: HTMLElement, text: TextMatch): HTMLElement`](#getbyalttextcontainer-htmlelement-text-textmatch-htmlelement) + * [`getByTitle(container: HTMLElement, title: ExactTextMatch): HTMLElement`](#getbytitlecontainer-htmlelement-title-exacttextmatch-htmlelement) * [`getByTestId(container: HTMLElement, text: ExactTextMatch): HTMLElement`](#getbytestidcontainer-htmlelement-text-exacttextmatch-htmlelement) * [`wait`](#wait) * [`waitForElement`](#waitforelement) @@ -250,6 +251,15 @@ and [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/area) const incrediblesPosterImg = getByAltText(container, /incredibles.*poster$/i) ``` +### `getByTitle(container: HTMLElement, title: ExactTextMatch): HTMLElement` + +This will return the element that has the matching `title` attribute. + +```javascript +// +const deleteElement = getByTitle(container, 'Delete') +``` + ### `getByTestId(container: HTMLElement, text: ExactTextMatch): HTMLElement` A shortcut to `` container.querySelector(`[data-testid="${yourId}"]`) `` (and it diff --git a/src/__tests__/__snapshots__/element-queries.js.snap b/src/__tests__/__snapshots__/element-queries.js.snap index a026cde0..67c2c6a9 100644 --- a/src/__tests__/__snapshots__/element-queries.js.snap +++ b/src/__tests__/__snapshots__/element-queries.js.snap @@ -40,6 +40,14 @@ exports[`get throws a useful error message 5`] = ` " `; +exports[`get throws a useful error message 6`] = ` +"Unable to find an element with the title: LucyRicardo. + +
 + 
 +
" +`; + exports[`label with no form control 1`] = ` "Found a label with the text of: alone, however no form control was found associated to that label. Make sure you're using the \\"for\\" attribute or \\"aria-labelledby\\" attribute correctly. diff --git a/src/__tests__/element-queries.js b/src/__tests__/element-queries.js index 51b08903..ae00396f 100644 --- a/src/__tests__/element-queries.js +++ b/src/__tests__/element-queries.js @@ -23,6 +23,7 @@ test('get throws a useful error message', () => { getByText, getByTestId, getByAltText, + getByTitle, } = render('
') expect(() => getByLabelText('LucyRicardo')).toThrowErrorMatchingSnapshot() expect(() => @@ -31,6 +32,7 @@ test('get throws a useful error message', () => { expect(() => getByText('LucyRicardo')).toThrowErrorMatchingSnapshot() expect(() => getByTestId('LucyRicardo')).toThrowErrorMatchingSnapshot() expect(() => getByAltText('LucyRicardo')).toThrowErrorMatchingSnapshot() + expect(() => getByTitle('LucyRicardo')).toThrowErrorMatchingSnapshot() }) test('can get elements by matching their text content', () => { diff --git a/src/queries.js b/src/queries.js index 49913838..7e666549 100644 --- a/src/queries.js +++ b/src/queries.js @@ -68,15 +68,11 @@ function queryByText(container, text, opts) { return firstResultOrNull(queryAllByText, container, text, opts) } -function queryAllByTitle(container, title, {selector = '*'} = {}) { - return Array.from(container.querySelectorAll(selector)).filter( - el => el.title === title, - ) -} +const queryAllByTitle = (...args) => + queryAllByAttribute('title', ...args, {exact: true}) -function queryByTitle(container, title, opts) { - return firstResultOrNull(queryAllByTitle, container, title, opts) -} +const queryByTitle = (...args) => + queryByAttribute('title', ...args, {exact: true}) function getAllByTitle(container, title, ...rest) { const els = queryAllByTitle(container, title, ...rest)