Skip to content

Latest commit

 

History

History
417 lines (296 loc) · 9.77 KB

contains.md

File metadata and controls

417 lines (296 loc) · 9.77 KB
title
contains

Get the DOM element containing the text. DOM elements can contain more than the desired text and still match. Additionally, Cypress {% urlHash 'prefers some DOM elements' Notes %} over the deepest element found.

Syntax

.contains(content)
.contains(content, options)
.contains(selector, content)
.contains(selector, content, options)

// ---or---

cy.contains(content)
cy.contains(content, options)
cy.contains(selector, content)
cy.contains(selector, content, options)

Usage

{% fa fa-check-circle green %} Correct Usage

cy.get('.nav').contains('About')  // Yield el in .nav containing 'About'
cy.contains('Hello')              // Yield first el in document containing 'Hello'

{% fa fa-exclamation-triangle red %} Incorrect Usage

cy.title().contains('My App')     // Errors, 'title' does not yield DOM element
cy.getCookies().contains('_key')  // Errors, 'getCookies' does not yield DOM element

Arguments

{% fa fa-angle-right %} content (String, Number, RegExp)

Get the DOM element containing the content.

{% fa fa-angle-right %} selector (String selector)

Specify a selector to filter DOM elements containing the text. Cypress will ignore its {% urlHash 'default preference order' Notes %} for the specified selector. Using a selector allows you to return more shallow elements (higher in the tree) that contain the specific text.

{% fa fa-angle-right %} options (Object)

Pass in an options object to change the default behavior of .contains().

