How to test login to GSuite calendar using Cypress

2020-06-20 10:47发布

问题:

Environment

  • Windows 10
  • NodeJs 8
  • Cypress 3.1.2
  • Selenium
  • Chromium v59

How to authenticate to Google calendar using Cypress?

I need to run automated tests on a Chrome extension that I am developing. The first step is to authenticate/login to GSuite calendar.

I am using Cypress but it is not allowing me to login into GSuite calendar. Instead when "clicking sign-in" (from Cypress) it jumps to the Next button again.

My code snippet

describe('Login',function() {
   it('Go to GSuite calendar', function() {
     cy.visit('https://www.google.com/calendar')
   })

   it('Login', function() {
     cy.get('#Email').type('my user')
     cy.get('#next').click()
     cy.get('#Passwd').type('my password')
     cy.get('#signIn').click()
   })
})  

This fails and takes me to the Next button

Screenshots

1. Hit execute

2. At the end, it returns to the initial screen instead of logging me in

My Try with Selenium & it works

from selenium import webdriver
import time

# variables for userid & password
u = "JohnDoe@xxxx-labs.com"
p = "Mysecretpassword"

# chromedriver installation required for login through google chrome
driverpath = "C:/Users/pjain2/Desktop/chromedriver_win32/chromedriver"

# launch google calendar login page
d = webdriver.Chrome(driverpath)
d.get("https://www.google.com/calendar")

# fill email field send_keys for filling text
e = d.find_element_by_id("identifierId")
e.send_keys(u)

# find & click next button
d.find_element_by_xpath("//*[@id='identifierNext']/content/span").click()
time.sleep(2)

# enter password
e = d.find_element_by_xpath("//*[@id='password']/div[1]/div/div[1]/input")
e.send_keys("Mysecretpassword")
time.sleep(2)

# sign in
d.find_element_by_xpath("//*[@id='passwordNext']/content/span").click()
time.sleep(10)

Screenshot of successfully login to Google calendar

I want to achieve the same thing with Cypress

Any pointers?

回答1:

In spec.js file, add the following code:

describe('Random VMR for ESG',function() {
    beforeEach(() => {
       cy.visit('https://www.google.com/calendar')
    })
      it('type email & password', function() {
        cy.get('#Email').type('my user')
        cy.get('#next').click()
        cy.get('#Passwd').type('my password')
        cy.get('#signIn').click()
    })   
})

In support folder, in command.js, add the following code:

Cypress.Commands.add('login', ()=> {
    cy.request({         // cy.request is not bound by any security and will bypass the login part
        method: 'POST' , // Post request to URL along with body
        url: 'https://www.google.com/calendar',
        body: {
            user: {
                email: 'my user',
                password: 'my password',
            }
        }
    })
     //server sends back the response JSON payload 
    .then((resp) => {      //token extracted from JSON payload and is saved in LocalStorage
     window.localStorage.setItem('jwt' , resp.body.user.token)
    })
})

In spec.js file, there is the code which just visits the URL and tests the email and password input type and signs in.

The problem was that is was redirecting the page back to the first page right after the sign in. To work around this behavior, we use cy.request in commands.js file since cy.request requests outside the constraints of the browser. i.e. it is not bound by any security.

Once you have a proper e2e test around logging in, there’s no reason to continue to cy.visit() the login and wait for the entire page to load all associated resources before running any other commands. Doing so can slow down our entire test suite. Using cy.request(), we can bypass all of this because it automatically gets and sets cookies just as if the requests came from the browser itself.

Therefore a POST request is been sent along with the JSON payload or body. Now upon successfully validating the request body, our application code extracts the token out of payload and save it in local storage and also adds the token in all the request header so that the API server can authenticate subsequent request coming from our application.

When our application loads, it checks that the token is already in local storage or not, if it is then it goes ahead and and sets it on the request agent. This way, it will bypass the login part when you will test the GSuite.