Let's get started with second part of Cypress basics. The first part of the blog can be found here.
In this blog, we will be going through CSS and XPath Locators, Types of Assertions in Cypress, and Folder Structure, Interacting with WebElements like Radio Buttons, Checkboxes, Dropdowns, Alerts.
Cypress E2E Web Automation:
CSS & XPath Locators: get() & xpath() methods:
Locators: CSS Selector, XPath Locators (supported with cypress XPath plugin)
CSS Selector in Cypress:
Locate the element and then identify the element using cy.get(locator)
tag id, tag class, tag attribute, tag class attribute→ tag is optional in these 4 combinations.
Check selector: SelectorsHub plugin (OR) ctrl+F
tag#id, tag.class, tag[attribute=’value’], tag.class[attribute=”value”]
Spec file: optional: const{describe} = require(“mocha”);
Every file: const cypress = require(“cypress”) (OR)
/// <reference types=”cypress”/> //can put in support/commands.js
cy.visit(“http://automationpractice.com/index.php”)
cy.get(“input#search_query_top”).type(“T-Shirts”) // tag input is optional here , id
cy.get(“[name=’submit_search’]”).click() // attribute
cy.get(“.lighter”).contains(“T-Shirts”) // class
Time travel can be seen switching between steps
When the spec file is modified, the test is run again automatically.
XPath Locators in Cypress:
To use XPath in Cypress: Search cypress plugins:
cypress-xpath plugin → npm install -D cypress --xpath
commands.js :add reference: /// <reference types=”cypress-xpath” />
e2e.js: require(‘cypress-xpath’) // applicable for all tests or individually in each spec file
cy.xpath(“//ul[@id=’homefeatured’]/li”).should(‘have.length’,7)
cy.xpath(“//ul[@id=’homefeatured’]”).xpath(“./li”).should(‘have.length’,7) // chained xpath
XPath: preceding, following, ancestor, sibling, child, parent, self, namespace, attribute …
Selenium WebDriver XPath axes: Child, Parent, Self, Ancestor, Ancestor-or-self, Descendant, Descendant-or-self, Following, Following-sibling, Preceding, Preceding-sibling, Attribute, Namespace axis.
Assertions: Types of Assertions: Implicit / Built-in assertions & Explicit Assertions
Keywords:: Implicit: should, and; explicit: expect (BDD Assertion), assert(TDD framework Assertion)
All assertions are derived from child library.
Implicit Assertions:
cy.url().should('include','orangehrm.com') // .url() get url
cy.url().should(‘eq’,’<full_url>’) , ‘contain’ similar to ‘include’
cy.url().should(...).should(...).should(...) → cy.url().should(...).and(...).and(...)
Negative assertions: ‘not.contain’
cy.title().should(...) // verify title
cy.get('.orangehrm-login-branding > img').should('be.visible') // .should(‘exist’)
Capture number of links on web page: cy.xpath("//a").should(‘have.length’,’5’)
cy.get("input[placeholder='Username']").type("Admin") // provide value into input box
cy.get("input[placeholder='Username']").should('have.value','Admin') // value check
Assertions for should: eq, contain, include, not.eq, not.contain, not.include, exist, have.length, have.value
Explicit assertions:
expect: BDD Assertions:
let expName = "xyz";
cy.get(".oxd-userdropdown-name").then( (x) =>{ // x stores element
let actName = x.text()
expect(actName).to.equal(expName)
expect(actName).to.not.equal(expName) // BDD assertions use expect
}
assert: TDD assertions
assert.equal(actName, expName) ;
assert.notEqual(actName, expName);
Folder Structure - IntelliSense Auto Suggestions:
The new version of Cypress has folder structure different from previous versions.
commnands.js: The following type of commands help to enable IntelliSense - to get list of available commands automatically - Intelligence Automated Suggestions. Instead of adding the commands in every Spec file, we can add in commands.js file once.
/// <reference types="Cypress" /> // for cypress
/// <reference types="cypress-xpath" /> // for xpath
e2e.js: had plugin information, contains commands.
cypress.config.js:
const {defineConfig} = require("cypress"); // for cypress commands to work
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config){
},
},
});
similarly we can also add in cypress.config.js:
const {xpathConfig} = require('cypress-xpath'); // for XPath, define function xpathConfig
Interacting with Elements | Validating Elements | Assertions:
Radio Buttons & Checkboxes:
RadioButton_CheckBox.cy.js:
describe("Check UI Elements", ()=>{
it("Checking Radio Buttons", ()=> {
cy.visit("https://itera-qa.azurewebsites.net/home/automation")
cy.get("input#male").should('be.visible') // visibility
cy.get("input#female").should('be.visible')
// selecting radio buttons
// check() selects element
cy.get("input#male").check().should('be.checked')
// only male or female should be selected, not both
cy.get("input#female").should('not.be.checked')
})
it("Checking Check Boxes", ()=>{
cy.visit("https://itera-qa.azurewebsites.net/home/automation")
// visibility of checkbox
cy.get("input#monday").should('be.visible')
// select single checkbox
cy.get("input#monday").check().should('be.checked')
// unselect checkbox
cy.get("input#monday").uncheck().should('not.be.checked')
})
})
be.visible: Here, "be" indicates behavior of web element.
When the test case is run, we can time travel between steps hovering over on the left pane, on each step of the test case. We can see this from below screenshot.
//select all check boxes
cy.get("input.form-check-input[type='checkbox']").check().should('be.checked')
// deselect all checkboxes
cy.get("input.form-check-input[type='checkbox']").uncheck().should('not.be.checked')
//select first check box
cy.get("input.form-check-input[type='checkbox']").first().check().should('be.checked')
// select last checkbox
cy.get("input.form-check-input[type='checkbox']").last().check().should('be.checked')
DropDowns:
// for those with select tag
cy.get('#zcf_address_country').select('Italy').should('have.value','Italy')
//boostrap framework drop downs, without select tag in HTML
cy.get('#select2-billing_country-container').click()
//enter in input box
cy.get('.select2-search__field').type('Italy').type('{enter}')
//assertion on drop box where value is selected.
cy.get('#select2-billing_country-container').should('have.text', 'Italy')
// Autosuggested Dropdown automation (static in nature)
it('Auto Suggest Dropdown', function(){
cy.get('#searchInput').type('Delhi')
// gets list of items and check for value in each of them
cy.get('.suggestion-title').contains('Delhi University').click()
})
// dynamic dropdown
it('Dynamic Dropdown', ()=>{
cy.visit("https://www.google.com/")
cy.get("input[name='q']").type('cypress automation')
cy.wait(3000)
cy.get('div.wM6W7d>span').should('have.length',12)
cy.get('div.wM6W7d>span').each( ($el, index, $list)=>{
// find the element
if($el.text() == 'cypress automation tool'){
cy.wrap($el).click()
}
})
cy.get("input[name='q']").should('have.value', 'cypress automation tool') // check if selected in input box
})
Alerts:
Cypress will automatically close alerts. But to do validation, we have to do it programmatically using events.
it.only executes only that test case and not other test cases in the describe test suite.
Alerts windows are automatically closed by Cypress itself. But, if we want to do some validations on alert window, get control on it by raising certain Event, and then control the Alert. https://docs.cypress.io/api/events/catalog-of-events has more events to be raised to control Alerts, for Validation.
describe('Alerts', ()=>{
// 1. JavaScript Alert: It will have some text and an 'OK' button.
it('JS Alert', ()=>{
cy.visit('http://the-internet.herokuapp.com/javascript_alerts')
cy.get("button[onclick='jsAlert()']").click();
// validating text on Alert window
cy.on('window:alert', (t)=>{
expect(t).to.contains('I am a JS Alert');
})
// alert window automatically closed by cypress
// after closing, validate alert window
cy.get("#result").should('have.text','You successfully clicked an alert')
})
// 2. JavaScript Confirm Alert: It will have some text with 'OK' and 'Cancel' buttons.
it('JS Confirm', ()=>{
cy.visit('http://the-internet.herokuapp.com/javascript_alerts')
// default cypress closes with OK automatically.
// to close alert clicking Cancel button:
cy.get("button[onclick='jsConfirm()']").click();
cy.on('window:confirm', (t)=>{
expect(t).to.contains('I am a JS Confirm');
})
// true here means cypress closes using default ok
// to click using cancel use false
cy.on('window:confirm',()=> false);
// alert window automatically closed by cypress
// after closing, validate alert window
cy.get('#result').should('have.text','You clicked: Cancel')
})
// 3. JavaScript Prompt Alert: It will have some text with a text box for user input along with 'OK' button.
// provide text and OK(1event) (OR) provide text and click Cancel (2events)
// before opening alert, we have to pass text in input box
// cypress closes by default clicking ok button
it('JS prompt alert', ()=>{
cy.visit('http://the-internet.herokuapp.com/javascript_alerts')
cy.window().then( (win)=>{
cy.stub(win,'prompt').returns('welcome');
})
cy.get("button[onclick='jsPrompt()']").click();
//validate for ok button automatically closed by cypress
//cy.get("#result").should('have.text', 'You entered: welcome');
cy.on('window:prompt',()=>false);
// validate for cancel button
cy.get("#result").should('have.text', 'You entered: welcome');
})
// 4. Authenticated Alert
it('Authenticated Alert', ()=>{
// pass username password, as parameters in visit method, to skip alert window
cy.visit('http://the-internet.herokuapp.com/basic_auth', {auth: {username:"admin", password:"admin"}});
cy.get("div[class='example'] p").should('have.contain',"Congratulations")
// pass username password, along with URL
cy.visit('http://admin:admin@the-internet.herokuapp.com/basic_auth');
cy.get("div[class='example'] p").should('have.contain',"Congratulations")
})
})
Hope you enjoyed learning Cypress, using CSS and XPath Locators, Types of Assertions in Cypress, and Folder Structure, Interacting with Web Elements like Radio Buttons, Checkboxes, Dropdowns, Alerts.