Skip to content

Commit 7d78203

Browse files
BlueWindsemilyrohrboughAtofStryker
authored
Update guides for Cy 13, where assertions are now commands (#5081)
* .readFile() is now a query (#5017) * .readFile() is now a query * Add section on new .readFile() superpowers * Fix page slug for readFile * Prettier run * Update guides to better support users in Cy 13, where assertions are now commands * Review updates * Apply suggestions from code review Co-authored-by: Emily Rohrbough <emilyrohrbough@users.noreply.github.com> * Partial review feedback (more to come) * Review updates * Prettier run * fix: update retry ability guide and migration guide now that should() and and() will not be queries in v13. see cypress-io/cypress#25738 * chore: correct number of queries in example * revert: images changes due to should() and and() being queries, which is no longer applicable due to cypress-io/cypress#25738 * chore: lint guides --------- Co-authored-by: Emily Rohrbough <emilyrohrbough@users.noreply.github.com> Co-authored-by: Bill Glesias <bglesias@gmail.com>
1 parent 674419f commit 7d78203

File tree

7 files changed

+138
-190
lines changed

7 files changed

+138
-190
lines changed

docs/guides/core-concepts/interacting-with-elements.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ Cypress will watch the DOM - re-running the queries that yielded the current
4040
subject - until an element passes all of these checks for the duration of the
4141
[`defaultCommandTimeout`](/guides/references/configuration#Timeouts) (described
4242
in depth in the
43-
[Default Assertions](/guides/core-concepts/introduction-to-cypress#Default-Assertions)
43+
[Implicit Assertions](/guides/core-concepts/introduction-to-cypress#Implicit-Assertions)
4444
core concept guide).
4545

4646
**_Checks and Actions Performed_**

docs/guides/core-concepts/introduction-to-cypress.mdx

Lines changed: 55 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ just in case".
302302
:::
303303

304304
Later in this guide we'll go into much more detail about
305-
[Default Assertions](#Default-Assertions) and [Timeouts](#Timeouts).
305+
[Implicit Assertions](#Implicit-Assertions) and [Timeouts](#Timeouts).
306306

307307
## Chains of Commands
308308

@@ -912,11 +912,10 @@ randomly fail. This would lead to flaky, inconsistent results.
912912

913913
:::info
914914

915-
While Cypress is built using Promises that come from
916-
[Bluebird](http://bluebirdjs.com/), these are not what we expose as commands and
917-
assertions on `cy`. If you'd like to learn more about handling asynchronous
918-
Cypress Commands please read our
919-
[Core Concept Guide](/guides/core-concepts/variables-and-aliases).
915+
While Cypress does have a [`.then()`](/api/commands/then) command, Cypress
916+
commands are not Promises and cannot be `await`ed. If you'd like to learn more
917+
about handling asynchronous Cypress Commands please read our
918+
[Variables and Aliases Guide](/guides/core-concepts/variables-and-aliases).
920919

921920
:::
922921

@@ -958,24 +957,22 @@ model after a real user working step by step.
958957
#### You cannot add a `.catch` error handler to a failed command
959958

960959
In Cypress there is no built in error recovery from a failed command. A command
961-
and its assertions all _eventually_ pass, or if one fails, all remaining
962-
commands are not executed, and the test fails.
960+
_eventually_ passes, or if it fails, all remaining commands are not executed,
961+
and the test as a whole fails.
963962

964963
You might be wondering:
965964

966965
> How do I create conditional control flow, using if/else? So that if an element
967966
> does (or doesn't) exist, I choose what to do?
968967
969-
The problem with this question is that this type of conditional control flow
970-
ends up being non-deterministic. This means different test runs may behave
971-
differently, which makes them less deterministic and consistent. In general,
972-
there are only a handful of very specific situations where you _can_ create
973-
control flow using Cypress commands.
968+
Cypress does not support this type of conditional control flow because it leads
969+
to non-deterministic tests - different runs may behave differently, which makes
970+
them less consistent and useful for verifying your application's correctness. In
971+
general, there are only a handful of very specific situations where you can or
972+
should create control flow using Cypress commands.
974973

975974
With that said, as long as you are aware of the potential pitfalls with control
976-
flow, it is possible to do this in Cypress!
977-
978-
You can read all about how to do
975+
flow, it is possible to do this in Cypress! You can read all about how to do
979976
[conditional testing](/guides/core-concepts/conditional-testing) here.
980977

981978
## Assertions
@@ -989,33 +986,18 @@ Assertions describe the **desired** state of your **elements**, your
989986

990987
:::
991988

992-
What makes Cypress unique from other testing tools is that commands
993-
**automatically retry** their assertions. In fact, they will look "downstream"
994-
at what you're expressing and modify their behavior to make your assertions
995-
pass.
996-
997-
You should think of assertions as **guards**.
998-
999-
Use your **guards** to describe what your application should look like, and
1000-
Cypress will automatically **block, wait, and retry** until it reaches that
1001-
state.
1002-
1003-
:::tip
1004-
1005-
<strong>Core Concept</strong>
1006-
1007-
Each command documents its behavior with assertions - such as how it retries or
1008-
waits for assertions to pass.
1009-
1010-
:::
989+
What makes Cypress unique from other testing tools is that assertions
990+
**automatically retry**. Think of them as **guards** - assertions describe what
991+
your application should look like, and Cypress will automatically **block, wait,
992+
and retry** until it reaches that state.
1011993

1012994
### Asserting in English
1013995

1014996
Let's look at how you'd describe an assertion in English:
1015997

1016998
:::note
1017999

1018-
After clicking on this `<button>`, I expect its class to eventually be `active`.
1000+
After clicking on this `<button>`, I expect its class to be `active`.
10191001

10201002
:::
10211003

@@ -1027,7 +1009,9 @@ cy.get('button').should('have.class', 'active')
10271009
```
10281010

10291011
This above test will pass even if the `.active` class is applied to the button
1030-
asynchronously - or after an indeterminate period of time.
1012+
asynchronously, after an indeterminate period of time or even if the button is
1013+
removed from the DOM entirely for a while (replaced with a waiting spinner, for
1014+
example).
10311015

10321016
```javascript
10331017
// even though we are adding the class
@@ -1078,7 +1062,7 @@ cy.get('form').submit()
10781062
:::
10791063

10801064
Without a single explicit assertion, there are dozens of ways this test can
1081-
fail! Here's a few:
1065+
fail. Here's a few:
10821066

10831067
- The initial [`cy.mount()`](/api/commands/mount) or
10841068
[`cy.visit()`](/api/commands/visit) could respond with something other than
@@ -1096,17 +1080,16 @@ fail! Here's a few:
10961080

10971081
<strong>Core Concept</strong>
10981082

1099-
With Cypress, you don't have to assert to have a useful test. Even without
1100-
assertions, a few lines of Cypress can ensure thousands of lines of code are
1101-
working properly across the client and server!
1083+
With Cypress, you don't have to write explicit assertions to have a useful test.
1084+
Without a single `expect()` or `.should()`, a few lines of Cypress can ensure
1085+
thousands of lines of code are working properly across the client and server.
11021086

1103-
This is because many commands have a built in
1104-
[Default Assertion](#Default-Assertions) which offer you a high level of
1105-
guarantee.
1087+
This is because many commands have a built in Implicit Assertions which offer
1088+
you a high level of confidence that your application is working as expected.
11061089

11071090
:::
11081091

1109-
### Default Assertions
1092+
### Implicit Assertions
11101093

11111094
Many commands have default, built-in assertions, or rather have requirements
11121095
that may cause it to fail without needing an explicit assertion you've added.
@@ -1159,7 +1142,7 @@ they can fail, typically by passing a `{force: true}` option.
11591142

11601143
```js
11611144
cy
1162-
// there is a default assertion that this
1145+
// there is an implicit assertion that this
11631146
// button must exist in the DOM before proceeding
11641147
.get('button')
11651148

@@ -1168,16 +1151,16 @@ cy
11681151
.click()
11691152
```
11701153

1171-
Cypress will automatically _wait_ for elements to pass their default assertions.
1172-
Like with the explicit assertions you've added, all of these assertions share
1173-
the _same_ timeout values.
1154+
Cypress will automatically _wait_ for elements to pass their implicit
1155+
assertions. See [Timeouts](#Timeouts) below for more on how timeouts are
1156+
determined.
11741157

1175-
#### Example #2: Reversing the Default Assertion
1158+
#### Example #2: Reversing the Implicit Assertion
11761159

11771160
Most of the time, when querying for elements, you expect them to eventually
11781161
exist. But sometimes you wish to wait until they _don't_ exist.
11791162

1180-
All you have to do is add that assertion and Cypress will **reverse** its rules
1163+
All you have to do is add that assertion and Cypress will **skip** implicitly
11811164
waiting for elements to exist.
11821165

11831166
```js
@@ -1196,15 +1179,14 @@ cy.get('#modal').should('not.exist')
11961179

11971180
<strong>Core Concept</strong>
11981181

1199-
By adding [`.should('not.exist')`](/api/commands/should) to any DOM command,
1200-
Cypress will reverse its default assertion and automatically wait until the
1201-
element does not exist.
1182+
If you want to disable the default existence assertion, you can add
1183+
[`.should('not.exist')`](/api/commands/should) to any DOM command.
12021184

12031185
:::
12041186

1205-
#### Example #3: Other Default Assertions
1187+
#### Example #3: Other Implicit Assertions
12061188

1207-
Other commands have other default assertions not related to the DOM.
1189+
Other commands have other implicit assertions not related to the DOM.
12081190

12091191
For instance, [`.its()`](/api/commands/its) requires that the property you're
12101192
asking about exists on the object.
@@ -1236,20 +1218,20 @@ use them in Cypress.
12361218

12371219
There are two ways to write assertions in Cypress:
12381220

1239-
1. **Implicit Subjects:** Using [`.should()`](/api/commands/should) or
1221+
1. **As Cypress Commands:** Using [`.should()`](/api/commands/should) or
12401222
[`.and()`](/api/commands/and).
1241-
2. **Explicit Subjects:** Using `expect`.
1223+
2. **As Mocha Assertions:** Using `expect`.
12421224

1243-
### Implicit Subjects
1225+
### Command Assertions
12441226

12451227
Using [`.should()`](/api/commands/should) or [`.and()`](/api/commands/and)
12461228
commands is the preferred way of making assertions in Cypress. These are typical
12471229
Cypress commands, which means they apply to the currently yielded subject in the
12481230
command chain.
12491231

12501232
```javascript
1251-
// the implicit subject here is the first <tr>
1252-
// this asserts that the <tr> has an .active class
1233+
// The subject here is the first <tr>.
1234+
// This asserts that the <tr> has an .active class
12531235
cy.get('tbody tr:first').should('have.class', 'active')
12541236
```
12551237

@@ -1268,29 +1250,11 @@ subject, [`.and('have.attr')`](/api/commands/and) is executed against the same
12681250
element. This is handy when you need to assert multiple things against a single
12691251
subject quickly.
12701252

1271-
If we wrote this assertion in the explicit form "the long way", it would look
1272-
like this:
1273-
1274-
```js
1275-
cy.get('tbody tr:first').should(($tr) => {
1276-
expect($tr).to.have.class('active')
1277-
expect($tr).to.have.attr('href', '/users')
1278-
})
1279-
```
1280-
1281-
The implicit form is much shorter! So when would you want to use the explicit
1282-
form?
1283-
1284-
Typically when you want to:
1285-
1286-
- Assert multiple things about the same subject
1287-
- Massage the subject in some way prior to making the assertion
1288-
1289-
### Explicit Subjects
1253+
### Mocha Assertions
12901254

1291-
Using `expect` allows you to pass in a specific subject and make an assertion
1292-
about it. This is probably how you're used to seeing assertions written in unit
1293-
tests:
1255+
Using `expect` allows you to assert on any javascript object, not just the
1256+
current subject. This is probably how you're used to seeing assertions written
1257+
in unit tests:
12941258

12951259
```js
12961260
// the explicit subject here is the boolean: true
@@ -1306,7 +1270,7 @@ Check out our example recipes for [unit testing](/examples/recipes) and
13061270

13071271
:::
13081272

1309-
Explicit assertions are great when you want to:
1273+
Mocha assertions are great when you want to:
13101274

13111275
- Perform custom logic prior to making the assertion.
13121276
- Make multiple assertions against the same subject.
@@ -1361,7 +1325,7 @@ cy.get('p').should(($p) => {
13611325

13621326
When using a callback function with [`.should()`](/api/commands/should), be sure
13631327
that the entire function can be executed multiple times without side effects.
1364-
Cypress applies its [retry](/guides/core-concepts/retry-ability) logic to these
1328+
Cypress applies its [retry logic](/guides/core-concepts/retry-ability) to these
13651329
functions: if there's a failure, it will repeatedly rerun the assertions until
13661330
the timeout is reached. That means your code should be retry-safe. The technical
13671331
term for this means your code must be **idempotent**.
@@ -1384,10 +1348,10 @@ Remember because assertions are used to describe a condition of the previous
13841348
commands - the `timeout` modification goes on the previous commands _not the
13851349
assertions_.
13861350

1387-
#### Example #1: Default Assertion
1351+
#### Example #1: Implicit Assertion
13881352

13891353
```js
1390-
// because .get() has a default assertion
1354+
// because .get() has a implicit assertion
13911355
// that this element exists, it can time out and fail
13921356
cy.get('.mobile-nav')
13931357
```
@@ -1416,14 +1380,14 @@ The _total_ amount of time Cypress will wait for _all_ of the assertions to pass
14161380
is for the duration of the [cy.get()](/api/commands/get) `timeout` (which is 4
14171381
seconds).
14181382

1419-
Timeouts can be modified per command and this will affect all default assertions
1420-
and any assertions chained after that command.
1383+
Timeouts can be modified per command and this will affect all implicit
1384+
assertions and any assertions chained after that command.
14211385

14221386
#### Example #3: Modifying Timeouts
14231387

14241388
```js
1425-
// we've modified the timeout which affects default
1426-
// plus all added assertions
1389+
// we've modified the timeout which affects the implicit
1390+
// assertions as well as all explicit ones.
14271391
cy.get('.mobile-nav', { timeout: 10000 })
14281392
.should('be.visible')
14291393
.and('contain', 'Home')

0 commit comments

Comments
 (0)