Migrating from Protractor to Cypress

Migrating from Protractor to Cypress? This is what you should know!

The Angular team has announced that they would cease development for protractor with Angular version 15 by end of 2022. So, checking out amongst the open-source alternatives, the closest watch is on Cypress. Cypress is a JavaScript-based front-end automation tool and is being adopted rapidly due to the following three main reasons:

    1. Simple Setup: Cypress does not need any configuration as the dependencies and libraries are already in-built.
    2. Faster Test Execution: Cypress has in-built wait abilities that make the script automatically wait for the next step to execute. With no implicit or explicit waits added, the test execution is faster.
    3. Debugging Abilities: Time travel feature takes the snapshot of the script execution which helps in debugging the script.

Protractor and Cypress both work perfectly well for JS based front end UI testing. While migrating your protractor Scripts to Cypress, you can start with simple syntax migrations as mentioned below:

Action Protractor Cypress
Launch URL browser.get(‘Url’) cy.visit(‘url’)
Backward Navigation browser.navigate().back() cy.go(‘back’)
Forward Navigation browser.navigate().forward() cy.go(‘forward’)
Click element element(locator).click() cy.get(locator).click()
Type in an input field element(locator).sendKeys(‘value’) cy.get(locator).type(‘value’)

Next, we illustrate code snippets of a few areas in terms of Protractor scripts and their equivalent Cypress code below:

1. Handling errors/exceptions

Cypress has inbuilt error handling capabilities, which avoids the usage of try-catch blocks from protractor. Here is an example:

Protractor Cypress
try { var ele = element(by.xpath(“//div[@title=’button’]”));
ele.getText();
}
catch(e) {
console.log(e);
}
const element = cy.xpath(“//div[@title=’button ‘]”).should(‘be.exist’);
.catch((e) => {
ele.getText();
})

2. Handling customized assertions

We can merge assertion to a single statement that could contain both the object and the assertion to be verified, which makes assertions simple via cypress. Here is an example:

Protractor Cypress
expect(element(by.tagName(‘form’)).element
(by.tagName(‘input’)).getAttribute(‘class’))
.not.toContain(‘disabled’)
cy.get(‘form’).find(‘input’).should
(‘not.have.class’, ‘disabled’)

3. Promises

Cypress has an inbuilt fully featured promise library to handle promises. Here is an example:

Protractor Cypress
element(by.css(‘input[name=’q’]’)).getAttribute(“title”)
.then(function(tooltip){expect(tooltip).toBe(“Search”, “tooltip is not ‘Search'”) })
cy.get(”input[name=’q’]’).then(($button) => {return new Cypress.Promise((resolve, reject) => { except($button).should(‘eq’, ‘Search’)

4. Customized loops

Cypress supports ‘each’ function to iterate an array/object like structure, instead of using looping statements. For example,

Protractor Cypress
var ele=element(by.tagName(‘li’)).count()expect
(ele.count()).tobe(3);for(int i=0; i<=count;i++)
{var elementText = ele.get(i).getText()return elementText}
cy.get(‘li’).should(‘have.length’, 3).each(($item, index, $list) => {return $item.text()})

5. File upload

Cypress has an inbuilt command ‘attachfile’, specifically capable of handling file upload. Here is an example:

Protractor Cypress
element(by.css(‘input[type=”file”]’)).sendKeys
(filepath);element(by.id(‘uploadButton’)).click();
cy.get(‘input[type=”file”]’).attachFile(filepath)
cy.get(‘#uploadButton’).click()

6. Read data from json file

Cypress has inbuilt file handling capabilities, which helps in avoiding the usage of any external plugins/packages as in protractor. For example:

Protractor Cypress
const fs = require(‘fs’);let rawdata = fs.readFileSync(‘D:Protractor Demo.json’);let web = JSON.parse(rawdata);let Value = web[“website”] cy const Value = cy.readFile(‘D:ProtractorDemo.json’).its(‘website’)

7. Key events

We can trigger the key events using direct command ‘type’ in cypress instead of triggering the API function keys in protractor. For example:

Protractor Cypress
element(by.css(“input[name=’E’]”).sendKeys
(“Automation”)browser.actions().sendKeys
(protractor.Key.BACK_SPACE).perform();
cy.get(“input[name=’E’]”).type(‘Automation’)
cy.get(“input[name=’E’]”)).type(“{backspace}”)

8. Key events

Cypress has an inbuilt method to perform drag and drop operations like in protractor. Cypress, using the JQuery method is used to calculate the coordinates of the DOM element. For example:

Protractor Cypress
1. Using dragAndDrop method -source = element
(by.id(“draggable”));target = element(by.id(“droppable”));
browser.actions().dragAndDrop(source.getWebElement(),
target.getWebElement()).perform();
2. Using dragAndDrop method and coordinates -browser.actions().dragAndDrop(source.getWebElement(),
{x: 40, y: 300}).perform();
3. Using mouse action class -rowser.actions().mouseDown
(source.getWebElement()).mouseMove(source.get
WebElement(),{x: 120, y: 360}).mouseUp().perform();
1. Using drag method -cy.get(‘#draggable’)
.drag(‘#droppable’)
2. Using Co-ordinates -cy.get(‘[id=”droppable”]’).then((targetElms)=>
{ const targetRect = targetElms[0].getBounding
ClientRect()let targetCX = targetRect.left + target
Rect.width/2let targetCY = targetRect.top + targetRect.height/2cy.get(‘[id=”draggable”]’)
.then((sourceElms)=>{ const sourceRect = sourceElms[0].getBoundingClientRect()
let sourceCX = sourceRect.left + sourceRect.
width/2let sourceCY = sourceRect.top + sourceRect.height/2cy.get(‘[id=”draggable”]’)
.trigger(“mousedown”, { which: 1, pageX:sourceCX, pageY:sourceCY}).trigger(“mousemove”, { which: 1, pageX:targetCX, pageY:targetCY}).trigger(“mouseup”)

 

ZenQ’s Center of Excellence for automation has created a strategy to migrate scripts from Protractor to Cypress. Please reach out to sales@zenq.com to find more information and get a quote on migration.

By: Balaji Ponnada & Sreekanth Kondaveeti