Skip to content

feat(configureTestIdAttribute): add ability to override data-testid [generic config] #164

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
Show file tree
Hide file tree
Changes from 2 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
12 changes: 12 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,18 @@
"contributions": [
"code"
]
},
{
"login": "RoystonS",
"name": "Royston Shufflebotham",
"avatar_url": "https://avatars0.githubusercontent.com/u/19773?v=4",
"profile": "https://github.com/RoystonS",
"contributions": [
"bug",
"code",
"doc",
"test"
]
}
]
}
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,21 @@

<hr />

<!-- prettier-ignore-start -->
[![Build Status][build-badge]][build]
[![Code Coverage][coverage-badge]][coverage]
[![version][version-badge]][package]
[![downloads][downloads-badge]][npmtrends]
[![MIT License][license-badge]][license]

[![All Contributors](https://img.shields.io/badge/all_contributors-42-orange.svg?style=flat-square)](#contributors)
[![All Contributors](https://img.shields.io/badge/all_contributors-43-orange.svg?style=flat-square)](#contributors)
[![PRs Welcome][prs-badge]][prs]
[![Code of Conduct][coc-badge]][coc]

[![Watch on GitHub][github-watch-badge]][github-watch]
[![Star on GitHub][github-star-badge]][github-star]
[![Tweet][twitter-badge]][twitter]
<!-- prettier-ignore-end -->

<div align="center">
<a href="https://testingjavascript.com">
Expand Down Expand Up @@ -456,6 +458,17 @@ const usernameInputElement = getByTestId(container, 'username-input')
> `data-testid`s from the blog post
> ["Making your UI tests resilient to change"][data-testid-blog-post]

#### Overriding `data-testid`

The `...ByTestId` functions in `dom-testing-library` use the attribute `data-testid`
by default, following the precedent set by
[React Native Web](https://github.com/kentcdodds/react-testing-library/issues/1)
which uses a `testID` prop to emit a `data-testid` attribute on the element,
and we recommend you adopt that attribute where possible.
But if you already have an existing codebase that uses a different attribute
for this purpose, you can override this value via
`configure({testIdAttribute: 'data-my-test-attribute'})`.

### `wait`

```typescript
Expand Down Expand Up @@ -1115,7 +1128,7 @@ Thanks goes to these people ([emoji key][emojis]):
| [<img src="https://avatars2.githubusercontent.com/u/21689428?v=4" width="100px;"/><br /><sub><b>Jonathan Stoye</b></sub>](http://jonathanstoye.de)<br />[📖](https://github.com/kentcdodds/dom-testing-library/commits?author=JonathanStoye "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/4126644?v=4" width="100px;"/><br /><sub><b>Sanghyeon Lee</b></sub>](https://github.com/yongdamsh)<br />[💡](#example-yongdamsh "Examples") | [<img src="https://avatars3.githubusercontent.com/u/8015514?v=4" width="100px;"/><br /><sub><b>Justice Mba </b></sub>](https://github.com/Dajust)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=Dajust "Code") [📖](https://github.com/kentcdodds/dom-testing-library/commits?author=Dajust "Documentation") [🤔](#ideas-Dajust "Ideas, Planning, & Feedback") | [<img src="https://avatars3.githubusercontent.com/u/340761?v=4" width="100px;"/><br /><sub><b>Wayne Crouch</b></sub>](https://github.com/wgcrouch)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=wgcrouch "Code") | [<img src="https://avatars1.githubusercontent.com/u/4996462?v=4" width="100px;"/><br /><sub><b>Ben Elliott</b></sub>](http://benjaminelliott.co.uk)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=benelliott "Code") | [<img src="https://avatars3.githubusercontent.com/u/577921?v=4" width="100px;"/><br /><sub><b>Ruben Costa</b></sub>](http://nuances.co)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=rubencosta "Code") | [<img src="https://avatars2.githubusercontent.com/u/4982001?v=4" width="100px;"/><br /><sub><b>Robert Smith</b></sub>](http://rbrtsmith.com/)<br />[🐛](https://github.com/kentcdodds/dom-testing-library/issues?q=author%3Arbrtsmith "Bug reports") [🤔](#ideas-rbrtsmith "Ideas, Planning, & Feedback") [📖](https://github.com/kentcdodds/dom-testing-library/commits?author=rbrtsmith "Documentation") |
| [<img src="https://avatars3.githubusercontent.com/u/881986?v=4" width="100px;"/><br /><sub><b>dadamssg</b></sub>](https://github.com/dadamssg)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=dadamssg "Code") | [<img src="https://avatars1.githubusercontent.com/u/186971?v=4" width="100px;"/><br /><sub><b>Neil Kistner</b></sub>](https://neilkistner.com/)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=wyze "Code") | [<img src="https://avatars3.githubusercontent.com/u/1448597?v=4" width="100px;"/><br /><sub><b>Ben Chauvette</b></sub>](http://bdchauvette.net/)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=bdchauvette "Code") | [<img src="https://avatars2.githubusercontent.com/u/777527?v=4" width="100px;"/><br /><sub><b>Jeff Baumgardt</b></sub>](https://github.com/JeffBaumgardt)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=JeffBaumgardt "Code") [📖](https://github.com/kentcdodds/dom-testing-library/commits?author=JeffBaumgardt "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/4658208?v=4" width="100px;"/><br /><sub><b>Matan Kushner</b></sub>](http://matchai.me)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=matchai "Code") [📖](https://github.com/kentcdodds/dom-testing-library/commits?author=matchai "Documentation") [🤔](#ideas-matchai "Ideas, Planning, & Feedback") [⚠️](https://github.com/kentcdodds/dom-testing-library/commits?author=matchai "Tests") | [<img src="https://avatars2.githubusercontent.com/u/5779538?v=4" width="100px;"/><br /><sub><b>Alex Wendte</b></sub>](http://www.wendtedesigns.com/)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=themostcolm "Code") [📖](https://github.com/kentcdodds/dom-testing-library/commits?author=themostcolm "Documentation") [⚠️](https://github.com/kentcdodds/dom-testing-library/commits?author=themostcolm "Tests") | [<img src="https://avatars0.githubusercontent.com/u/2196208?v=4" width="100px;"/><br /><sub><b>Tamas Fodor</b></sub>](https://github.com/ruffle1986)<br />[📖](https://github.com/kentcdodds/dom-testing-library/commits?author=ruffle1986 "Documentation") |
| [<img src="https://avatars3.githubusercontent.com/u/14793495?v=4" width="100px;"/><br /><sub><b>Benjamin Eckardt</b></sub>](https://github.com/BenjaminEckardt)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=BenjaminEckardt "Code") | [<img src="https://avatars3.githubusercontent.com/u/205752?v=4" width="100px;"/><br /><sub><b>Ryan Campbell</b></sub>](https://github.com/campbellr)<br />[📖](https://github.com/kentcdodds/dom-testing-library/commits?author=campbellr "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/1335519?v=4" width="100px;"/><br /><sub><b>Taylor Briggs</b></sub>](https://taylor-briggs.com)<br />[⚠️](https://github.com/kentcdodds/dom-testing-library/commits?author=TaylorBriggs "Tests") | [<img src="https://avatars2.githubusercontent.com/u/132233?v=4" width="100px;"/><br /><sub><b>John Gozde</b></sub>](https://github.com/jgoz)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=jgoz "Code") | [<img src="https://avatars2.githubusercontent.com/u/3382565?v=4" width="100px;"/><br /><sub><b>C. T. Lin</b></sub>](https://github.com/chentsulin)<br />[📖](https://github.com/kentcdodds/dom-testing-library/commits?author=chentsulin "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/5312329?v=4" width="100px;"/><br /><sub><b>Terrence Wong</b></sub>](http://terrencewwong.com)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=terrencewwong "Code") | [<img src="https://avatars0.githubusercontent.com/u/12230408?v=4" width="100px;"/><br /><sub><b>Soo Jae Hwang</b></sub>](https://www.ossfinder.com)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=misoguy "Code") |

| [<img src="https://avatars0.githubusercontent.com/u/19773?v=4" width="100px;"/><br /><sub><b>Royston Shufflebotham</b></sub>](https://github.com/RoystonS)<br />[🐛](https://github.com/kentcdodds/dom-testing-library/issues?q=author%3ARoystonS "Bug reports") [💻](https://github.com/kentcdodds/dom-testing-library/commits?author=RoystonS "Code") [📖](https://github.com/kentcdodds/dom-testing-library/commits?author=RoystonS "Documentation") [⚠️](https://github.com/kentcdodds/dom-testing-library/commits?author=RoystonS "Tests") |
<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors][all-contributors] specification.
Expand Down
39 changes: 29 additions & 10 deletions src/__tests__/element-queries.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'jest-dom/extend-expect'
import {configure} from '../config'
import {render, renderIntoDocument} from './helpers/test-utils'
import document from './helpers/document'

Expand Down Expand Up @@ -258,16 +259,34 @@ test('query/get select by text with multiple options selected', () => {
expect(queryBySelectText('Alaska').id).toEqual('state-select')
})

test('can get elements by data-testid attribute', () => {
const {queryByTestId} = render(`<div data-testid="firstName"></div>`)
expect(queryByTestId('firstName')).toBeTruthy()
expect(queryByTestId(/first/)).toBeTruthy()
expect(queryByTestId(testid => testid === 'firstName')).toBeTruthy()
// match should be exact, case-sensitive
expect(queryByTestId('firstname')).not.toBeTruthy()
expect(queryByTestId('first')).not.toBeTruthy()
expect(queryByTestId('firstNamePlusMore')).not.toBeTruthy()
expect(queryByTestId('first-name')).not.toBeTruthy()
describe('query by test id', () => {
test('can get elements by test id', () => {
const {queryByTestId} = render(`<div data-testid="firstName"></div>`)
expect(queryByTestId('firstName')).toBeTruthy()
expect(queryByTestId(/first/)).toBeTruthy()
expect(queryByTestId(testid => testid === 'firstName')).toBeTruthy()
// match should be exact, case-sensitive
expect(queryByTestId('firstname')).not.toBeTruthy()
expect(queryByTestId('first')).not.toBeTruthy()
expect(queryByTestId('firstNamePlusMore')).not.toBeTruthy()
expect(queryByTestId('first-name')).not.toBeTruthy()
})

test('can override test id attribute', () => {
const {queryByTestId} = render(`<div data-my-test-id="theTestId"></div>`)

configure({testIdAttribute: 'data-my-test-id'})
expect(queryByTestId('theTestId')).toBeTruthy()

configure({testIdAttribute: 'something-else'})
expect(queryByTestId('theTestId')).toBeFalsy()
})

afterEach(() => {
// Restore the default test id attribute
// even if these tests failed
configure({testIdAttribute: 'data-testid'})
})
})

test('getAll* matchers return an array', () => {
Expand Down
16 changes: 16 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// It would be cleaner for this to live inside './queries', but
// other parts of the code assume that all exports from
// './queries' are query functions.
let config = {
testIdAttribute: 'data-testid',
}

export function configure(configDelta) {
config = {
...config,
...configDelta,
}
}
export function getTestIdAttribute() {
return config.testIdAttribute
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me. My only nit is that I don't think there needs to be a special method to grab just this attribute; export the whole config object or a getConfig function instead.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Configure could also take an update function:

configure(currentConfig => { return {...newConfig} })

This would be nice if you want to read and extend subobjects or arrays (like the current set of queries) without importing the default value into the host file.

Copy link
Contributor Author

@RoystonS RoystonS Nov 29, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me. My only nit is that I don't think there needs to be a special method to grab just this attribute; export the whole config object or a getConfig function instead.

This comes from of some of my type-safety background. It's easy to get a silent failure from getConfig().mistypedConfigKeyName but getMistypedConfigKeyFunction() will always blow. But in this case the code will be protected by a unit test so that shouldn't be an issue. I'll tweak it to a getConfig function as that's more flexible than merely exposing the whole config.

}
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export * from './events'
export * from './get-queries-for-element'
export * from './query-helpers'
export * from './pretty-dom'
export {configure} from './config'

export {
// The original name of bindElementToQueries was weird
Expand Down
9 changes: 6 additions & 3 deletions src/queries.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
queryAllByAttribute,
queryByAttribute,
} from './query-helpers'
import {getTestIdAttribute} from './config'

// 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
Expand Down Expand Up @@ -150,8 +151,10 @@ function queryBySelectText(...args) {

const queryByPlaceholderText = queryByAttribute.bind(null, 'placeholder')
const queryAllByPlaceholderText = queryAllByAttribute.bind(null, 'placeholder')
const queryByTestId = queryByAttribute.bind(null, 'data-testid')
const queryAllByTestId = queryAllByAttribute.bind(null, 'data-testid')
const queryByTestId = (...args) =>
queryByAttribute(getTestIdAttribute(), ...args)
const queryAllByTestId = (...args) =>
queryAllByAttribute(getTestIdAttribute(), ...args)
const queryByValue = queryByAttribute.bind(null, 'value')
const queryAllByValue = queryAllByAttribute.bind(null, 'value')
const queryByRole = queryByAttribute.bind(null, 'role')
Expand Down Expand Up @@ -182,7 +185,7 @@ function getAllByTestId(container, id, ...rest) {
const els = queryAllByTestId(container, id, ...rest)
if (!els.length) {
throw getElementError(
`Unable to find an element by: [data-testid="${id}"]`,
`Unable to find an element by: [${getTestIdAttribute()}="${id}"]`,
container,
)
}
Expand Down
5 changes: 5 additions & 0 deletions typings/config.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface IConfig {
testIdAttribute: string
}

export function configure(configDelta: Partial<IConfig>): void
1 change: 1 addition & 0 deletions typings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ export * from './get-node-text'
export * from './events'
export * from './get-queries-for-element'
export * from './pretty-dom'
export * from './config'