Skip to content

Commit

Permalink
feat(queryByTitle): add new query for title attribute (#34)
Browse files Browse the repository at this point in the history
* poc for getting/querying by title

* updated docs, tests, simplified implementation
  • Loading branch information
lgandecki authored and Kent C. Dodds committed May 5, 2018
1 parent d22a9ff commit 5fe849f
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 0 deletions.
10 changes: 10 additions & 0 deletions README.md
Expand Up @@ -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)
Expand Down Expand Up @@ -250,6 +251,15 @@ and [`<area>`](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
// <span title="Delete" id="2" />
const deleteElement = getByTitle(container, 'Delete')
```

### `getByTestId(container: HTMLElement, text: ExactTextMatch): HTMLElement`

A shortcut to `` container.querySelector(`[data-testid="${yourId}"]`) `` (and it
Expand Down
8 changes: 8 additions & 0 deletions src/__tests__/__snapshots__/element-queries.js.snap
Expand Up @@ -40,6 +40,14 @@ exports[`get throws a useful error message 5`] = `
</div>"
`;

exports[`get throws a useful error message 6`] = `
"Unable to find an element with the title: LucyRicardo.
<div>
<div />
</div>"
`;

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.
Expand Down
15 changes: 15 additions & 0 deletions src/__tests__/element-queries.js
Expand Up @@ -23,6 +23,7 @@ test('get throws a useful error message', () => {
getByText,
getByTestId,
getByAltText,
getByTitle,
} = render('<div />')
expect(() => getByLabelText('LucyRicardo')).toThrowErrorMatchingSnapshot()
expect(() =>
Expand All @@ -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', () => {
Expand Down Expand Up @@ -117,6 +119,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(`
<div>
<span title="Ignore this" id="1"/>
<span title="Delete" id="2"/>
<span title="Ignore this as well" id="3"/>
</div>
`)

expect(getByTitle('Delete').id).toEqual('2')
expect(queryByTitle('Delete').id).toEqual('2')
})

test('can get elements by data-testid attribute', () => {
const {queryByTestId} = render(`<div data-testid="firstName"></div>`)
expect(queryByTestId('firstName')).toBeInTheDOM()
Expand Down
26 changes: 26 additions & 0 deletions src/queries.js
Expand Up @@ -68,6 +68,28 @@ function queryByText(container, text, opts) {
return firstResultOrNull(queryAllByText, container, text, opts)
}

const queryAllByTitle = (...args) =>
queryAllByAttribute('title', ...args, {exact: true})

const queryByTitle = (...args) =>
queryByAttribute('title', ...args, {exact: true})

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} = {}) {
Expand Down Expand Up @@ -215,6 +237,10 @@ export {
queryAllByTestId,
getByTestId,
getAllByTestId,
queryByTitle,
queryAllByTitle,
getByTitle,
getAllByTitle,
}

/* eslint complexity:["error", 14] */

0 comments on commit 5fe849f

Please sign in to comment.