Input element value

📺 Watch this recipe explained in Input Element Valueopen in new window.

Regular HTML elements with text

To get the text of an element, you invoke the text() method provided by jQuery.

<p id="name">Joe Smith</p>
// yields jQuery object
cy.get('#name')
  // calls the jQuery method "text()"
  .invoke('text')
  .should('equal', 'Joe Smith')

You can also use Chai-jQueryopen in new window assertion have.text to confirm the element's text content.

cy.get('#name').should('have.text', 'Joe Smith')

A text input

If you want to get a value from an input element (text or number), you need to invoke the jQuery method val()

<input
  type="text"
  name="firstName"
  placeholder="Enter your first name"
/>
// yields jQuery object
cy.get('[name=firstName]')
  // calls the jQuery method "val()"
  .invoke('val')
  // the value is an empty string at first
  .should('equal', '')
// enter the first name and confirm
cy.get('[name=firstName]').type('Anna')
cy.get('[name=firstName]').invoke('val').should('equal', 'Anna')

You can check a value of an input element using the built-in Chai-jQuery assertion "have.value".

cy.get('[name=firstName]').should('have.value', 'Anna')

A textarea

<textarea
  id="quote"
  placeholder="Enter your favorite quote"
></textarea>
const quote =
  'It was the best of times, it was the worst of times'
cy.get('#quote')
  // initially the textarea is empty
  .should('have.value', '')
  .type(quote)
  .should('have.value', quote)

A number input

<input
  type="number"
  name="quantity"
  placeholder="Enter the number of items"
/>
// yields jQuery object
cy.get('[name=quantity]')
  // calls the jQuery method "val()"
  .invoke('val')
  // the value is an empty string at first
  .should('equal', '')
// enter the first name and confirm
cy.get('[name=quantity]').type('42')
// note: even if the input element is numeric,
// the value "val()" yields is a string
cy.get('[name=quantity]').invoke('val').should('equal', '42')

You can check a value of an input element using the built-in Chai-jQuery assertion "have.value".

// compare as a string
cy.get('[name=quantity]').should('have.value', '42')
// Chai-jQuery assertion also casts a number automatically
cy.get('[name=quantity]').should('have.value', 42)

You can confirm the value is between two limits by using a should(callback)

cy.get('[name=quantity]')
  .invoke('val')
  .should((valueAsString) => {
    expect(Number(valueAsString)).to.be.within(40, 50)
  })

We don't have to convert the string value to a number ourselves. Numeric input elements have the valueAsNumber property which we can get using have.prop assertion or via prop('valueAsNumber') call

// yield the property "valueAsNumber"
cy.get('[name=quantity]')
  .should('have.prop', 'valueAsNumber')
  // yields the value
  .should('be.within', 40, 50)
// yield the property "valueAsNumber"
cy.get('[name=quantity]')
  .invoke('prop', 'valueAsNumber')
  .should('be.closeTo', 40, 3)

Nested element

To improve the retry-abilityopen in new window of your tests, do not split accessing the element into multiple querying commands (if possible).

<section id="nested">
  <form name="info">
    <input type="text" name="firstName" value="Joe" />
  </form>
</section>
// Might be ok, but might lead to flaky tests
// if the application re-renders the form
cy.get('#nested')
  .find('[name=info]')
  .find('[name=firstName]')
  .should('have.value', 'Joe')

Instead of using separate commands cy.get + cy.find to locate the element, merge the CSS selector into a single one:

// Recommended: merge the queries into one cy.get
cy.get('#nested [name=info] [name=firstName]').should(
  'have.value',
  'Joe',
)

Checkbox

Checkbox elements also have a value.

📺 Watch the checkbox value explained in the video Checkbox Input Element Valueopen in new window.

Default checkbox value

<label for="accept-terms">Accept terms</label>
<input type="checkbox" id="accept-terms" />
// by default the checkbox has value "on"
// even if unchecked
cy.get('#accept-terms')
  .should('have.value', 'on')
  .and('not.be.checked')
  .check()
  .should('have.value', 'on')
  .and('be.checked')

Custom checkbox value

<label for="accept-terms">Accept terms</label>
<input type="checkbox" id="accept-terms" value="accepted" />
cy.get('#accept-terms')
  .should('have.value', 'accepted')
  .and('not.be.checked')
  .check()
  .should('have.value', 'accepted')
  .and('be.checked')

Input value is set

Let's confirm that the text input element has the empty initial value and then sets some value. Maybe the application is loading the previously entered values, and there is a delay between the input appearing and the values set.

<input id="account-name" type="text" />
<script>
  setTimeout(() => {
    document.getElementById('account-name').value =
      'Default bank'
  }, 1000)
</script>

Let's confirm that the input element gets some value.

// initially the value is empty
cy.get('#account-name').should('have.value', '')
// at some point it will be a non-empty string
// both cy.get and cy.invoke are queries and retry
// until the assertion "not.equal" passes
cy.get('#account-name').invoke('val').should('not.equal', '')

Tip: if you are loading the input element's value, please disable the element and enable it after the value has been loaded. Otherwise, the user might be tempted to enter new value just to lose their work.

Input value is set and is stable

Imagine the input element shows several values before showing the "final" value that you want. Maybe it is flashing "loading..." initially. To check if the element's value goes unchanged for N milliseconds, use the cy.stable command from the cypress-mapopen in new window plugin.

<input id="account-name" type="text" value="..." />
<script>
  setTimeout(() => {
    document.getElementById('account-name').value = 'loading...'
  }, 500)

  setTimeout(() => {
    document.getElementById('account-name').value =
      'Default bank'
  }, 1000)
</script>
cy.get('#account-name').stable('value')
// let's confirm the value, we can set timeout to zero
// because the element's value has been set for some time
cy.get('#account-name', { timeout: 0 }).should(
  'have.value',
  'Default bank',
)