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:
-
- Simple Setup: Cypress does not need any configuration as the dependencies and libraries are already in-built.
- 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.
- 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