Cypress logs out when using cy.visit()

Viewed 1106

I'm sending multiple API requests and everything works fine, until I try to navigate to the page that was generated during API testing. When I navigate to the page using cy.visit() function I get unauthorized and all subsequent requests are being sent without authorization token, even though I added authorization header to the cy.visit() function.

Any help would be appreciated

    var accessToken
    before(function () {
        cy.request({
            method: 'POST',
            url: 'https://someurl.com/connect/token',
            form: true,
            body: {
                grant_type: 'password',
                username: 'admin',
                password: 'pass',
                client_id: 'client_id',
                client_secret: 'secret'
            }
        }).then((response) => {
            accessToken = response.body.access_token
        })
    })
   
   //api requests

    it('Navigates to order page', () => {
        cy.visit(`https://someurl.com/orders/${orderId}`, { auth: { bearer: accessToken.replace('Bearer ', '') } })
    })

enter image description here

enter image description here

2 Answers

Your code looks like the antipattern example in the Cypress Docs: Core Concepts: Aliases example. Using as to create an alias, you could do something like:

before(function () {
    cy.request({
        method: 'POST',
        url: 'https://someurl.com/connect/token',
        form: true,
        body: {
            grant_type: 'password',
            username: 'admin',
            password: 'pass',
            client_id: 'client_id',
            client_secret: 'secret'
        }
    }).then((response) => {
        cy.wrap(response.body.access_token).as('accessToken')
    })
})

//api requests

it('Navigates to order page', function() {
  const accessToken = this.accessToken
  cy.visit({
    url: `https://someurl.com/orders/${orderId}`,
    headers: {
      'Authorization': accessToken
    }
  })
})

NOTE: It is necessary to change the closure of the it() block from an arrow function to a regular function because the arrow function uses the lexical scope this, and will not include the alias created in the before() closure.

I managed to fix the problem by changing authorization from backed api request to frontend login form and then whitelisting local storage.

I had to add this piece of code

        Cypress.LocalStorage.clear = function (keys, ls, rs) {
            if (keys) {
                return
            }
        }

And now my spec file looks like this:

    before(function () {
        cy.server()
        cy.route('GET', '/api/orders/orders?PageNo=1&Size=20').as('orders')

        cy.LogIn('email', 'pass')
    
        //wrapping access token from the request after successfull authorization

        cy.wait('@orders').then((request) => {
            cy.wrap(request.requestHeaders.Authorization).as('accessToken')
        })
        
        //whitelisting local storage

        Cypress.LocalStorage.clear = function (keys, ls, rs) {
            if (keys) {
                return
            }
        }
    })

    it('A',()=>{
      cy.visit('some url') //it works!
    })

Also when restarting the test I was still logged in. To prevent this from happening I added clearing local storage at the very beginning of before() function

        window.localStorage.clear()

https://github.com/cypress-io/cypress/issues/461

Related