├── .all-contributorsrc
├── .eslintrc
├── .gitattributes
├── .github
├── ISSUE_TEMPLATE.md
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ └── validate.yml
├── .gitignore
├── .huskyrc.js
├── .npmrc
├── .prettierignore
├── .prettierrc.js
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── add-commands.js
├── cypress.config.js
├── cypress
├── .eslintrc
├── e2e
│ └── find.cy.js
├── fixtures
│ └── test-app
│ │ ├── index.html
│ │ └── next-page.html
└── support
│ └── e2e.js
├── jest.config.js
├── lint-staged.config.js
├── other
├── CODE_OF_CONDUCT.md
├── MAINTAINING.md
├── USERS.md
├── manual-releases.md
├── testingjavascript.jpg
└── tiger.png
├── package.json
├── src
├── __tests__
│ ├── add-commands.js
│ └── commands.js
├── add-commands.js
├── index.js
└── utils.js
└── types
├── add-commands.d.ts
├── index.d.ts
├── test.ts
└── tsconfig.json
/.all-contributorsrc:
--------------------------------------------------------------------------------
1 | {
2 | "projectName": "cypress-testing-library",
3 | "projectOwner": "testing-library",
4 | "files": [
5 | "README.md"
6 | ],
7 | "imageSize": 100,
8 | "commit": false,
9 | "skipCi": false,
10 | "contributors": [
11 | {
12 | "login": "kentcdodds",
13 | "name": "Kent C. Dodds",
14 | "avatar_url": "https://avatars.githubusercontent.com/u/1500684?v=3",
15 | "profile": "https://kentcdodds.com",
16 | "contributions": [
17 | "code",
18 | "doc",
19 | "infra",
20 | "test"
21 | ]
22 | },
23 | {
24 | "login": "sompylasar",
25 | "name": "Ivan Babak",
26 | "avatar_url": "https://avatars2.githubusercontent.com/u/498274?v=4",
27 | "profile": "https://sompylasar.github.io",
28 | "contributions": [
29 | "code",
30 | "ideas"
31 | ]
32 | },
33 | {
34 | "login": "lgandecki",
35 | "name": "Łukasz Gandecki",
36 | "avatar_url": "https://avatars1.githubusercontent.com/u/4002543?v=4",
37 | "profile": "http://team.thebrain.pro",
38 | "contributions": [
39 | "code",
40 | "test"
41 | ]
42 | },
43 | {
44 | "login": "npeterkamps",
45 | "name": "Peter Kamps",
46 | "avatar_url": "https://avatars1.githubusercontent.com/u/25429764?v=4",
47 | "profile": "https://github.com/npeterkamps",
48 | "contributions": [
49 | "code",
50 | "doc",
51 | "ideas",
52 | "test"
53 | ]
54 | },
55 | {
56 | "login": "airato",
57 | "name": "Airat Aminev",
58 | "avatar_url": "https://avatars3.githubusercontent.com/u/4506749?v=4",
59 | "profile": "https://github.com/airato",
60 | "contributions": [
61 | "code",
62 | "test",
63 | "tool"
64 | ]
65 | },
66 | {
67 | "login": "adrian1358",
68 | "name": "Adrian Smijulj",
69 | "avatar_url": "https://avatars0.githubusercontent.com/u/5121148?v=4",
70 | "profile": "https://www.webiny.com",
71 | "contributions": [
72 | "code"
73 | ]
74 | },
75 | {
76 | "login": "misoguy",
77 | "name": "Soo Jae Hwang",
78 | "avatar_url": "https://avatars0.githubusercontent.com/u/12230408?v=4",
79 | "profile": "https://www.ossfinder.com",
80 | "contributions": [
81 | "bug",
82 | "code",
83 | "test"
84 | ]
85 | },
86 | {
87 | "login": "wKovacs64",
88 | "name": "Justin Hall",
89 | "avatar_url": "https://avatars1.githubusercontent.com/u/1288694?v=4",
90 | "profile": "https://github.com/wKovacs64",
91 | "contributions": [
92 | "code",
93 | "test"
94 | ]
95 | },
96 | {
97 | "login": "euZebe",
98 | "name": "euzebe",
99 | "avatar_url": "https://avatars3.githubusercontent.com/u/9463809?v=4",
100 | "profile": "https://github.com/euZebe",
101 | "contributions": [
102 | "doc"
103 | ]
104 | },
105 | {
106 | "login": "jkdowdle",
107 | "name": "jkdowdle",
108 | "avatar_url": "https://avatars0.githubusercontent.com/u/19804196?v=4",
109 | "profile": "https://github.com/jkdowdle",
110 | "contributions": [
111 | "code"
112 | ]
113 | },
114 | {
115 | "login": "existentialism",
116 | "name": "Brian Ng",
117 | "avatar_url": "https://avatars3.githubusercontent.com/u/56288?v=4",
118 | "profile": "https://brian.ng",
119 | "contributions": [
120 | "code"
121 | ]
122 | },
123 | {
124 | "login": "klaari",
125 | "name": "Kari Laari",
126 | "avatar_url": "https://avatars2.githubusercontent.com/u/2477131?v=4",
127 | "profile": "https://karilaari.fi",
128 | "contributions": [
129 | "doc"
130 | ]
131 | },
132 | {
133 | "login": "ppi-buck",
134 | "name": "Basti Buck",
135 | "avatar_url": "https://avatars2.githubusercontent.com/u/37330764?v=4",
136 | "profile": "https://github.com/ppi-buck",
137 | "contributions": [
138 | "code"
139 | ]
140 | },
141 | {
142 | "login": "ShimiTheFirst",
143 | "name": "ShimiTheFirst",
144 | "avatar_url": "https://avatars2.githubusercontent.com/u/25421369?v=4",
145 | "profile": "https://github.com/ShimiTheFirst",
146 | "contributions": [
147 | "bug"
148 | ]
149 | },
150 | {
151 | "login": "omerose",
152 | "name": "omerose",
153 | "avatar_url": "https://avatars2.githubusercontent.com/u/9358542?v=4",
154 | "profile": "https://github.com/omerose",
155 | "contributions": [
156 | "doc"
157 | ]
158 | },
159 | {
160 | "login": "aaronmcadam",
161 | "name": "Aaron Mc Adam",
162 | "avatar_url": "https://avatars3.githubusercontent.com/u/37928?v=4",
163 | "profile": "http://www.aaronmcadam.com",
164 | "contributions": [
165 | "code",
166 | "test"
167 | ]
168 | },
169 | {
170 | "login": "karlhorky",
171 | "name": "Karl Horky",
172 | "avatar_url": "https://avatars2.githubusercontent.com/u/1935696?v=4",
173 | "profile": "https://twitter.com/karlhorky",
174 | "contributions": [
175 | "doc"
176 | ]
177 | },
178 | {
179 | "login": "NoriSte",
180 | "name": "Stefano Magni",
181 | "avatar_url": "https://avatars0.githubusercontent.com/u/173663?v=4",
182 | "profile": "https://twitter.com/NoriSte",
183 | "contributions": [
184 | "code",
185 | "test",
186 | "doc"
187 | ]
188 | },
189 | {
190 | "login": "weyert",
191 | "name": "Weyert de Boer",
192 | "avatar_url": "https://avatars3.githubusercontent.com/u/7049?v=4",
193 | "profile": "https://github.com/weyert",
194 | "contributions": [
195 | "code"
196 | ]
197 | },
198 | {
199 | "login": "simjes",
200 | "name": "Simon Jespersen",
201 | "avatar_url": "https://avatars0.githubusercontent.com/u/6494049?v=4",
202 | "profile": "https://simjes.dev/",
203 | "contributions": [
204 | "code",
205 | "review"
206 | ]
207 | },
208 | {
209 | "login": "afontcu",
210 | "name": "Adrià Fontcuberta",
211 | "avatar_url": "https://avatars0.githubusercontent.com/u/9197791?v=4",
212 | "profile": "https://afontcu.dev",
213 | "contributions": [
214 | "infra",
215 | "doc",
216 | "review"
217 | ]
218 | },
219 | {
220 | "login": "Megoos",
221 | "name": "Mikhail Guskov",
222 | "avatar_url": "https://avatars2.githubusercontent.com/u/9866017?v=4",
223 | "profile": "https://github.com/Megoos",
224 | "contributions": [
225 | "bug"
226 | ]
227 | },
228 | {
229 | "login": "juliusdelta",
230 | "name": "JD Gonzales",
231 | "avatar_url": "https://avatars1.githubusercontent.com/u/10285055?v=4",
232 | "profile": "https://jds.work",
233 | "contributions": [
234 | "doc"
235 | ]
236 | },
237 | {
238 | "login": "frinyvonnick",
239 | "name": "Yvonnick FRIN",
240 | "avatar_url": "https://avatars0.githubusercontent.com/u/13099512?v=4",
241 | "profile": "https://yvonnickfrin.dev",
242 | "contributions": [
243 | "doc"
244 | ]
245 | },
246 | {
247 | "login": "kefranabg",
248 | "name": "Franck Abgrall",
249 | "avatar_url": "https://avatars3.githubusercontent.com/u/9840435?v=4",
250 | "profile": "https://www.franck-abgrall.me/",
251 | "contributions": [
252 | "review"
253 | ]
254 | },
255 | {
256 | "login": "tlrobinson",
257 | "name": "Tom Robinson",
258 | "avatar_url": "https://avatars0.githubusercontent.com/u/18193?v=4",
259 | "profile": "http://twitter.com/tlrobinson",
260 | "contributions": [
261 | "code",
262 | "test"
263 | ]
264 | },
265 | {
266 | "login": "NicholasBoll",
267 | "name": "Nicholas Boll",
268 | "avatar_url": "https://avatars2.githubusercontent.com/u/338257?v=4",
269 | "profile": "https://github.com/NicholasBoll",
270 | "contributions": [
271 | "code",
272 | "test"
273 | ]
274 | },
275 | {
276 | "login": "FlopieUtd",
277 | "name": "FlopieUtd",
278 | "avatar_url": "https://avatars3.githubusercontent.com/u/23555863?v=4",
279 | "profile": "https://github.com/FlopieUtd",
280 | "contributions": [
281 | "doc"
282 | ]
283 | },
284 | {
285 | "login": "leosuncin",
286 | "name": "Jaime Leonardo Suncin Cruz",
287 | "avatar_url": "https://avatars1.githubusercontent.com/u/4307697?v=4",
288 | "profile": "https://github.com/leosuncin",
289 | "contributions": [
290 | "bug",
291 | "code",
292 | "test"
293 | ]
294 | },
295 | {
296 | "login": "travi",
297 | "name": "Matt Travi",
298 | "avatar_url": "https://avatars1.githubusercontent.com/u/126441?v=4",
299 | "profile": "https://matt.travi.org",
300 | "contributions": [
301 | "code"
302 | ]
303 | },
304 | {
305 | "login": "MichaelDeBoey",
306 | "name": "Michaël De Boey",
307 | "avatar_url": "https://avatars3.githubusercontent.com/u/6643991?v=4",
308 | "profile": "https://michaeldeboey.be",
309 | "contributions": [
310 | "code"
311 | ]
312 | },
313 | {
314 | "login": "huchenme",
315 | "name": "Hu Chen",
316 | "avatar_url": "https://avatars3.githubusercontent.com/u/2078389?v=4",
317 | "profile": "https://huchen.dev",
318 | "contributions": [
319 | "doc"
320 | ]
321 | },
322 | {
323 | "login": "frederickfogerty",
324 | "name": "Frederick Fogerty",
325 | "avatar_url": "https://avatars0.githubusercontent.com/u/615334?v=4",
326 | "profile": "https://github.com/frederickfogerty",
327 | "contributions": [
328 | "code"
329 | ]
330 | },
331 | {
332 | "login": "kylemh",
333 | "name": "Kyle Holmberg",
334 | "avatar_url": "https://avatars1.githubusercontent.com/u/9523719?v=4",
335 | "profile": "https://kylemh.com",
336 | "contributions": [
337 | "doc"
338 | ]
339 | },
340 | {
341 | "login": "Thisen",
342 | "name": "Mathis Møller",
343 | "avatar_url": "https://avatars2.githubusercontent.com/u/10807938?v=4",
344 | "profile": "https://github.com/Thisen",
345 | "contributions": [
346 | "code",
347 | "test"
348 | ]
349 | },
350 | {
351 | "login": "SimenB",
352 | "name": "Simen Bekkhus",
353 | "avatar_url": "https://avatars1.githubusercontent.com/u/1404810?v=4",
354 | "profile": "https://github.com/SimenB",
355 | "contributions": [
356 | "code"
357 | ]
358 | },
359 | {
360 | "login": "amitmiran137",
361 | "name": "Amit Miran",
362 | "avatar_url": "https://avatars.githubusercontent.com/u/47772523?v=4",
363 | "profile": "https://github.com/amitmiran137",
364 | "contributions": [
365 | "infra"
366 | ]
367 | },
368 | {
369 | "login": "leschdom",
370 | "name": "Dominik Lesch",
371 | "avatar_url": "https://avatars.githubusercontent.com/u/62334278?v=4",
372 | "profile": "https://github.com/leschdom",
373 | "contributions": [
374 | "doc"
375 | ]
376 | },
377 | {
378 | "login": "Andarist",
379 | "name": "Mateusz Burzyński",
380 | "avatar_url": "https://avatars.githubusercontent.com/u/9800850?v=4",
381 | "profile": "https://github.com/Andarist",
382 | "contributions": [
383 | "code"
384 | ]
385 | },
386 | {
387 | "login": "nielsdB97",
388 | "name": "Niels de Bruin",
389 | "avatar_url": "https://avatars.githubusercontent.com/u/11021818?v=4",
390 | "profile": "https://nielsdb97.nl",
391 | "contributions": [
392 | "code"
393 | ]
394 | },
395 | {
396 | "login": "MatanBobi",
397 | "name": "Matan Borenkraout",
398 | "avatar_url": "https://avatars.githubusercontent.com/u/12711091?v=4",
399 | "profile": "https://matan.io",
400 | "contributions": [
401 | "code"
402 | ]
403 | }
404 | ],
405 | "repoType": "github",
406 | "repoHost": "https://github.com",
407 | "contributorsPerLine": 7
408 | }
409 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./node_modules/kcd-scripts/eslint.js",
3 | "rules": {
4 | "max-lines-per-function": "off",
5 | "testing-library/prefer-screen-queries": "off",
6 | "testing-library/no-dom-import": "off", // We're not using React Testing Library here. We're wrapping DOM Testing Library directly
7 | "@typescript-eslint/no-explicit-any": "off" // let's do better in the future
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto eol=lf
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
18 |
19 | - `cypress-testing-library` version:
20 | - `node` version:
21 | - `npm` (or `yarn`) version:
22 |
23 | Relevant code or config
24 |
25 | ```javascript
26 |
27 | ```
28 |
29 | What you did:
30 |
31 | What happened:
32 |
33 |
34 |
35 | Reproduction repository:
36 |
37 |
41 |
42 | Problem description:
43 |
44 | Suggested solution:
45 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 | **What**:
20 |
21 |
22 |
23 | **Why**:
24 |
25 |
26 |
27 | **How**:
28 |
29 |
30 |
31 | **Checklist**:
32 |
33 |
34 |
35 |
36 |
37 | - [ ] Documentation
38 | - [ ] Tests
39 | - [ ] Ready to be merged
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/.github/workflows/validate.yml:
--------------------------------------------------------------------------------
1 | name: validate
2 | on:
3 | push:
4 | branches:
5 | - '+([0-9])?(.{+([0-9]),x}).x'
6 | - 'main'
7 | - 'next'
8 | - 'next-major'
9 | - 'beta'
10 | - 'alpha'
11 | - '!all-contributors/**'
12 | pull_request:
13 |
14 | concurrency:
15 | group: ${{ github.workflow }}-${{ github.ref }}
16 | cancel-in-progress: true
17 |
18 | jobs:
19 | main:
20 | # ignore all-contributors PRs
21 | if: ${{ !contains(github.head_ref, 'all-contributors') }}
22 | strategy:
23 | matrix:
24 | node: [18, 20]
25 | runs-on: ubuntu-latest
26 | steps:
27 | - name: ⬇️ Checkout repo
28 | uses: actions/checkout@v2
29 |
30 | - name: ⎔ Setup node
31 | uses: actions/setup-node@v2
32 | with:
33 | node-version: ${{ matrix.node }}
34 |
35 | - name: 📥 Download deps
36 | uses: bahmutov/npm-install@v1
37 | with:
38 | useLockFile: false
39 |
40 | - name: ▶️ Run validate script
41 | run: npm run validate
42 |
43 | - name: ⬆️ Upload coverage report
44 | uses: codecov/codecov-action@v1
45 |
46 | release:
47 | needs: main
48 | runs-on: ubuntu-latest
49 | if:
50 | ${{ github.repository == 'testing-library/cypress-testing-library' &&
51 | contains('refs/heads/main,refs/heads/beta,refs/heads/next,refs/heads/alpha',
52 | github.ref) && github.event_name == 'push' }}
53 | steps:
54 | - name: ⬇️ Checkout repo
55 | uses: actions/checkout@v2
56 |
57 | - name: ⎔ Setup node
58 | uses: actions/setup-node@v2
59 | with:
60 | node-version: 20
61 |
62 | - name: 📥 Download deps
63 | uses: bahmutov/npm-install@v1
64 | with:
65 | useLockFile: false
66 |
67 | - name: 🏗 Run build script
68 | run: npm run build
69 |
70 | - name: 🚀 Release
71 | uses: cycjimmy/semantic-release-action@v2
72 | with:
73 | semantic_version: 17
74 | branches: |
75 | [
76 | '+([0-9])?(.{+([0-9]),x}).x',
77 | 'main',
78 | 'next',
79 | 'next-major',
80 | {name: 'beta', prerelease: true},
81 | {name: 'alpha', prerelease: true}
82 | ]
83 | env:
84 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
85 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
86 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | coverage
3 | dist
4 | .DS_Store
5 |
6 | # these cause more harm than good
7 | # when working with contributors
8 | package-lock.json
9 | yarn.lock
10 |
11 | # cypress recordings during a test run are temporary files
12 | /cypress/videos/
13 | /cypress/screenshots/
14 |
--------------------------------------------------------------------------------
/.huskyrc.js:
--------------------------------------------------------------------------------
1 | module.exports = require('kcd-scripts/husky')
2 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | registry=https://registry.npmjs.org/
2 | package-lock=false
3 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | coverage
3 | dist
4 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = require('kcd-scripts/prettier')
2 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # CHANGELOG
2 |
3 | The changelog is automatically updated using
4 | [semantic-release](https://github.com/semantic-release/semantic-release). You
5 | can see it on the [releases page](../../releases).
6 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | Thanks for being willing to contribute!
4 |
5 | **Working on your first Pull Request?** You can learn how from this _free_
6 | series [How to Contribute to an Open Source Project on GitHub][egghead]
7 |
8 | ## Project setup
9 |
10 | 1. Fork and clone the repo
11 | 2. Run `npm run setup -s` to install dependencies and run validation
12 | 3. Create a branch for your PR with `git checkout -b pr/your-branch-name`
13 |
14 | > Tip: Keep your `main` branch pointing at the original repository and make
15 | > pull requests from branches on your fork. To do this, run:
16 | >
17 | > ```
18 | > git remote add upstream https://github.com/testing-library/cypress-testing-library.git
19 | > git fetch upstream
20 | > git branch --set-upstream-to=upstream/main main
21 | > ```
22 | >
23 | > This will add the original repository as a "remote" called "upstream," Then
24 | > fetch the git information from that remote, then set your local `main`
25 | > branch to use the upstream main branch whenever you run `git pull`. Then you
26 | > can make all of your pull request branches based on this `main` branch.
27 | > Whenever you want to update your version of `main`, do a regular `git pull`.
28 |
29 | ## Committing and Pushing changes
30 |
31 | Please make sure to run the tests before you commit your changes.
32 |
33 | ### opt into git hooks
34 |
35 | There are git hooks set up with this project that are automatically installed
36 | when you install dependencies. They're really handy, but are turned off by
37 | default (so as to not hinder new contributors). You can opt into these by
38 | creating a file called `.opt-in` at the root of the project and putting this
39 | inside:
40 |
41 | ```
42 | pre-commit
43 | ```
44 |
45 | ## Help needed
46 |
47 | Please checkout the [the open issues][issues]
48 |
49 | Also, please watch the repo and respond to questions/bug reports/feature
50 | requests! Thanks!
51 |
52 | [egghead]:
53 | https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github
54 | [issues]: https://github.com/testing-library/cypress-testing-library/issues
55 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright (c) 2017 Kent C. Dodds
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all
12 | copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
Cypress Testing Library
3 |
4 |
5 |
11 |
12 |
13 |
Simple and complete custom Cypress commands and utilities that encourage good
14 | testing practices.
15 |
16 | [**Read the docs**](https://testing-library.com/cypress) |
17 | [Edit the docs](https://github.com/alexkrolick/testing-library-docs)
18 |
19 |
20 |
21 | ---
22 |
23 |
24 | [![Build Status][build-badge]][build]
25 | [![Code Coverage][coverage-badge]][coverage]
26 | [![version][version-badge]][package]
27 | [![downloads][downloads-badge]][npmtrends]
28 | [![MIT License][license-badge]][license]
29 | [![All Contributors][all-contributors-badge]](#contributors-)
30 | [![PRs Welcome][prs-badge]][prs]
31 | [![Code of Conduct][coc-badge]][coc]
32 |
33 |
34 |
43 |
44 | ## The problem
45 |
46 | You want to use [`DOM Testing Library`][dom-testing-library] methods in your
47 | [Cypress][cypress] tests.
48 |
49 | ## This solution
50 |
51 | This allows you to use all the useful
52 | [`DOM Testing Library`][dom-testing-library] methods in your tests.
53 |
54 | ## Table of Contents
55 |
56 |
57 |
58 |
59 | - [Installation](#installation)
60 | - [With TypeScript](#with-typescript)
61 | - [Intellisense for JavaScript with VS Code](#intellisense-for-javascript-with-vs-code)
62 | - [Usage](#usage)
63 | - [Differences from DOM Testing Library](#differences-from-dom-testing-library)
64 | - [Config testIdAttribute](#config-testidattribute)
65 | - [Other Solutions](#other-solutions)
66 | - [Issues](#issues)
67 | - [🐛 Bugs](#-bugs)
68 | - [💡 Feature Requests](#-feature-requests)
69 | - [Contributors ✨](#contributors-)
70 | - [LICENSE](#license)
71 |
72 |
73 |
74 | ## Installation
75 |
76 | This module is distributed via [npm][npm] which is bundled with [node][node] and
77 | should be installed as one of your project's `devDependencies`:
78 |
79 | ```
80 | npm install --save-dev @testing-library/cypress
81 | ```
82 |
83 | ### With TypeScript
84 |
85 | Typings should be added as follows in `tsconfig.json`:
86 |
87 | ```json
88 | {
89 | "compilerOptions": {
90 | "types": ["cypress", "@testing-library/cypress"]
91 | }
92 | }
93 | ```
94 |
95 | ### Intellisense for JavaScript with VS Code
96 |
97 | If you're not using TypeScript, you use VS Code, and want to have
98 | code-completion with the methods from this library, simply add the following
99 | line to your project's root-level `jsconfig.json` file:
100 |
101 | ```json
102 | {
103 | "include": ["node_modules/cypress", "./cypress/**/*.js"]
104 | }
105 | ```
106 |
107 | ## Usage
108 |
109 | `Cypress Testing Library` extends Cypress' `cy` command.
110 |
111 | Add this line to your project's `cypress/support/commands.js`:
112 |
113 | ```javascript
114 | import '@testing-library/cypress/add-commands'
115 | ```
116 |
117 | You can now use all of `DOM Testing Library`'s `findBy` and `findAllBy`
118 | commands.
119 | [See the `DOM Testing Library` docs for reference](https://testing-library.com)
120 |
121 | You can find
122 | [all Library definitions here](https://github.com/testing-library/cypress-testing-library/tree/main/types/index.d.ts).
123 |
124 | To configure DOM Testing Library, use the following custom command:
125 |
126 | ```javascript
127 | cy.configureCypressTestingLibrary(config)
128 | ```
129 |
130 | To show some simple examples (from
131 | [cypress/e2e/find.cy.js](cypress/e2e/find.cy.js)):
132 |
133 | ```javascript
134 | cy.findAllByText('Button Text').should('exist')
135 | cy.findAllByText('Non-existing Button Text').should('not.exist')
136 | cy.findAllByLabelText('Label text', {timeout: 7000}).should('exist')
137 | cy.findAllByText('Jackie Chan').click()
138 |
139 | // findAllByText _inside_ a form element
140 | cy.get('form').findAllByText('Button Text').should('exist')
141 | ```
142 |
143 | ### Differences from DOM Testing Library
144 |
145 | `Cypress Testing Library` supports both jQuery elements and DOM nodes. This is
146 | necessary because Cypress uses jQuery elements, while `DOM Testing Library`
147 | expects DOM nodes. When you chain a query, it will get the first DOM node from
148 | `subject` of the collection and use that as the `container` parameter for the
149 | `DOM Testing Library` functions.
150 |
151 | `query*` queries are not supported. You should use the `should('not.exist')`
152 | assertion instead to check for the absence of an element.
153 |
154 | `get*` queries are not supported. `find*` queries do not use the Promise API of
155 | `DOM Testing Library`, but instead forward to the `get*` queries and use
156 | Cypress' built-in retryability using error messages from `get*` APIs to forward
157 | as error messages if a query fails.
158 |
159 | `findAll*` can select more than one element and is closer in functionality to
160 | how Cypress built-in commands work. `find*` commands will fail if more than one
161 | element is found that matches the criteria which is not how built-in Cypress
162 | commands work, but is provided for closer compatibility to other Testing
163 | Libraries.
164 |
165 | Cypress handles actions when there is only one element found. For example, the
166 | following will work without having to limit to only 1 returned element. The
167 | `cy.click` will automatically fail if more than 1 element is returned by the
168 | `findAllByText`:
169 |
170 | ```javascript
171 | cy.findAllByText('Some Text').click()
172 | ```
173 |
174 | If you intend to enforce only 1 element is returned by a selector, the following
175 | examples will both fail if more than one element is found.
176 |
177 | ```javascript
178 | cy.findAllByText('Some Text').should('have.length', 1)
179 | cy.findByText('Some Text').should('exist')
180 | ```
181 |
182 | ## Config testIdAttribute
183 |
184 | If you would like to change the default testId from `data-testId` to
185 | `data-test-id`, add to your project's `cypress/support/index.js`:
186 |
187 | ```javascript
188 | import {configure} from '@testing-library/cypress'
189 | configure({testIdAttribute: 'data-test-id'})
190 | ```
191 |
192 | It accepts all configurations listed in
193 | [DOM testing library](https://testing-library.com/docs/dom-testing-library/api-configuration).
194 |
195 | ## Other Solutions
196 |
197 | I'm not aware of any, if you are please [make a pull request][prs] and add it
198 | here!
199 |
200 | ## Issues
201 |
202 | _Looking to contribute? Look for the [Good First Issue][good-first-issue]
203 | label._
204 |
205 | ### 🐛 Bugs
206 |
207 | Please file an issue for bugs, missing documentation, or unexpected behavior.
208 |
209 | [**See Bugs**][bugs]
210 |
211 | ### 💡 Feature Requests
212 |
213 | Please file an issue to suggest new features. Vote on feature requests by adding
214 | a 👍. This helps maintainers prioritize what to work on.
215 |
216 | [**See Feature Requests**][requests]
217 |
218 | ## Contributors ✨
219 |
220 | Thanks goes to these people ([emoji key][emojis]):
221 |
222 |
223 |
224 |
225 |
280 |
281 |
282 |
283 |
284 |
285 |
286 | This project follows the [all-contributors][all-contributors] specification.
287 | Contributions of any kind welcome!
288 |
289 | ## LICENSE
290 |
291 | MIT
292 |
293 |
294 | [npm]: https://npmjs.com
295 | [node]: https://nodejs.org
296 | [build-badge]: https://img.shields.io/github/workflow/status/testing-library/cypress-testing-library/validate?logo=github&style=flat-square
297 | [build]: https://github.com/testing-library/cypress-testing-library/actions?query=workflow%3Avalidate
298 | [coverage-badge]: https://img.shields.io/codecov/c/github/testing-library/cypress-testing-library.svg?style=flat-square
299 | [coverage]: https://codecov.io/github/testing-library/cypress-testing-library
300 | [version-badge]: https://img.shields.io/npm/v/@testing-library/cypress.svg?style=flat-square
301 | [package]: https://www.npmjs.com/package/@testing-library/cypress
302 | [downloads-badge]: https://img.shields.io/npm/dm/@testing-library/cypress.svg?style=flat-square
303 | [npmtrends]: http://www.npmtrends.com/@testing-library/cypress
304 | [license-badge]: https://img.shields.io/npm/l/@testing-library/cypress.svg?style=flat-square
305 | [license]: https://github.com/testing-library/cypress-testing-library/blob/main/LICENSE
306 | [prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
307 | [prs]: http://makeapullrequest.com
308 | [coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square
309 | [coc]: https://github.com/testing-library/cypress-testing-library/blob/main/other/CODE_OF_CONDUCT.md
310 | [emojis]: https://allcontributors.org/docs/en/emoji-key
311 | [all-contributors]: https://github.com/all-contributors/all-contributors
312 | [all-contributors-badge]: https://img.shields.io/github/all-contributors/testing-library/cypress-testing-library?color=orange&style=flat-square
313 | [bugs]: https://github.com/testing-library/cypress-testing-library/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3A%22%F0%9F%90%9B+Bug%22+sort%3Acreated-desc
314 | [requests]: https://github.com/testing-library/cypress-testing-library/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3Aenhancement
315 | [good-first-issue]: https://github.com/testing-library/cypress-testing-library/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3A%22good+first+issue%22
316 |
317 | [cypress]: https://cypress.io
318 | [dom-testing-library]: https://github.com/testing-library/dom-testing-library
319 |
320 |
--------------------------------------------------------------------------------
/add-commands.js:
--------------------------------------------------------------------------------
1 | // this file is here so it's easy to register the commands
2 | // `import '@testing-library/cypress/add-commands'`
3 | // eslint-disable-next-line
4 | require('./dist/add-commands')
5 |
--------------------------------------------------------------------------------
/cypress.config.js:
--------------------------------------------------------------------------------
1 | const {defineConfig} = require('cypress')
2 |
3 | module.exports = defineConfig({
4 | e2e: {},
5 | video: false,
6 | })
7 |
--------------------------------------------------------------------------------
/cypress/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "testing-library/await-async-query": "off", // Cypress chains don't use promises
4 | "testing-library/prefer-screen-queries": "off", // screen queries don't make sense in the context of Cypress Testing Library
5 | "testing-library/prefer-explicit-assert": "off", // we're lazy
6 |
7 | // No Jest here
8 | "jest/valid-expect": "off",
9 | "jest/valid-expect-in-promise": "off",
10 | "jest/no-conditional-expect": "off"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/cypress/e2e/find.cy.js:
--------------------------------------------------------------------------------
1 | ///
2 | describe('find* dom-testing-library commands', () => {
3 | beforeEach(() => {
4 | cy.visit('cypress/fixtures/test-app/')
5 | })
6 |
7 | // Test each of the types of queries: LabelText, PlaceholderText, Text, DisplayValue, AltText, Title, Role, TestId
8 |
9 | it('findByLabelText', () => {
10 | cy.findByLabelText('Label 1').click().type('Hello Input Labelled By Id')
11 | })
12 |
13 | it('findAllByLabelText', () => {
14 | cy.findAllByLabelText(/^Label \d$/).should('have.length', 2)
15 | })
16 |
17 | it('findByPlaceholderText', () => {
18 | cy.findByPlaceholderText('Input 1').click().type('Hello Placeholder')
19 | })
20 |
21 | it('findAllByPlaceholderText', () => {
22 | cy.findAllByPlaceholderText(/^Input \d$/).should('have.length', 2)
23 | })
24 |
25 | it('findByText', () => {
26 | cy.findByText('Button Text 1').click().should('contain', 'Button Clicked')
27 | })
28 |
29 | it('findAllByText', () => {
30 | cy.findAllByText(/^Button Text \d$/)
31 | .should('have.length', 2)
32 | .click({multiple: true})
33 | .should('contain', 'Button Clicked')
34 | })
35 |
36 | it('findByDisplayValue', () => {
37 | cy.findByDisplayValue('Display Value 1')
38 | .click()
39 | .clear()
40 | .type('Some new text')
41 | })
42 |
43 | it('findAllByDisplayValue', () => {
44 | cy.findAllByDisplayValue(/^Display Value \d$/).should('have.length', 2)
45 | })
46 |
47 | it('findByAltText', () => {
48 | cy.findByAltText('Image Alt Text 1').click()
49 | })
50 |
51 | it('findAllByAltText', () => {
52 | cy.findAllByAltText(/^Image Alt Text \d$/).should('have.length', 2)
53 | })
54 |
55 | it('findByTitle', () => {
56 | cy.findByTitle('Title 1').click()
57 | })
58 |
59 | it('findAllByTitle', () => {
60 | cy.findAllByTitle(/^Title \d$/).should('have.length', 2)
61 | })
62 |
63 | it('findByRole', () => {
64 | cy.findByRole('dialog').click()
65 | })
66 |
67 | it('findAllByRole', () => {
68 | cy.findAllByRole('dialog').should('have.length', 1)
69 | })
70 |
71 | it('findByTestId', () => {
72 | cy.findByTestId('image-with-random-alt-tag-1').click()
73 | })
74 |
75 | it('findAllByTestId', () => {
76 | cy.findAllByTestId(/^image-with-random-alt-tag-\d$/).should(
77 | 'have.length',
78 | 2,
79 | )
80 | })
81 |
82 | /* Test the behaviour around these queries */
83 |
84 | it('findByText should handle non-existence', () => {
85 | cy.findByText('Does Not Exist').should('not.exist')
86 | })
87 |
88 | it('findByText should handle eventual existence', () => {
89 | cy.findByText('Eventually Exists').should('exist')
90 | })
91 |
92 | it('findByText should handle eventual non-existence', () => {
93 | cy.findByText('Eventually Not exists').should('not.exist')
94 | })
95 |
96 | it("findByText with should('not.exist')", () => {
97 | cy.findAllByText(/^Button Text \d$/).should('exist')
98 | cy.findByText('Non-existing Button Text', {timeout: 100}).should(
99 | 'not.exist',
100 | )
101 | })
102 |
103 | it('findByText with a previous subject', () => {
104 | cy.get('#nested').findByText('Button Text 1').should('not.exist')
105 | cy.get('#nested').findByText('Button Text 2').should('exist')
106 | })
107 |
108 | it('findByText within', () => {
109 | cy.get('#nested').within(() => {
110 | cy.findByText('Button Text 1').should('not.exist')
111 | cy.findByText('Button Text 2').should('exist')
112 | })
113 | })
114 |
115 | it('findByText in container', () => {
116 | cy.get('#nested').then(subject => {
117 | cy.findByText('Button Text 1', {container: subject}).should('not.exist')
118 | cy.findByText('Button Text 2', {container: subject}).should('exist')
119 | })
120 | })
121 |
122 | it('findByText inside within and with a previous subject', () => {
123 | cy.get('section:nth-of-type(2)').within(() => {
124 | cy.findByText(/Button Text 1/).should('exist')
125 | })
126 | cy.get('#nested')
127 | .findByText(/Button Text/)
128 | .should('exist')
129 | cy.get('section:nth-of-type(2)').within(() => {
130 | cy.get('#nested')
131 | .findByText(/Button Text/)
132 | .should('exist')
133 | })
134 | })
135 |
136 | it('findByText works when another page loads', () => {
137 | cy.findByText('Next Page').click()
138 | cy.findByText('New Page Loaded').should('exist')
139 | })
140 |
141 | it('findByText should set the Cypress element to the found element', () => {
142 | // This test is a little strange since snapshots show what element
143 | // is selected, but snapshots themselves don't give access to those
144 | // elements. I had to make the implementation specific so that the `$el`
145 | // is the `subject` when the log is added and the `$el` is the `value`
146 | // when the log is changed. It would be better to extract the `$el` from
147 | // each snapshot
148 |
149 | cy.on('log:changed', (attrs, log) => {
150 | if (log.get('name') === 'findByText') {
151 | expect(log.get('$el')).to.have.text('Button Text 1')
152 | }
153 | })
154 |
155 | cy.findByText('Button Text 1')
156 | })
157 |
158 | it('findByText should error if no elements are found', () => {
159 | const regex = /Supercalifragilistic/
160 | const errorMessage = `Unable to find an element with the text: /Supercalifragilistic/`
161 | cy.on('fail', err => {
162 | expect(err.message).to.contain(errorMessage)
163 | })
164 |
165 | cy.findByText(regex, {timeout: 100})
166 | })
167 |
168 | it('findByText should default to Cypress non-existence error message', () => {
169 | const errorMessage = `Expected not to exist in the DOM, but it was continuously found.`
170 | cy.on('fail', err => {
171 | expect(err.message).to.contain(errorMessage)
172 | })
173 |
174 | cy.findByText('Button Text 1', {timeout: 100}).should('not.exist')
175 | })
176 |
177 | it('findByLabelText should forward useful error messages from @testing-library/dom', () => {
178 | const errorMessage = `Found a label with the text of: Label 3, however no form control was found associated to that label.`
179 | cy.on('fail', err => {
180 | expect(err.message).to.contain(errorMessage)
181 | })
182 |
183 | cy.findByLabelText('Label 3', {timeout: 100})
184 | })
185 |
186 | it('findByText finding multiple items should error', () => {
187 | const errorMessage = `Found multiple elements with the text: /^Button Text/i`
188 | cy.on('fail', err => {
189 | expect(err.message).to.contain(errorMessage)
190 | })
191 |
192 | cy.findByText(/^Button Text/i, {timeout: 100})
193 | })
194 |
195 | it('findByText should show as a parent command if it starts a chain', () => {
196 | const assertLog = (attrs, log) => {
197 | if (log.get('name') === 'findByText') {
198 | expect(log.get('type')).to.equal('parent')
199 | cy.off('log:added', assertLog)
200 | }
201 | }
202 | cy.on('log:added', assertLog)
203 | cy.findByText('Button Text 1')
204 | })
205 |
206 | it('findByText should show as a child command if it continues a chain', () => {
207 | const assertLog = (attrs, log) => {
208 | if (log.get('name') === 'findByText') {
209 | expect(log.get('type')).to.equal('child')
210 | cy.off('log:added', assertLog)
211 | }
212 | }
213 | cy.on('log:added', assertLog)
214 | cy.get('body').findByText('Button Text 1')
215 | })
216 | })
217 |
218 | /* global cy */
219 |
--------------------------------------------------------------------------------
/cypress/fixtures/test-app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | cypress-testing-library
8 |
26 |
27 |
28 |
29 | No auto-reload after changing this static HTML markup:
30 | click ↻ Run All Tests.
31 |
32 |
43 |
44 | *ByText
45 | Button Text 1
46 |
47 |
ByText within
48 | Button Text 2
49 |
50 |
51 |
57 |
58 | *ByAltText
59 |
64 |
69 |
70 |
71 | *ByTitle
72 | 1
73 | 2
74 |
75 |
76 | *ByRole
77 | dialog 1
78 | dialog 2
79 |
80 |
81 | *ByTestId
82 |
87 |
92 |
93 |
94 | *AllByText
95 | Jackie Chan 1
96 | Jackie Chan 2
97 |
98 |
99 | *ByText on another page
100 | Next Page
101 |
102 |
103 | Eventual existence
104 |
105 |
110 |
111 |
112 | Eventual non-existence
113 | Eventually not exists
114 |
119 |
120 |
121 | Chain selectors
122 |
126 |
127 |
128 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/cypress/fixtures/test-app/next-page.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | cypress-testing-library
8 |
19 |
20 |
21 |
22 | No auto-reload after changing this static HTML markup:
23 | click ↻ Run All Tests.
24 |
25 |
26 | New Page Loaded
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/cypress/support/e2e.js:
--------------------------------------------------------------------------------
1 | import '../../src/add-commands'
2 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | const jestConfig = require('kcd-scripts/jest')
2 |
3 | module.exports = Object.assign(jestConfig, {
4 | testEnvironment: 'jest-environment-jsdom',
5 | testURL: 'http://localhost/',
6 | })
7 |
--------------------------------------------------------------------------------
/lint-staged.config.js:
--------------------------------------------------------------------------------
1 | const config = require('kcd-scripts/dist/config/lintstagedrc')
2 |
3 | // we need to exclude the test and lint scripts on commit because we run it in the validate script
4 | const jsLinter = Object.keys(config).find(key => key.includes('js'))
5 | config[jsLinter] = config[jsLinter].filter(
6 | script => !script.includes('test') && !script.includes('lint'),
7 | )
8 |
9 | module.exports = config
10 |
--------------------------------------------------------------------------------
/other/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, religion, or sexual identity and
10 | orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | - Demonstrating empathy and kindness toward other people
21 | - Being respectful of differing opinions, viewpoints, and experiences
22 | - Giving and gracefully accepting constructive feedback
23 | - Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | - Focusing on what is best not just for us as individuals, but for the overall
26 | community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | - The use of sexualized language or imagery, and sexual attention or advances of
31 | any kind
32 | - Trolling, insulting or derogatory comments, and personal or political attacks
33 | - Public or private harassment
34 | - Publishing others' private information, such as a physical or email address,
35 | without their explicit permission
36 | - Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at
63 | me+coc@kentcdodds.com. All complaints will be reviewed and investigated promptly
64 | and fairly.
65 |
66 | All community leaders are obligated to respect the privacy and security of the
67 | reporter of any incident.
68 |
69 | ## Enforcement Guidelines
70 |
71 | Community leaders will follow these Community Impact Guidelines in determining
72 | the consequences for any action they deem in violation of this Code of Conduct:
73 |
74 | ### 1. Correction
75 |
76 | **Community Impact**: Use of inappropriate language or other behavior deemed
77 | unprofessional or unwelcome in the community.
78 |
79 | **Consequence**: A private, written warning from community leaders, providing
80 | clarity around the nature of the violation and an explanation of why the
81 | behavior was inappropriate. A public apology may be requested.
82 |
83 | ### 2. Warning
84 |
85 | **Community Impact**: A violation through a single incident or series of
86 | actions.
87 |
88 | **Consequence**: A warning with consequences for continued behavior. No
89 | interaction with the people involved, including unsolicited interaction with
90 | those enforcing the Code of Conduct, for a specified period of time. This
91 | includes avoiding interactions in community spaces as well as external channels
92 | like social media. Violating these terms may lead to a temporary or permanent
93 | ban.
94 |
95 | ### 3. Temporary Ban
96 |
97 | **Community Impact**: A serious violation of community standards, including
98 | sustained inappropriate behavior.
99 |
100 | **Consequence**: A temporary ban from any sort of interaction or public
101 | communication with the community for a specified period of time. No public or
102 | private interaction with the people involved, including unsolicited interaction
103 | with those enforcing the Code of Conduct, is allowed during this period.
104 | Violating these terms may lead to a permanent ban.
105 |
106 | ### 4. Permanent Ban
107 |
108 | **Community Impact**: Demonstrating a pattern of violation of community
109 | standards, including sustained inappropriate behavior, harassment of an
110 | individual, or aggression toward or disparagement of classes of individuals.
111 |
112 | **Consequence**: A permanent ban from any sort of public interaction within the
113 | community.
114 |
115 | ## Attribution
116 |
117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118 | version 2.0, available at
119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
120 |
121 | Community Impact Guidelines were inspired by
122 | [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
123 |
124 | [homepage]: https://www.contributor-covenant.org
125 |
126 | For answers to common questions about this code of conduct, see the FAQ at
127 | https://www.contributor-covenant.org/faq. Translations are available at
128 | https://www.contributor-covenant.org/translations.
129 |
--------------------------------------------------------------------------------
/other/MAINTAINING.md:
--------------------------------------------------------------------------------
1 | # Maintaining
2 |
3 |
4 |
5 |
6 | **Table of Contents**
7 |
8 | - [Code of Conduct](#code-of-conduct)
9 | - [Issues](#issues)
10 | - [Pull Requests](#pull-requests)
11 | - [Release](#release)
12 | - [Thanks!](#thanks)
13 |
14 |
15 |
16 | This is documentation for maintainers of this project.
17 |
18 | ## Code of Conduct
19 |
20 | Please review, understand, and be an example of it. Violations of the code of
21 | conduct are taken seriously, even (especially) for maintainers.
22 |
23 | ## Issues
24 |
25 | We want to support and build the community. We do that best by helping people
26 | learn to solve their own problems. We have an issue template and hopefully most
27 | folks follow it. If it's not clear what the issue is, invite them to create a
28 | minimal reproduction of what they're trying to accomplish or the bug they think
29 | they've found.
30 |
31 | Once it's determined that a code change is necessary, point people to
32 | [makeapullrequest.com](http://makeapullrequest.com) and invite them to make a
33 | pull request. If they're the one who needs the feature, they're the one who can
34 | build it. If they need some hand holding and you have time to lend a hand,
35 | please do so. It's an investment into another human being, and an investment
36 | into a potential maintainer.
37 |
38 | Remember that this is open source, so the code is not yours, it's ours. If
39 | someone needs a change in the codebase, you don't have to make it happen
40 | yourself. Commit as much time to the project as you want/need to. Nobody can ask
41 | any more of you than that.
42 |
43 | ## Pull Requests
44 |
45 | As a maintainer, you're fine to make your branches on the main repo or on your
46 | own fork. Either way is fine.
47 |
48 | When we receive a pull request, a GitHub Action is kicked off automatically (see
49 | the `.github/workflows/validate.yml` for what runs in the Action). We avoid
50 | merging anything that breaks the GitHub Action.
51 |
52 | Please review PRs and focus on the code rather than the individual. You never
53 | know when this is someone's first ever PR and we want their experience to be as
54 | positive as possible, so be uplifting and constructive.
55 |
56 | When you merge the pull request, 99% of the time you should use the
57 | [Squash and merge](https://help.github.com/articles/merging-a-pull-request)
58 | feature. This keeps our git history clean, but more importantly, this allows us
59 | to make any necessary changes to the commit message so we release what we want
60 | to release. See the next section on Releases for more about that.
61 |
62 | ## Release
63 |
64 | Our releases are automatic. They happen whenever code lands into `main`. A
65 | GitHub Action gets kicked off and if it's successful, a tool called
66 | [`semantic-release`](https://github.com/semantic-release/semantic-release) is
67 | used to automatically publish a new release to npm as well as a changelog to
68 | GitHub. It is only able to determine the version and whether a release is
69 | necessary by the git commit messages. With this in mind, **please brush up on
70 | [the commit message convention][commit] which drives our releases.**
71 |
72 | > One important note about this: Please make sure that commit messages do NOT
73 | > contain the words "BREAKING CHANGE" in them unless we want to push a major
74 | > version. I've been burned by this more than once where someone will include
75 | > "BREAKING CHANGE: None" and it will end up releasing a new major version. Not
76 | > a huge deal honestly, but kind of annoying...
77 |
78 | ## Thanks!
79 |
80 | Thank you so much for helping to maintain this project!
81 |
82 |
83 | [commit]: https://github.com/conventional-changelog-archived-repos/conventional-changelog-angular/blob/ed32559941719a130bb0327f886d6a32a8cbc2ba/convention.md
84 |
85 |
--------------------------------------------------------------------------------
/other/USERS.md:
--------------------------------------------------------------------------------
1 | # Users
2 |
3 | If you or your company uses this project, add your name to this list! Eventually
4 | we may have a website to showcase these (wanna build it!?)
5 |
6 | > No users have been added yet!
7 |
8 |
13 |
--------------------------------------------------------------------------------
/other/manual-releases.md:
--------------------------------------------------------------------------------
1 | # manual-releases
2 |
3 | This project has an automated release set up. So things are only released when
4 | there are useful changes in the code that justify a release. But sometimes
5 | things get messed up one way or another and we need to trigger the release
6 | ourselves. When this happens, simply bump the number below and commit that with
7 | the following commit message based on your needs:
8 |
9 | **Major**
10 |
11 | ```
12 | fix(release): manually release a major version
13 |
14 | There was an issue with a major release, so this manual-releases.md
15 | change is to release a new major version.
16 |
17 | Reference: #
18 |
19 | BREAKING CHANGE:
20 | ```
21 |
22 | **Minor**
23 |
24 | ```
25 | feat(release): manually release a minor version
26 |
27 | There was an issue with a minor release, so this manual-releases.md
28 | change is to release a new minor version.
29 |
30 | Reference: #
31 | ```
32 |
33 | **Patch**
34 |
35 | ```
36 | fix(release): manually release a patch version
37 |
38 | There was an issue with a patch release, so this manual-releases.md
39 | change is to release a new patch version.
40 |
41 | Reference: #
42 | ```
43 |
44 | The number of times we've had to do a manual release is: 3
45 |
--------------------------------------------------------------------------------
/other/testingjavascript.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/testing-library/cypress-testing-library/d77c9df17863dc0ca1d14fb7ccd1f568c6b65580/other/testingjavascript.jpg
--------------------------------------------------------------------------------
/other/tiger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/testing-library/cypress-testing-library/d77c9df17863dc0ca1d14fb7ccd1f568c6b65580/other/tiger.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@testing-library/cypress",
3 | "version": "0.0.0-semantically-released",
4 | "description": "Simple and complete custom Cypress commands and utilities that encourage good testing practices.",
5 | "main": "dist/index.js",
6 | "types": "types/index.d.ts",
7 | "engines": {
8 | "node": ">=12",
9 | "npm": ">=6"
10 | },
11 | "scripts": {
12 | "build": "kcd-scripts build",
13 | "lint": "kcd-scripts lint",
14 | "setup": "npm install && npm run validate -s",
15 | "test": "npm-run-all --parallel test:unit test:cypress",
16 | "test:cypress": "npm run test:cypress:run",
17 | "test:cypress:dev": "npm run test:cypress:open",
18 | "test:cypress:open": "cypress open",
19 | "test:cypress:run": "cypress run",
20 | "test:unit": "kcd-scripts test --no-watch",
21 | "test:unit:watch": "kcd-scripts test",
22 | "typecheck": "kcd-scripts typecheck --build types",
23 | "validate": "kcd-scripts validate build,lint,test,typecheck"
24 | },
25 | "files": [
26 | "dist",
27 | "add-commands.js",
28 | "types/*.d.ts"
29 | ],
30 | "keywords": [
31 | "testing",
32 | "cypress",
33 | "ui",
34 | "dom",
35 | "integration",
36 | "functional",
37 | "end-to-end",
38 | "e2e"
39 | ],
40 | "author": "Kent C. Dodds (https://kentcdodds.com)",
41 | "license": "MIT",
42 | "dependencies": {
43 | "@babel/runtime": "^7.14.6",
44 | "@testing-library/dom": "^10.1.0"
45 | },
46 | "devDependencies": {
47 | "cypress": "^14.0.0",
48 | "kcd-scripts": "^11.2.0",
49 | "npm-run-all": "^4.1.5",
50 | "typescript": "^4.3.5"
51 | },
52 | "peerDependencies": {
53 | "cypress": "^12.0.0 || ^13.0.0 || ^14.0.0"
54 | },
55 | "eslintConfig": {
56 | "extends": "./node_modules/kcd-scripts/eslint.js",
57 | "rules": {
58 | "import/prefer-default-export": "off",
59 | "import/no-unassigned-import": "off",
60 | "jest/valid-expect": "off"
61 | }
62 | },
63 | "eslintIgnore": [
64 | "node_modules",
65 | "coverage",
66 | "dist"
67 | ],
68 | "repository": {
69 | "type": "git",
70 | "url": "https://github.com/testing-library/cypress-testing-library"
71 | },
72 | "bugs": {
73 | "url": "https://github.com/testing-library/cypress-testing-library/issues"
74 | },
75 | "homepage": "https://github.com/testing-library/cypress-testing-library#readme"
76 | }
77 |
--------------------------------------------------------------------------------
/src/__tests__/add-commands.js:
--------------------------------------------------------------------------------
1 | import {commands} from '../'
2 |
3 | test('adds commands to Cypress', () => {
4 | const addMock = jest.fn().mockName('Cypress.Commands.add')
5 | const addQueryMock = jest.fn().mockName('Cypress.Commands.addQuery')
6 | global.Cypress = {Commands: {add: addMock, addQuery: addQueryMock}}
7 | global.cy = {}
8 |
9 | require('../add-commands')
10 |
11 | expect(addQueryMock).toHaveBeenCalledTimes(commands.length)
12 | expect(addMock).toHaveBeenCalledTimes(1) // we're also adding a configuration command
13 | commands.forEach(({name}, index) => {
14 | expect(addQueryMock.mock.calls[index]).toMatchObject([
15 | name,
16 | // We get a new function that is `command.bind(null, cy)` i.e. global `cy` passed into the first argument.
17 | // The commands themselves will be tested separately in the Cypress end-to-end tests.
18 | expect.any(Function),
19 | ])
20 | })
21 | })
22 |
--------------------------------------------------------------------------------
/src/__tests__/commands.js:
--------------------------------------------------------------------------------
1 | import {queries} from '@testing-library/dom'
2 | import {commands} from '../'
3 |
4 | const queryNames = Object.keys(queries).filter(q => /^find/.test(q))
5 |
6 | test('exports expected commands', () => {
7 | expect(commands).toMatchObject(expect.any(Array))
8 | const sortedQueryNames = queryNames.sort()
9 | const sortedCommandNames = commands.map(({name}) => name).sort()
10 | expect(sortedCommandNames).toEqual(sortedQueryNames)
11 | commands.forEach(command =>
12 | expect(command).toMatchObject({
13 | name: expect.any(String),
14 | // We get a new function that wraps the respective query from `dom-testing-library`.
15 | // The commands themselves will be tested separately in the Cypress end-to-end tests.
16 | command: expect.any(Function),
17 | }),
18 | )
19 | })
20 |
--------------------------------------------------------------------------------
/src/add-commands.js:
--------------------------------------------------------------------------------
1 | import {configure, commands} from './'
2 |
3 | commands.forEach(({name, command}) => {
4 | Cypress.Commands.addQuery(name, command)
5 | })
6 |
7 | Cypress.Commands.add('configureCypressTestingLibrary', config => {
8 | configure(config)
9 | })
10 |
11 | /* global Cypress */
12 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import {configure as configureDTL, queries} from '@testing-library/dom'
2 | import {getFirstElement} from './utils'
3 |
4 | function configure({fallbackRetryWithoutPreviousSubject, ...config}) {
5 | return configureDTL(config)
6 | }
7 |
8 | const findRegex = /^find/
9 | const queryNames = Object.keys(queries).filter(q => findRegex.test(q))
10 |
11 | const commands = queryNames.map(queryName => {
12 | return createQuery(queryName, queryName.replace(findRegex, 'get'))
13 | })
14 |
15 | function createQuery(queryName, implementationName) {
16 | return {
17 | name: queryName,
18 | command(...args) {
19 | const lastArg = args[args.length - 1]
20 | const options = typeof lastArg === 'object' ? {...lastArg} : {}
21 |
22 | this.set('timeout', options.timeout)
23 |
24 | const queryImpl = queries[implementationName]
25 | const inputArr = args.filter(filterInputs)
26 |
27 | const selector = `${queryName}(${queryArgument(args)})`
28 |
29 | const consoleProps = {
30 | // TODO: Would be good to completely separate out the types of input into their own properties
31 | input: inputArr,
32 | Selector: selector,
33 | }
34 |
35 | const log =
36 | options.log !== false &&
37 | Cypress.log({
38 | name: queryName,
39 | type:
40 | this.get('prev')?.get('chainerId') === this.get('chainerId')
41 | ? 'child'
42 | : 'parent',
43 | message: inputArr,
44 | timeout: options.timeout,
45 | consoleProps: () => consoleProps,
46 | })
47 |
48 | const withinSubject = cy.state('withinSubjectChain')
49 |
50 | let error
51 | this.set('onFail', err => {
52 | if (error) {
53 | err.message = error.message
54 | }
55 | })
56 |
57 | return subject => {
58 | const container = getFirstElement(
59 | options.container ||
60 | subject ||
61 | cy.getSubjectFromChain(withinSubject) ||
62 | cy.state('window').document,
63 | )
64 | consoleProps['Applied To'] = container
65 |
66 | let value
67 |
68 | try {
69 | value = queryImpl(container, ...args)
70 | } catch (e) {
71 | error = e
72 | value = Cypress.$()
73 | value.selector = selector
74 | }
75 |
76 | const result = Cypress.$(value)
77 |
78 | if (value && log) {
79 | log.set('$el', result)
80 | }
81 |
82 | // Overriding the selector of the jquery object because it's displayed in the long message of .should('exist') failure message
83 | // Hopefully it makes it clearer, because I find the normal response of "Expected to find element '', but never found it" confusing
84 | result.selector = selector
85 |
86 | consoleProps.elements = result.length
87 | if (result.length === 1) {
88 | consoleProps.yielded = result.toArray()[0]
89 | } else if (result.length > 0) {
90 | consoleProps.yielded = result.toArray()
91 | }
92 |
93 | if (result.length > 1 && !/All/.test(queryName)) {
94 | // Is this useful?
95 | throw Error(
96 | `Found multiple elements with the text: ${queryArgument(args)}`,
97 | )
98 | }
99 |
100 | return result
101 | }
102 | },
103 | }
104 | }
105 |
106 | function filterInputs(value) {
107 | if (Array.isArray(value) && value.length === 0) {
108 | return false
109 | }
110 | if (value instanceof RegExp) {
111 | return value.toString()
112 | }
113 | if (typeof value === 'object' && Object.keys(value).length === 0) {
114 | return false
115 | }
116 | return Boolean(value)
117 | }
118 |
119 | function queryArgument(args) {
120 | const input = args.find(value => {
121 | return value instanceof RegExp || typeof value === 'string'
122 | })
123 |
124 | if (input && typeof input === 'string') {
125 | return `\`${input}\``
126 | }
127 |
128 | return input
129 | }
130 |
131 | export {commands, configure}
132 |
133 | /* eslint no-new-func:0, complexity:0 */
134 | /* globals Cypress, cy */
135 |
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | function getFirstElement(jqueryOrElement) {
2 | if (Cypress.dom.isJquery(jqueryOrElement)) {
3 | return jqueryOrElement.get(0)
4 | }
5 | return jqueryOrElement
6 | }
7 |
8 | export {getFirstElement}
9 |
10 | /* globals Cypress */
11 |
--------------------------------------------------------------------------------
/types/add-commands.d.ts:
--------------------------------------------------------------------------------
1 | // Allow `import '@testing-library/cypress/add-commands'` from a `cypress/commands.ts` file
2 | import './'
3 |
--------------------------------------------------------------------------------
/types/index.d.ts:
--------------------------------------------------------------------------------
1 | // TypeScript Version: 3.8
2 |
3 | import {
4 | configure,
5 | Matcher,
6 | ByRoleMatcher,
7 | MatcherOptions as DTLMatcherOptions,
8 | ByRoleOptions as DTLByRoleOptions,
9 | SelectorMatcherOptions as DTLSelectorMatcherOptions,
10 | } from '@testing-library/dom'
11 |
12 | export interface CTLMatcherOptions
13 | extends Partial,
14 | Partial {
15 | container?: Element | JQuery
16 | }
17 |
18 | export type MatcherOptions = DTLMatcherOptions | CTLMatcherOptions
19 | export type ByRoleOptions = DTLByRoleOptions | CTLMatcherOptions
20 | export type SelectorMatcherOptions =
21 | | DTLSelectorMatcherOptions
22 | | CTLMatcherOptions
23 |
24 | declare global {
25 | namespace Cypress {
26 | // 🤔 unsure why this Subject is unused, nor what to do with it...
27 | // eslint-disable-next-line @typescript-eslint/no-unused-vars
28 | interface Chainable {
29 | /**
30 | * dom-testing-library helpers for Cypress
31 | *
32 | * `findBy*` APIs search for an element and throw an error if nothing found
33 | * `findAllBy*` APIs search for all elements and throw an error if nothing found
34 | *
35 | * @see https://github.com/testing-library/cypress-testing-library#usage
36 | * @see https://github.com/testing-library/dom-testing-library#table-of-contents
37 | */
38 | findByPlaceholderText(
39 | id: Matcher,
40 | options?: MatcherOptions,
41 | ): Chainable
42 |
43 | /**
44 | * dom-testing-library helpers for Cypress
45 | *
46 | * `findBy*` APIs search for an element and throw an error if nothing found
47 | * `findAllBy*` APIs search for all elements and throw an error if nothing found
48 | *
49 | * @see https://github.com/testing-library/cypress-testing-library#usage
50 | * @see https://github.com/testing-library/dom-testing-library#table-of-contents
51 | */
52 | findAllByPlaceholderText(
53 | id: Matcher,
54 | options?: MatcherOptions,
55 | ): Chainable
56 |
57 | /**
58 | * dom-testing-library helpers for Cypress
59 | *
60 | * `findBy*` APIs search for an element and throw an error if nothing found
61 | * `findAllBy*` APIs search for all elements and throw an error if nothing found
62 | *
63 | * @see https://github.com/testing-library/cypress-testing-library#usage
64 | * @see https://github.com/testing-library/dom-testing-library#table-of-contents
65 | */
66 | findByText(
67 | id: Matcher,
68 | options?: SelectorMatcherOptions,
69 | ): Chainable
70 |
71 | /**
72 | * dom-testing-library helpers for Cypress
73 | *
74 | * `findBy*` APIs search for an element and throw an error if nothing found
75 | * `findAllBy*` APIs search for all elements and throw an error if nothing found
76 | *
77 | * @see https://github.com/testing-library/cypress-testing-library#usage
78 | * @see https://github.com/testing-library/dom-testing-library#table-of-contents
79 | */
80 | findAllByText(
81 | id: Matcher,
82 | options?: SelectorMatcherOptions,
83 | ): Chainable
84 |
85 | /**
86 | * dom-testing-library helpers for Cypress
87 | *
88 | * `findBy*` APIs search for an element and throw an error if nothing found
89 | * `findAllBy*` APIs search for all elements and throw an error if nothing found
90 | *
91 | * @see https://github.com/testing-library/cypress-testing-library#usage
92 | * @see https://github.com/testing-library/dom-testing-library#table-of-contents
93 | */
94 | findByLabelText(
95 | id: Matcher,
96 | options?: SelectorMatcherOptions,
97 | ): Chainable
98 |
99 | /**
100 | * dom-testing-library helpers for Cypress
101 | *
102 | * `findBy*` APIs search for an element and throw an error if nothing found
103 | * `findAllBy*` APIs search for all elements and throw an error if nothing found
104 | *
105 | * @see https://github.com/testing-library/cypress-testing-library#usage
106 | * @see https://github.com/testing-library/dom-testing-library#table-of-contents
107 | */
108 | findAllByLabelText(
109 | id: Matcher,
110 | options?: SelectorMatcherOptions,
111 | ): Chainable
112 |
113 | /**
114 | * dom-testing-library helpers for Cypress
115 | *
116 | * `findBy*` APIs search for an element and throw an error if nothing found
117 | * `findAllBy*` APIs search for all elements and throw an error if nothing found
118 | *
119 | * @see https://github.com/testing-library/cypress-testing-library#usage
120 | * @see https://github.com/testing-library/dom-testing-library#table-of-contents
121 | */
122 | findByAltText(id: Matcher, options?: MatcherOptions): Chainable
123 |
124 | /**
125 | * dom-testing-library helpers for Cypress
126 | *
127 | * `findBy*` APIs search for an element and throw an error if nothing found
128 | * `findAllBy*` APIs search for all elements and throw an error if nothing found
129 | *
130 | * @see https://github.com/testing-library/cypress-testing-library#usage
131 | * @see https://github.com/testing-library/dom-testing-library#table-of-contents
132 | */
133 | findAllByAltText(id: Matcher, options?: MatcherOptions): Chainable
134 |
135 | /**
136 | * dom-testing-library helpers for Cypress
137 | *
138 | * `findBy*` APIs search for an element and throw an error if nothing found
139 | * `findAllBy*` APIs search for all elements and throw an error if nothing found
140 | *
141 | * @see https://github.com/testing-library/cypress-testing-library#usage
142 | * @see https://github.com/testing-library/dom-testing-library#table-of-contents
143 | */
144 | findByTestId(id: Matcher, options?: MatcherOptions): Chainable
145 |
146 | /**
147 | * dom-testing-library helpers for Cypress
148 | *
149 | * `findBy*` APIs search for an element and throw an error if nothing found
150 | * `findAllBy*` APIs search for all elements and throw an error if nothing found
151 | *
152 | * @see https://github.com/testing-library/cypress-testing-library#usage
153 | * @see https://github.com/testing-library/dom-testing-library#table-of-contents
154 | */
155 | findAllByTestId(id: Matcher, options?: MatcherOptions): Chainable
156 |
157 | /**
158 | * dom-testing-library helpers for Cypress
159 | *
160 | * `findBy*` APIs search for an element and throw an error if nothing found
161 | * `findAllBy*` APIs search for all elements and throw an error if nothing found
162 | *
163 | * @see https://github.com/testing-library/cypress-testing-library#usage
164 | * @see https://github.com/testing-library/dom-testing-library#table-of-contents
165 | */
166 | findByTitle(id: Matcher, options?: MatcherOptions): Chainable
167 |
168 | /**
169 | * dom-testing-library helpers for Cypress
170 | *
171 | * `findBy*` APIs search for an element and throw an error if nothing found
172 | * `findAllBy*` APIs search for all elements and throw an error if nothing found
173 | *
174 | * @see https://github.com/testing-library/cypress-testing-library#usage
175 | * @see https://github.com/testing-library/dom-testing-library#table-of-contents
176 | */
177 | findAllByTitle(id: Matcher, options?: MatcherOptions): Chainable
178 |
179 | /**
180 | * dom-testing-library helpers for Cypress
181 | *
182 | * `findBy*` APIs search for an element and throw an error if nothing found
183 | * `findAllBy*` APIs search for all elements and throw an error if nothing found
184 | *
185 | * @see https://github.com/testing-library/cypress-testing-library#usage
186 | * @see https://github.com/testing-library/dom-testing-library#table-of-contents
187 | */
188 | findByDisplayValue(
189 | id: Matcher,
190 | options?: MatcherOptions,
191 | ): Chainable
192 |
193 | /**
194 | * dom-testing-library helpers for Cypress
195 | *
196 | * `findBy*` APIs search for an element and throw an error if nothing found
197 | * `findAllBy*` APIs search for all elements and throw an error if nothing found
198 | *
199 | * @see https://github.com/testing-library/cypress-testing-library#usage
200 | * @see https://github.com/testing-library/dom-testing-library#table-of-contents
201 | */
202 | findAllByDisplayValue(
203 | id: Matcher,
204 | options?: MatcherOptions,
205 | ): Chainable
206 |
207 | /**
208 | * dom-testing-library helpers for Cypress
209 | *
210 | * `findBy*` APIs search for an element and throw an error if nothing found
211 | * `findAllBy*` APIs search for all elements and throw an error if nothing found
212 | *
213 | * @see https://github.com/testing-library/cypress-testing-library#usage
214 | * @see https://github.com/testing-library/dom-testing-library#table-of-contents
215 | */
216 | findByRole(id: ByRoleMatcher, options?: ByRoleOptions): Chainable
217 |
218 | /**
219 | * dom-testing-library helpers for Cypress
220 | *
221 | * `findBy*` APIs search for an element and throw an error if nothing found
222 | * `findAllBy*` APIs search for all elements and throw an error if nothing found
223 | *
224 | * @see https://github.com/testing-library/cypress-testing-library#usage
225 | * @see https://github.com/testing-library/dom-testing-library#table-of-contents
226 | */
227 | findAllByRole(
228 | id: ByRoleMatcher,
229 | options?: ByRoleOptions,
230 | ): Chainable
231 |
232 | /**
233 | * dom-testing-library helpers for Cypress
234 | *
235 | * Configure dom-testing-library through Cypress object. Wraps `configure(config)`
236 | *
237 | * @see https://github.com/testing-library/cypress-testing-library#usage
238 | * @see https://github.com/testing-library/dom-testing-library#table-of-contents
239 | */
240 | configureCypressTestingLibrary(
241 | config: Parameters[0],
242 | ): Chainable
243 | }
244 | }
245 | }
246 |
247 | export {configure}
248 |
--------------------------------------------------------------------------------
/types/test.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import {configure} from '.'
3 | import './add-commands'
4 |
5 | configure({testIdAttribute: 'data-myown-testid'})
6 |
7 | // findBy*
8 | cy.findByPlaceholderText('foo') // $ExpectType Chainable>
9 | cy.findByText('foo') // $ExpectType Chainable>
10 | cy.findByLabelText('foo') // $ExpectType Chainable>
11 | cy.findByAltText('foo') // $ExpectType Chainable>
12 | cy.findByTestId('foo') // $ExpectType Chainable>
13 | cy.findByTitle('foo') // $ExpectType Chainable>
14 | cy.findByDisplayValue('foo') // $ExpectType Chainable>
15 | cy.findByRole('foo') // $ExpectType Chainable>
16 |
17 | // findAllBy*
18 | cy.findAllByPlaceholderText('foo') // $ExpectType Chainable>
19 | cy.findAllByText('foo') // $ExpectType Chainable>
20 | cy.findAllByLabelText('foo') // $ExpectType Chainable>
21 | cy.findAllByAltText('foo') // $ExpectType Chainable>
22 | cy.findAllByTestId('foo') // $ExpectType Chainable>
23 | cy.findAllByTitle('foo') // $ExpectType Chainable>
24 | cy.findAllByDisplayValue('foo') // $ExpectType Chainable>
25 | cy.findAllByRole('foo') // $ExpectType Chainable>
26 |
27 | // configure
28 | cy.configureCypressTestingLibrary({testIdAttribute: 'data-myawesome-testid'}) // $ExpectType Chainable
29 |
--------------------------------------------------------------------------------
/types/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../node_modules/kcd-scripts/shared-tsconfig.json",
3 | "include": ["."]
4 | }
5 |
--------------------------------------------------------------------------------