Actions
Examples of actions being performed on DOM elements in Cypress, for a full reference of commands, go to docs.cypress.io
.type()
To type into a DOM element, use the .type()
command.
<form>
<div class="form-group">
<label for="name1">Name</label>
<input
type="text"
class="form-control"
id="name1"
placeholder="Joe Bravo"
/>
</div>
<div class="form-group">
<label for="email1">Email address</label>
<input
type="email"
class="form-control action-email"
id="email1"
placeholder="Email"
/>
</div>
<div class="form-group">
<label>Disabled Textarea</label>
<textarea
class="form-control action-disabled"
disabled="disabled"
></textarea>
</div>
</form>
cy.get('.action-email')
.type('[email protected]')
.should('have.value', '[email protected]')
// .type() with special character sequences
.type('{leftarrow}{rightarrow}{uparrow}{downarrow}')
.type('{del}{selectall}{backspace}')
// .type() with key modifiers
.type('{alt}{option}') //these are equivalent
.type('{ctrl}{control}') //these are equivalent
.type('{meta}{command}{cmd}') //these are equivalent
.type('{shift}')
// Delay each keypress by 0.1 sec
.type('[email protected]', { delay: 100 })
.should('have.value', '[email protected]')
cy.get('.action-disabled')
// Ignore error checking prior to type
// like whether the input is visible or disabled
.type('disabled error checking', { force: true })
.should('have.value', 'disabled error checking')
You can clear the field before typing
cy.get('#name1')
.type('Joe')
// use "have.value" assertion to check the input element's value
.should('have.value', 'Joe')
.clear()
.type('Джо Браво')
.should('have.value', 'Джо Браво')
.focus()
To focus on a DOM element, use the .focus()
command.
<form>
<div class="form-group">
<label for="password1">Password</label>
<input
type="password"
class="form-control action-focus"
id="password1"
placeholder="Password"
/>
</div>
</form>
<script>
// listen to focus to demonstrate logic on focus command
$('.action-focus').on('focus', function (e) {
$(e.currentTarget).addClass('focus')
$(e.currentTarget).prev().css('color', 'orange')
})
</script>
cy.get('.action-focus')
.focus()
.should('have.class', 'focus')
.prev()
.should('have.attr', 'style', 'color: orange;')
.blur()
To blur on a DOM element, use the .blur()
command.
<form>
<div class="form-group">
<label for="fullName1">Full Name</label>
<input
type="text"
class="form-control action-blur"
id="fullName1"
placeholder="Enter your name"
/>
</div>
</form>
<script>
// listen to blur to demonstrate logic on blur command
$('.action-blur').on('blur', function (e) {
$(e.currentTarget).addClass('error')
$(e.currentTarget).prev().css('color', 'red')
})
</script>
cy.get('.action-blur')
.type('About to blur')
.blur()
.should('have.class', 'error')
.prev()
.should('have.attr', 'style', 'color: red;')
.clear()
To clear on a DOM element, use the .clear()
command.
<form>
<div class="form-group">
<label for="description">Describe:</label>
<input
type="text"
class="form-control action-clear"
id="description"
/>
</div>
</form>
cy.get('.action-clear')
.type('Clear this text')
.should('have.value', 'Clear this text')
.clear()
.should('have.value', '')
.submit()
To submit a form, use the cy.submit()
command.
<form class="action-form">
<div class="form-group">
<label for="couponCode1" val="HALFOFF">Coupon Code</label>
<input type="text" class="form-control" id="couponCode1" />
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<script>
$('.action-form').on('submit', function (e) {
e.preventDefault()
const text = document.createElement('p')
text.innerText = 'Your form has been submitted!'
$(text).insertAfter(e.currentTarget).css('color', '#20B520')
})
</script>
cy.get('.action-form').find('[type="text"]').type('HALFOFF')
cy.get('.action-form')
.submit()
.next()
.should('contain', 'Your form has been submitted!')
.and('be.visible')
.click()
To click a DOM element, use the .click()
command.
<button
type="button"
class="btn btn-lg btn-danger action-btn"
data-toggle="popover"
title="Popover"
data-placement="top"
data-content="This popover shows up on click"
>
Click to toggle popover
</button>
<script>
$('[data-toggle=popover]').popover()
</script>
cy.get('.action-btn')
.click()
// when popover appears it adds an attribute
.should('have.attr', 'aria-describedby')
// close it
cy.get('.action-btn')
.click()
.should('not.have.attr', 'aria-describedby')
Click on canvas
<h6>Canvas to Illustrate Click Positions</h6>
<canvas width="250" height="250" id="action-canvas"></canvas>
<script>
// place variable declarations into a closure
// to avoid accidental name clashes
;(function () {
// begin: draw dots on canvas on mouse click ---
const canvas = document.getElementById('action-canvas')
const context = canvas.getContext('2d')
$('#action-canvas').on('click', function (e) {
draw(e)
})
function draw(e) {
const pos = getMousePos(canvas, e)
const posx = pos.x
const posy = pos.y
context.fillStyle = 'red'
context.beginPath()
context.arc(posx, posy, 5, 0, 2 * Math.PI)
context.fill()
}
function getMousePos(canvas, evt) {
const rect = canvas.getBoundingClientRect()
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top,
}
}
})()
</script>
// clicking in the center of the element is the default
cy.get('#action-canvas').click()
cy.get('#action-canvas').click('topLeft')
cy.get('#action-canvas').click('top')
cy.get('#action-canvas').click('topRight')
cy.get('#action-canvas').click('left')
cy.get('#action-canvas').click('right')
cy.get('#action-canvas').click('bottomLeft')
cy.get('#action-canvas').click('bottom')
cy.get('#action-canvas').click('bottomRight')
// .click() accepts a an x and y coordinate
// that controls where the click occurs :)
cy.get('#action-canvas')
.click(80, 75)
.click(170, 75)
.click(80, 165)
.click(100, 185)
.click(125, 190)
.click(150, 185)
.click(170, 165)
Click on multiple elements
You can click on multiple elements by passing an option multiple: true
<div class="action-labels">
<span
class="badge badge-pill badge-primary label"
data-toggle="popover"
data-placement="bottom"
data-content="clicked"
>click me</span
>
<span
class="badge badge-pill badge-primary label"
data-toggle="popover"
data-placement="bottom"
data-content="clicked"
>and me</span
>
<span
class="badge badge-pill badge-primary label"
data-toggle="popover"
data-placement="bottom"
data-content="clicked"
>and me</span
>
<span
class="badge badge-pill badge-primary label"
data-toggle="popover"
data-placement="bottom"
data-content="clicked"
>and me</span
>
<span
class="badge badge-pill badge-primary label"
data-toggle="popover"
data-placement="bottom"
data-content="clicked"
>and me</span
>
<span
class="badge badge-pill badge-primary label"
data-toggle="popover"
data-placement="bottom"
data-content="clicked"
>and me</span
>
</div>
<script>
$('[data-toggle=popover]').popover()
</script>
// click multiple elements by passing multiple: true
cy.get('.action-labels>.label').click({ multiple: true })
// confirm the badges got popovers
cy.get('[data-toggle=popover][aria-describedby]').should(
'have.length',
6,
)
Click on disabled element
You can override Cypress' built-in checks and click on the disable element.
<style>
.action-opacity {
position: relative;
margin-top: 50px;
}
.action-opacity .opacity-cover {
text-align: center;
line-height: 50px;
color: #333;
font-weight: bold;
font-size: 25px;
position: absolute;
top: -5px;
left: -5px;
width: 235px;
height: 60px;
background-color: red;
opacity: 0.7;
box-shadow: 0 2px 7px #000;
}
</style>
<div class="action-opacity">
<button
type="button"
class="btn btn-lg btn-primary"
data-toggle="popover"
data-placement="left"
data-content="This popover shows up because we forced the click on the button"
>
I'm being covered
</button>
<div class="opacity-cover"></div>
</div>
<script>
$('[data-toggle=popover]').popover()
</script>
// Ignore error checking prior to clicking
cy.get('.action-opacity>.btn').click({ force: true })
Click waits for visible element
The element will need to be visible and actionable for .click
to work. If the element is invisible for example, the .click
retries until the element becomes visible or the command times out.
<button id="invisible-at-first" style="display:none">
Click me
</button>
<script>
setTimeout(function () {
document.getElementById('invisible-at-first').style.display =
'block'
}, 500)
</script>
cy.get('#invisible-at-first').click({ timeout: 1000 })
To be explicit about visibility, you might insert an assertion before the .click
command.
<button id="invisible-at-first2" style="display:none">
Click me
</button>
<script>
setTimeout(function () {
document.getElementById(
'invisible-at-first2',
).style.display = 'block'
}, 500)
</script>
cy.get('#invisible-at-first2')
.should('be.visible')
.click({ timeout: 50 })
.dblclick()
To double click a DOM element, use the .dblclick()
command.
<form>
<div class="form-group">
<div class="action-div">Double click to edit</div>
<input
type="text"
class="action-input-hidden hidden form-control"
value="Double click to edit"
/>
</div>
</form>
<script>
// listen to dblclick to demonstrate logic on double click command
$('.action-div').on('dblclick', function (e) {
$('.action-input-hidden').removeClass('hidden').focus()
$(e.currentTarget).addClass('hidden')
})
</script>
cy.get('.action-div').dblclick().should('not.be.visible')
cy.get('.action-input-hidden').should('be.visible')
.rightclick()
To right click a DOM element, use the .rightclick()
command.
<form>
<div class="form-group">
<div class="rightclick-action-div">Right click to edit</div>
<input
type="text"
class="rightclick-action-input-hidden hidden form-control"
value="Right click to edit"
/>
</div>
</form>
<script>
// listen to contextmenu to demonstrate logic on right click command
$('.rightclick-action-div').on('contextmenu', function (e) {
$('.rightclick-action-input-hidden')
.removeClass('hidden')
.focus()
$(e.currentTarget).addClass('hidden')
})
</script>
cy.get('.rightclick-action-div')
.rightclick()
.should('not.be.visible')
cy.get('.rightclick-action-input-hidden').should('be.visible')
.check()
To check a checkbox or radio, use the .check()
command.
<div class="action-checkboxes">
<div class="checkbox">
<label>
<input type="checkbox" value="checkbox1" />
Checkbox one has value "checkbox1"
</label>
</div>
<div class="checkbox disabled">
<label>
<input type="checkbox" value="checkbox2" disabled />
Checkbox two is disabled
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox" value="checkbox3" />
Checkbox three has value "checkbox3"
</label>
</div>
</div>
<hr />
<div class="action-multiple-checkboxes">
<div class="checkbox">
<label>
<input type="checkbox" value="checkbox1" />
Checkbox one has value "checkbox1"
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox" value="checkbox2" />
Checkbox two has value "checkbox2"
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox" value="checkbox3" />
Checkbox three has value "checkbox3"
</label>
</div>
</div>
<hr />
<div class="action-radios">
<div class="radio">
<label>
<input
type="radio"
name="optionsRadios"
id="optionsRadios1"
value="radio1"
/>
Radio one has value "radio1"
</label>
</div>
<div class="radio">
<label>
<input
type="radio"
name="optionsRadios"
id="optionsRadios2"
value="radio2"
/>
Radio two has value "radio2". When checked, it will uncheck
Radio one.
</label>
</div>
<div class="radio disabled">
<label>
<input
type="radio"
name="optionsRadios"
id="optionsRadios3"
value="radio3"
disabled
/>
Radio three is disabled
</label>
</div>
</div>
// By default, .check() will check all
// matching checkbox or radio elements in succession, one after another
cy.get('.action-checkboxes [type="checkbox"]')
.not('[disabled]')
.check()
.should('be.checked')
cy.get('.action-radios [type="radio"]')
.not('[disabled]')
.check()
.should('be.checked')
// .check() accepts a value argument
cy.get('.action-radios [type="radio"]')
.check('radio1')
.should('be.checked')
// .check() accepts an array of values
cy.get('.action-multiple-checkboxes [type="checkbox"]')
.check(['checkbox1', 'checkbox2'])
.should('be.checked')
// Ignore error checking prior to checking
cy.get('.action-checkboxes [disabled]')
.check({ force: true })
.should('be.checked')
cy.get('.action-radios [type="radio"]')
.check('radio3', { force: true })
.should('be.checked')
Tip: Looking to check indeterminate checkboxes? Check out the example repo bahmutov/indeterminate-checkboxes.
The input is already checked
If the input element is already checked, the .check()
command continues
<div>
<input type="checkbox" id="empty" />
Unchecked at first
</div>
<div>
<input type="checkbox" id="filled" checked />
Already checked
</div>
// checks the input element
cy.get('#empty').check().should('be.checked')
// cy.check() does not nothing
// because the input element is checked already
cy.get('#filled').check().should('be.checked')
Get checked option
You can get the currently checked option using the jQuery's :checked selector.
<form id="pick-fruit">
<div>
<input
type="radio"
name="fruit"
value="orange"
id="orange"
/>
<label for="orange">orange</label>
</div>
<div>
<input
type="radio"
name="fruit"
value="apple"
id="apple"
checked="checked"
/>
<label for="apple">apple</label>
</div>
<div>
<input
type="radio"
name="fruit"
value="banana"
id="banana"
/>
<label for="banana">banana</label>
</div>
<div id="log"></div>
</form>
cy.get('#pick-fruit :checked')
.should('be.checked')
.and('have.value', 'apple')
The same selector works for checkbox elements
<form id="newsletter">
<h3>Newsletter frequency</h3>
<p>
<input
type="checkbox"
name="newsletter"
value="Hourly"
checked="checked"
title="hourly"
/>
<input
type="checkbox"
name="newsletter"
value="Daily"
title="daily"
/>
<input
type="checkbox"
name="newsletter"
value="Weekly"
title="weekly"
/>
<input
type="checkbox"
name="newsletter"
value="Monthly"
title="monthly"
checked
/>
<input
type="checkbox"
name="newsletter"
value="Yearly"
title="yearly"
/>
</p>
</form>
cy.get('#newsletter :checked')
.should('have.length', 2)
.first()
.should('have.value', 'Hourly')
.uncheck()
To uncheck a checkbox or radio, use the .uncheck()
command.
<div class="action-check">
<div class="checkbox">
<label>
<input type="checkbox" value="checkbox1" checked />
Checkbox one has value "checkbox1"
</label>
</div>
<div class="checkbox disabled">
<label>
<input
type="checkbox"
value="checkbox2"
disabled
checked
/>
Checkbox two is disabled
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox" value="checkbox3" checked />
Checkbox three has value "checkbox3"
</label>
</div>
</div>
// By default, .uncheck() will uncheck all matching
// checkbox elements in succession, one after another
cy.get('.action-check [type="checkbox"]')
.not('[disabled]')
.uncheck()
.should('not.be.checked')
// .uncheck() accepts a value argument
cy.get('.action-check [type="checkbox"]')
.check('checkbox1')
.uncheck('checkbox1')
.should('not.be.checked')
// .uncheck() accepts an array of values
cy.get('.action-check [type="checkbox"]')
.check(['checkbox1', 'checkbox3'])
.uncheck(['checkbox1', 'checkbox3'])
.should('not.be.checked')
// Ignore error checking prior to unchecking
cy.get('.action-check [disabled]')
.uncheck({ force: true })
.should('not.be.checked')
.select()
To select an option in a select, use the .select()
command.
<form>
<select class="form-control action-select">
<option>--Select a fruit--</option>
<option value="fr-apples">apples</option>
<option value="fr-oranges">oranges</option>
<option value="fr-bananas">bananas</option>
</select>
<select
class="form-control action-select-multiple"
multiple="true"
>
<option value="fr-apples">apples</option>
<option value="fr-oranges">oranges</option>
<option value="fr-bananas">bananas</option>
</select>
</form>
// at first, no option should be selected
cy.get('.action-select').should(
'have.value',
'--Select a fruit--',
)
// Select option(s) with matching text content
cy.get('.action-select').select('apples')
// confirm the apples were selected
// note that each value starts with "fr-" in our HTML
cy.get('.action-select').should('have.value', 'fr-apples')
cy.get('.action-select-multiple')
.select(['apples', 'oranges', 'bananas'])
// when getting multiple values, invoke "val" method first
.invoke('val')
// because we are comparing arrays, we need to use "deep.equal" assertion
.should('deep.equal', [
'fr-apples',
'fr-oranges',
'fr-bananas',
])
// Select option(s) with matching value
cy.get('.action-select')
.select('fr-bananas')
// can attach an assertion right away to the element
.should('have.value', 'fr-bananas')
cy.get('.action-select-multiple')
.select(['fr-apples', 'fr-oranges', 'fr-bananas'])
.invoke('val')
// because we are comparing arrays, we need to use "deep.equal" assertion
.should('deep.equal', [
'fr-apples',
'fr-oranges',
'fr-bananas',
])
// assert the selected values include oranges
cy.get('.action-select-multiple')
.invoke('val')
.should('include', 'fr-oranges')
You can select an option by index.
// select the very first option (the index starts at zero)
cy.get('.action-select')
.select(0)
.should('have.value', '--Select a fruit--')
// select the apple option, which is at index 1
.select(1)
.should('have.value', 'fr-apples')
Tip: selecting an option by index lets you pick one of the duplicate options, see the select from an optgroup recipe.
Select multiple options by index
cy.get('.action-select-multiple')
.select([1, 2])
.invoke('val')
// because we are comparing arrays, we need to use "deep.equal" assertion
.should('deep.equal', ['fr-oranges', 'fr-bananas'])
See also the recipes Selected value and select from an optgroup.
.scrollIntoView()
To scroll an element into view, use the .scrollintoview()
command.
<div
id="scroll-horizontal"
style="height: 300px; width: 300px; overflow: auto;"
>
<div style="width: 1000px; position: relative;">
Horizontal Scroll
<button
class="btn btn-danger"
style="position: absolute; top: 0; left: 500px;"
>
I'm Here
</button>
</div>
</div>
<div
id="scroll-vertical"
style="height: 300px; width: 300px; overflow: auto;"
>
<div style="height: 1000px; position: relative;">
Vertical Scroll
<button
class="btn btn-danger"
style="position: absolute; top: 500px; left: 0"
>
I'm Here
</button>
</div>
</div>
<div
id="scroll-both"
style="height: 300px; width: 300px; overflow: auto;"
>
<div
style="width: 1000px; height: 1000px; position: relative;"
>
Both Scroll
<button
class="btn btn-danger"
style="position: absolute; top: 500px; left: 500px"
>
I'm Here
</button>
</div>
</div>
// https://on.cypress.io/scrollintoview
// normally all of these buttons are hidden,
// because they're not within
// the viewable area of their parent
// (we need to scroll to see them)
cy.get('#scroll-horizontal button').should('not.be.visible')
// scroll the button into view, as if the user had scrolled
cy.get('#scroll-horizontal button')
.scrollIntoView()
.should('be.visible')
cy.get('#scroll-vertical button').should('not.be.visible')
// Cypress handles the scroll direction needed
cy.get('#scroll-vertical button')
.scrollIntoView()
.should('be.visible')
cy.get('#scroll-both button').should('not.be.visible')
// Cypress knows to scroll to the right and down
cy.get('#scroll-both button')
.scrollIntoView()
.should('be.visible')
.scrollTo()
To scroll the window or a scrollable element to a specific position, use the cy.scrollTo()
command.
<div id="scrollable-horizontal" style="height: 150px; width: 300px; overflow: auto;">
<div style="width: 3000px">
Horizontal Scroll
<ul>
<li class="square100" />
<li class="square100" />
<li class="square100" />
<li class="square100" />
<li class="square100" />
<li class="square100" />
<li class="square100" />
<li class="square100" />
<li class="square100" />
<li class="square100" />
<li class="square100" />
<li class="square100" />
<li class="square100" />
<li class="square100" />
<li class="square100" />
</ul>
</div>
</div>
<div id="scrollable-vertical" style="height: 150px; width: 300px; overflow: auto;">
<div style='height: 1000px'>
Vertical Scroll
<ul>
<li class="square100" />
<li class="square100" />
<li class="square100" />
<li class="square100" />
<li class="square100" />
<li class="square100" />
<li class="square100" />
<li class="square100" />
</ul>
</div>
</div>
<div id="scrollable-both" style="height: 150px; width: 300px; overflow: auto;">
<div style="width: 1000px; height: 1000px; position: relative;">
Both Scroll
<button class="btn btn-danger" style="position: absolute; top: 500px; left: 500px">I'm Here</button>
</div>
</div>
</div>
// if you chain .scrollTo() off of cy, we will
// scroll the entire window
cy.scrollTo('bottom')
cy.get('#scrollable-horizontal').scrollTo('right', {
duration: 1500,
})
// or you can scroll to a specific coordinate:
// (x axis, y axis) in pixels
cy.get('#scrollable-vertical').scrollTo(250, 250)
// or you can scroll to a specific percentage
// of the (width, height) of the element
cy.get('#scrollable-both').scrollTo('75%', '25%')
// control the easing of the scroll (default is 'swing')
cy.get('#scrollable-vertical').scrollTo('center', {
easing: 'linear',
})
// control the duration of the scroll (in ms)
cy.get('#scrollable-both').scrollTo('center', { duration: 2000 })
.trigger()
To trigger an event on a DOM element, use the .trigger()
command.
<form>
<fieldset>
<label for="range-input">Range Input</label>
<input
class="trigger-input-range"
name="range-input"
type="range"
value="0"
/>
<p>0</p>
</fieldset>
</form>
<script>
// listen to input range for trigger command
$('.trigger-input-range').on('change', function (e) {
const $range = $(e.target)
$range.next('p').text($range.val())
})
</script>
cy.get('.trigger-input-range')
.invoke('val', 25)
.trigger('change')
.get('input[type=range]')
.siblings('p')
.should('have.text', '25')
📺 Recommended: watch the videos Testing React Input With Type Range By Dispatching Events and Trigger React Slider OnChange Event.
Trigger a click event on a disabled button
<div id="click-disabled">
<button id="a-button" disabled>Click me</button>
<div id="result"></div>
</div>
<script>
document
.querySelector('#click-disabled #a-button')
.addEventListener('click', function () {
document.querySelector(
'#click-disabled #result',
).innerText = 'Clicked'
})
</script>
We cannot click on a disabled button using cy.click
command. We can if we remove the "disabled" attribute first.
cy.get('#click-disabled #a-button')
.invoke('removeAttr', 'disabled')
.trigger('click')
cy.contains('#click-disabled #result', 'Clicked')
Using jQuery click
In this example, the application removes the button, just as the Test Runner is about to click it, causing the "Element is detached from the DOM" error. We get around the built-in cy.click
checks using the jQuery method to click on the button.
<div id="jquery-click">
<button id="a-button">Click me</button>
<div id="result"></div>
</div>
<script>
document
.querySelector('#jquery-click #a-button')
.addEventListener('click', function () {
document.querySelector('#jquery-click #result').innerText =
'Clicked'
})
setTimeout(function removeButton() {
const button = document.querySelector(
'#jquery-click #a-button',
)
button.parentNode.removeChild(button)
}, 1000)
</script>
cy.get('#jquery-click #a-button')
.wait(1000)
// cy.click command has built-in checks
// and will throw an error "element detached from DOM"
.then(($button) => {
// we avoid the checks and the error
// by using the jQuery click method
// https://api.jquery.com/click/
$button.click()
})
cy.contains('#jquery-click #result', 'Clicked')
Watch the video Fight Element Detached From DOM Error Using jQuery Click.