Skip to content

Commit

Permalink
Issue 194 (#220)
Browse files Browse the repository at this point in the history
* rename to 'Variables and Aliases'

* point to renamed aliases doc

* WIP begin rewriting variables and aliases

- provide much better explanations
- show multiple uses of aliases
- explain closures and why you’d use them
- debugging tips

* WIP, better intro, add aliasing elements section

* finished improving variables and aliases

* updated network requests, balanced aliasing + waiting on routes better. cleanup content and headers

* sprinkled in references to aliases and network guides better into API docs

* reference variables and aliases in intro to cypress better

* FAQ references to intro + aliases doc

* wrote new best practice on trying to assign return values
  • Loading branch information
brian-mann authored Nov 4, 2017
1 parent b538d3b commit 39cec5e
Show file tree
Hide file tree
Showing 12 changed files with 571 additions and 187 deletions.
2 changes: 1 addition & 1 deletion source/_data/sidebar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ guides:
writing-and-organizing-tests: writing-and-organizing-tests.html
interacting-with-elements: interacting-with-elements.html
overview-of-test-runner: overview-of-test-runner.html
aliases-and-references: aliases-and-references.html
variables-and-aliases: variables-and-aliases.html
conditional-testing: conditional-testing.html
guides:
command-line: command-line.html
Expand Down
4 changes: 2 additions & 2 deletions source/api/commands/as.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ comments: false
Assign an alias for later use. Reference the alias later within a {% url `cy.get()` get %} or {% url `cy.wait()` wait %} command with a `@` prefix.

{% note info %}
**Note:** `.as()` assumes you are already familiar with core concepts such as {% url 'aliases' aliases-and-references %}
**Note:** `.as()` assumes you are already familiar with core concepts such as {% url 'aliases' variables-and-aliases %}
{% endnote %}

# Syntax
Expand Down Expand Up @@ -104,4 +104,4 @@ Aliases of routes display in the routes instrument panel:

- {% url `cy.get()` get %}
- {% url `cy.wait()` wait %}
- {% url 'Guides: Aliases' aliases-and-references %}
- {% url 'Guides: Aliases' variables-and-aliases %}
30 changes: 25 additions & 5 deletions source/api/commands/get.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: get
comments: false
---

Get one or more DOM elements by selector or {% url 'alias' aliases-and-references %}.
Get one or more DOM elements by selector or {% url 'alias' variables-and-aliases %}.

{% note info %}
The querying behavior of this command matches exactly how {% url `$(...)` http://api.jquery.com/jQuery/ %} works in jQuery.
Expand Down Expand Up @@ -36,10 +36,12 @@ A selector used to filter matching DOM elements.

An alias as defined using the {% url `.as()` as %} command and referenced with the `@` character and the name of the alias.

Internally, Cypress keeps a cache of all aliased elements. If the element currently exists in the DOM, it is immediately returned. If the element no longer exists, Cypress will re-query the element based on the previous selector path defined before {% url `.as()` as %} to find it again.
You can use `cy.get()` for aliases of primitives, regular objects, or even DOM elements.

{% note info %}
{% url 'Read more about aliases here' aliases-and-references %}
When using aliases with DOM elements, Cypress will query the DOM again if the previously aliased DOM element has gone stale.

{% note info 'Core Concept' %}
{% url 'You can read more about aliasing objects and elements in our Core Concept Guide' variables-and-aliases#Aliases %}.
{% endnote %}

**{% fa fa-angle-right %} options** ***(Object)***
Expand Down Expand Up @@ -92,7 +94,7 @@ cy.get('form').within(function(){

## Alias

For a detailed explanation of aliasing, {% url 'read more about aliasing here' aliases-and-references %}.
For a detailed explanation of aliasing, {% url 'read more about aliasing here' variables-and-aliases#Aliases %}.

***Get the aliased 'todos' elements***

Expand All @@ -117,6 +119,24 @@ it('disables on click', function(){
})
```

***Get the aliased 'users' fixture***

```javascript
beforeEach(function(){
cy.fixtures('users.json').as('users')
})

it('disables on click', function(){
// access the array of users
cy.get('@users').then((users) => {
// get the first user
const user = users[0]

cy.get('header').contains(user.name)
})
})
```

# Rules

## Requirements {% helper_icon requirements %}
Expand Down
13 changes: 11 additions & 2 deletions source/api/commands/then.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ comments: false

Enables you to work with the subject yielded from the previous command.

{% note info %}
**Note:** `.then()` assumes you are already familiar with core concepts such as {% url 'closures' variables-and-aliases#Closures %}.
{% endnote %}

# Syntax

```javascript
Expand Down Expand Up @@ -37,14 +41,18 @@ Option | Default | Description

## Yields {% helper_icon yields %}

`.then()` is modeled identically to the way Promises work in JavaScript. Whatever is returned from the callback function becomes the new subject and will flow into the next command (with the exception of `null` and `undefined`).
`.then()` is modeled identically to the way Promises work in JavaScript. Whatever is returned from the callback function becomes the new subject and will flow into the next command (with the exception of `undefined`).

When `null` or `undefined` are returned by the callback function, the subject will not be modified and will instead carry over to the next command.
When `undefined` is returned by the callback function, the subject will not be modified and will instead carry over to the next command.

Just like Promises, you can return any compatible "thenable" (anything that has a `.then()` interface) and Cypress will wait for that to resolve before continuing forward through the chain of commands.

# Examples

{% note info %}
We have several more examples in our {% url 'Core Concepts Guide' variables-and-aliases %} which go into the various ways you can use `.then()` to store, compare, and debug values.
{% endnote %}

## DOM element

***The element `input` is yielded***
Expand Down Expand Up @@ -158,4 +166,5 @@ cy.get('button').click().then(($button) => {
- {% url `.its()` its %}
- {% url `.should()` should %}
- {% url `.spread()` spread %}
- {% url 'Guide: Using Closures to compare values' variables-and-aliases#Closures %}
- {% url 'Guide: Chains of Commands' introduction-to-cypress#Chains-of-Commands %}
10 changes: 6 additions & 4 deletions source/api/commands/wait.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ The amount of time to wait in milliseconds.

An aliased route as defined using the {% url `.as()` as %} command and referenced with the `@` character and the name of the alias.

{% note info %}
{% url 'Read about using aliases here.' aliases-and-references %}
{% note info 'Core Concept' %}
{% url 'You can read more about aliasing routes in our Core Concept Guide' network-requests#Waiting %}.
{% endnote %}

**{% fa fa-angle-right %} aliases** ***(Array)***
Expand Down Expand Up @@ -75,13 +75,15 @@ cy.wait(2000) // wait for 2 seconds
{% note warning 'Anti-Pattern' %}
You almost **never** need to wait for an arbitrary period of time. There are always better ways to express this in Cypress.

Passing a number to `cy.wait()` exists because it's sometimes helpful when debugging to isolate a test failure you're trying to temporarily understand.

Read about {% url 'best practices' best-practices#Unnecessary-Waiting %} here.
{% endnote %}

Additionally, its often much easier to use {% url `cy.debug()` debug %} or {% url `cy.pause()` pause %} when debugging your test code.

## Alias

For a detailed explanation of aliasing, {% url 'read more about waiting on routes here' network-requests#Waiting %}.

***Wait for a specific XHR to respond***

```javascript
Expand Down
13 changes: 13 additions & 0 deletions source/faq/questions/using-cypress-faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ cy.get('input').invoke('val').then((val1) => {
})
```

## {% fa fa-angle-right %} How do I compare the value or state of one thing to another?

Our {% url 'Variables and Aliases guide' variables-and-aliases %} gives you examples of doing exactly that.

## {% fa fa-angle-right %} How do I get the native DOM reference of an element found using Cypress?

Cypress wraps elements in jQuery so you'd just get the native element from there within a {% url "`.then()`" then %} command.
Expand All @@ -109,6 +113,15 @@ What you're asking about is conditional testing and control flow.

Please read our extensive {% url 'Conditional Testing Guide' conditional-testing %} which explains this in detail.

## {% fa fa-angle-right %} Can I use the new ES7 async / await syntax?

No. The Command API is not designed in a way that makes this possible.

If you're curious please read:

- Our {% url 'Introduction to Cypress guide' introduction-to-cypress#Commands-Are-Asynchronous %} which explains how the Commands are designed
- Our {% url 'Variables and Aliases guide' variables-and-aliases %} which talks about patterns dealing with async code

## {% fa fa-angle-right %} Can I prevent Cypress from failing my test when my application throws an uncaught exception error?

Yes.
Expand Down
161 changes: 0 additions & 161 deletions source/guides/core-concepts/aliases-and-references.md

This file was deleted.

14 changes: 11 additions & 3 deletions source/guides/core-concepts/introduction-to-cypress.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ Cypress commands do not **return** their subjects, they **yield** them. Remember
{% endnote %}

{% note info %}
To work around the need to reference elements, Cypress has a feature {% url 'known as aliasing' aliases-and-references %}. Aliasing helps you to **store** and **save** element references for future use.
To work around the need to reference elements, Cypress has a feature {% url 'known as aliasing' variables-and-aliases %}. Aliasing helps you to **store** and **save** element references for future use.
{% endnote %}

***Using {% url `.then()` then %} To Act On A Subject***
Expand Down Expand Up @@ -333,9 +333,13 @@ cy
})
```

{% note info 'Core Concept' %}
We have many more examples and use cases of `cy.then()` in our {% url 'Core Concept Guide' variables-and-aliases %} that teaches you how to properly deal with asynchronous code, when to use variables, and what aliasing is.
{% endnote %}

***Using Aliases to Refer to Previous Subjects***

Cypress has some added functionality for quickly referring back to past subjects called {% url 'Aliases' aliases-and-references %}. It looks something like this:
Cypress has some added functionality for quickly referring back to past subjects called {% url 'Aliases' variables-and-aliases %}. It looks something like this:

```js
cy
Expand Down Expand Up @@ -477,6 +481,10 @@ These design patterns ensure we can create **deterministic**, **repeatable**, **

{% note info %}
Cypress is built using Promises that come from {% url "Bluebird" http://bluebirdjs.com/ %}. However, Cypress commands do not return these typical Promise instances. Instead we return what's called a `Chainer` that acts like a layer sitting on top of the internal Promise instances.

For this reason you cannot **ever** return or assign anything useful from Cypress commands.

If you'd like to learn more about handling asynchronous Cypress Commands please read our {% url 'Core Concept Guide' variables-and-aliases %}.
{% endnote %}

## Commands Are Not Promises
Expand Down Expand Up @@ -908,7 +916,7 @@ We've set their default timeout durations based on how long we expect certain ac
For instance:
- {% url `cy.visit()` visit %} loads a remote page and does not resolve *until all of the external resources complete their loading phase*. This may take awhile, so its default timeout is set to `60000ms`.
- {% url `cy.exec()` exec %} runs a system command such as *seeding a database*. We expect this to potentially take a long time, and its default timeout is set to `60000ms`.
- {% url `cy.wait()` wait %} actually uses 2 different timeouts. When waiting for a {% url 'routing alias' aliases-and-references#Aliasing-Routes %}, we wait for a matching request for `5000ms`, and then additionally for the server's response for `30000ms`. We expect your application to make a matching request quickly, but we expect the server's response to potentially take much longer.
- {% url `cy.wait()` wait %} actually uses 2 different timeouts. When waiting for a {% url 'routing alias' variables-and-aliases#Routes %}, we wait for a matching request for `5000ms`, and then additionally for the server's response for `30000ms`. We expect your application to make a matching request quickly, but we expect the server's response to potentially take much longer.

That leaves most other commands including all DOM based commands to time out by default after 4000ms.

Expand Down
Loading

0 comments on commit 39cec5e

Please sign in to comment.