Option Default Description
matchCase true Check case sensitivity
log true {% usage_options log %}
timeout {% url defaultCommandTimeout configuration#Timeouts %} {% usage_options timeout .contains %}

Yields {% helper_icon yields %}

{% yields changes_dom_subject .contains %}

Examples

Content

Find the first element containing some text

<ul>
  <li>apples</li>
  <li>oranges</li>
  <li>bananas</li>
</ul>
// yields <li>apples</li>
cy.contains('apples')

Find the input[type='submit'] by value

Get the form element and search in its descendants for the content "submit the form!"

<div id="main">
  <form>
    <div>
      <label>name</label>
      <input name="name" />
    </div>
    <div>
      <label>age</label>
      <input name="age" />
    </div>
    <input type="submit" value="submit the form!" />
  </form>
</div>
// yields input[type='submit'] element then clicks it
cy.get('form').contains('submit the form!').click()

Number

Find the first element containing a number

Even though the <span> is the deepest element that contains a "4", Cypress automatically yields <button> elements over spans because of its {% urlHash 'preferred element order' Preferences %}.

<button class="btn btn-primary" type="button">
  Messages <span class="badge">4</span>
</button>
// yields <button>
cy.contains(4)

Regular Expression

Find the first element with text matching the regular expression

<ul>
  <li>apples</li>
  <li>oranges</li>
  <li>bananas</li>
</ul>
// yields <li>bananas</li>
cy.contains(/^b\w+/)

Selector

Specify a selector to return a specific element

Technically the <html>, <body>, <ul>, and first <li> in the example below all contain "apples".

Normally Cypress would return the first <li> since that is the deepest element that contains "apples".

To override the element that is yielded we can pass 'ul' as the selector.

<html>
  <body>
    <ul>
      <li>apples</li>
      <li>oranges</li>
      <li>bananas</li>
    </ul>
  </body>
</html>
// yields <ul>...</ul>
cy.contains('ul', 'apples')

Keep the form as the subject

Here's an example that uses the selector to ensure that the <form> remains the {% url subject introduction-to-cypress#Subject-Management %} for future chaining.

<form>
  <div>
    <label>name</label>
    <input name="name" />
  </div>
  <button type="submit">Proceed</button>
</form>
cy.get('form')                  // yields <form>...</form>
  .contains('form', 'Proceed')  // yields <form>...</form>
  .submit()                     // yields <form>...</form>

Without the explicit selector the subject would change to be the <button>. Using the explicit selector ensures that chained commands will have the <form> as the subject.

Case Sensitivity

Here's an example using the matchCase option to ignore case sensitivity.

<div>Capital Sentence</div>
cy.get('div').contains('capital sentence') // fail
cy.get('div').contains('capital sentence', { matchCase: false }) // pass

Notes

Scopes

.contains() acts differently whether it's starting a series of commands or being chained off an existing series.

When starting a series of commands:

This queries the entire document for the content.

cy.contains('Log In')

When chained to an existing series of commands

This will query inside of the <#checkout-container> element.

cy.get('#checkout-container').contains('Buy Now')

Be wary of chaining multiple contains

Let's imagine a scenario where you click a button to delete a user and a dialog appears asking you to confirm this deletion.

// This doesn't work as intended
cy.contains('Delete User').click().contains('Yes, Delete!').click()

Because the second .contains() is chained off of a command that yielded the <button>, Cypress will look inside of the <button> for the new content.

In other words, Cypress will look inside of the <button> containing "Delete User" for the content: "Yes, Delete!", which is not what we intended.

What you want to do is call cy again, which automatically creates a new chain scoped to the document.

cy.contains('Delete User').click()
cy.contains('Yes, Delete!').click()

Leading, trailing, duplicate whitespaces aren't ignored in <pre> tag

Unlike other tags, <pre> doesn't ignore leading, trailing, or duplicate whitespaces as shown below:

<!--Code for test-->
<h2>Other tags</h2>
<p>           Hello,          World   !</p>

<h2>Pre tag</h2>
<pre>                 Hello,           World      !</pre>

Rendered result:

{% imgTag /img/api/contains/contains-pre-exception.png "The result of pre tag" %}

To reflect this behavior, Cypress also doesn't ignore them.

// test result for above code

cy.get('p').contains('Hello, World !') // pass
cy.get('p').contains('           Hello,          World   !') // fail

cy.get('pre').contains('Hello, World !') // fail
cy.get('pre').contains('                 Hello,           World      !') // pass

Single Element

Only the first matched element will be returned

<ul id="header">
  <li>Welcome, Jane Lane</li>
</ul>
<div id="main">
  <span>These users have 10 connections with Jane Lane</span>
  <ul>
    <li>Jamal</li>
    <li>Patricia</li>
  </ul>
</div>

The below example will return the <li> in the #header since that is the first element that contains the text "Jane Lane".

// yields #header li
cy.contains('Jane Lane')

If you wanted to select the <span> instead, you could narrow the elements yielded before the .contains().

// yields <span>
cy.get('#main').contains('Jane Lane')

Preferences

Element preference order

.contains() defaults to preferring elements higher in the tree when they are:

  • input[type='submit']
  • button
  • a
  • label

Cypress will ignore this element preference order if you pass a selector argument to .contains().

Favor of <button> over other deeper elements

Even though the <span> is the deepest element that contains "Search", Cypress yields <button> elements over spans.

<form>
  <button>
    <i class="fa fa-search"></i>
    <span>Search</span>
  </button>
</form>
// yields <button>
cy.contains('Search').children('i').should('have.class', 'fa-search')

Favor of <a> over other deeper elements

Even though the <span> is the deepest element that contains "Sign Out", Cypress yields anchor elements over spans.

<nav>
  <a href="/users">
    <span>Users</span>
  </a>
  <a href="/signout">
    <span>Sign Out</span>
  </a>
</nav>
// yields <a>
cy.get('nav').contains('Sign Out').should('have.attr', 'href', '/signout')

Favor of <label> over other deeper elements

Even though the <span> is the deepest element that contains "Age", Cypress yields <label> elements over <span>.

<form>
  <label>
    <span>Name:</span>
    <input name="name" />
  </label>
  <label>
    <span>Age:</span>
    <input name="age" />
  </label>
</form>
// yields label
cy.contains('Age').find('input').type('29')

Rules

Requirements {% helper_icon requirements %}

{% requirements dual_existence .contains %}

Assertions {% helper_icon assertions %}

{% assertions existence .contains %}

Timeouts {% helper_icon timeout %}

{% timeouts existence .contains %}

Command Log

Element contains text "New User"

cy.get('h1').contains('New User')

The commands above will display in the Command Log as:

{% imgTag /img/api/contains/find-el-that-contains-text.png "Command Log contains" %}

When clicking on the contains command within the command log, the console outputs the following:

{% imgTag /img/api/contains/see-elements-found-from-contains-in-console.png "console.log contains" %}

{% history %} {% url "4.0.0" changelog#4-0-0 %} | Added support for option matchCase. {% endhistory %}

See also

  • {% url cy.get() get %}
  • {% url .invoke() invoke %}
  • {% url .within() within %}
  • {% url "Retry-ability" retry-ability %}