docs/testcafe-testing-library/intro.mdx
testcafe-testing-library allows the use of dom testing library queries
within Testcafe for cross-browser
end-to-end web testing.
If you are new to the testing-library approach for writing tests, check out the this guide on which query to use as well as the cheat sheet.
npm install --save-dev testcafe @testing-library/testcafe
testcafe-testing-library provides custom Selectors allowing you to query the
dom.
Add the following to your .testcaferc.json file:
"clientScripts": [
{ "module": "@testing-library/dom/dist/@testing-library/dom.umd.js" }
],
You can now import screen which has all the get[All]By*, query[All]By*,
find[All]By* selectors that you can use in your tests.
import {screen} from '@testing-library/testcafe'
A note about queries in testcafe. Testcafe has built in waiting, for this reason, there's no difference between
queryByandfindByqueries in testcafe testing library.getByqueries will throw an exception (as designed) so they will fail immediately and do not work with the built in waiting that Testcafe provides.
To show some simple examples (from https://github.com/testing-library/testcafe-testing-library/blob/master/tests/testcafe/selectors.ts):
import {screen} from '@testing-library/testcafe'
test('getByPlaceHolderText', async t => {
await t.typeText(
screen.getByPlaceholderText('Placeholder Text'),
'Hello Placeholder',
)
})
test('getByText', async t => {
await t.click(screen.getByText('getByText'))
})
test('getByLabelText', async t => {
await t.typeText(
screen.getByLabelText('Label For Input Labelled By Id'),
'Hello Input Labelled By Id',
)
})
test('queryAllByText', async t => {
await t.expect(screen.queryAllByText('Button Text').exists).ok()
await t
.expect(screen.queryAllByText('Non-existing Button Text').exists)
.notOk()
})
You can customize the testIdAttribute using the configure function of DOM Testing Library in a few different ways:
import {configureOnce, getByTestId} from '@testing-library/testcafe'
test('can be configured once in a single page load', async t => {
await configureOnce({testIdAttribute: 'data-other-test-id'})
await t.click(screen.getByTestId('other-id'))
})
import {configure, screen} from '@testing-library/testcafe'
fixture`configure`.clientScripts(
configure({testIdAttribute: 'data-automation-id'}),
).page`http://localhost:13370`
test('supports alternative testIdAttribute', async t => {
await t.click(screen.getByTestId('image-with-random-alt-tag'))
})
test('still works after browser page load and reload', async t => {
await t.click(screen.getByText('Go to Page 2'))
await t.eval(() => location.reload(true))
await t
.click(screen.getByTestId('page2-thing'))
.expect(screen.getByText('second page').exists)
.ok()
})
Note: the dom-testing-library umd must come before your configure script
"clientScripts": [
"./node_modules/@testing-library/dom/dist/@testing-library/dom.umd.js",
"./path/to/my-app-testcafe.config.js"
]
window.TestingLibraryDom.configure({testIdAttribute: 'data-automation-id'})
By default the selectors come pre-bound to document.body, so no need to
provide a container. However, if you want to restrict your query using a
container, you can use within which can take either a string or a query
(get[All]By*, query[All]By*, find[All]By*).
withinimport {within, screen} from '@testing-library/testcafe'
fixture`within`.page`http://localhost:13370`
test('works with getBy* selectors', async t => {
await t
.expect(
within(screen.getByTestId('nested')).getByText('Button Text').exists,
)
.ok()
})
test('works with CSS selector strings', async t => {
const {getByText} = await within('#nested')
await t.click(getByText('Button Text')).ok()
})
test('works on any testcafe selector', async t => {
const nested = Selector('#nested')
await t.expect(within(nested).getByText('Button Text').exists).ok()
})
test('works with results from "byAll" query with index - regex', async t => {
const nestedDivs = screen.getAllByTestId(/nested/)
await t.expect(nestedDivs.count).eql(2)
await t
.expect(within(nestedDivs.nth(0)).getByText('Button Text').exists)
.ok()
.expect(
within(nestedDivs.nth(1)).getByText('text only in 2nd nested').exists,
)
.ok()
})