Cypress: Get token from API then save in local storage and use in another API's header then return the response body of the 2nd API

…衆ロ難τιáo~ 提交于 2020-01-16 11:25:34

问题


I have an API (let's call it getToken) to generate a token in its response body. I then call that token and store in the header of another API (let's call it returnBody). It makes sense to use localStorage for the getToken API as this token is re-usable for multiple API's. However, I am having doubts using localStorage if I need to return / display the response body of the succeeding API's such as returnBody. Inside the API's function/command, it logs the response body. However, when I call it via the test file, it generates null. Sample code below:

commands.js:

Cypress.Commands.add('getToken', () => { //API to generate token
    cy.request({
        method: 'POST',
        url: 'https://someAPItoGenerateToken',
        form: true, //sets to application/x-www-form-urlencoded
        body: {
            grant_type: 'credentials',
            scope: 'all-apis'
        },
        auth: {
            username: Cypress.env('api_username'),
            password: Cypress.env('api_password')
        }
    })
        .its('body')
        .then(bearerToken => {
            cy.setLocalStorage('bearerToken', JSON.stringify(bearerToken))
            cy.log('Token generated: ' + bearerToken.token)
            }
        )
})

Cypress.Commands.add('returnBody', (url, token) => { //API to return some values
    return cy.request({
        method: 'GET',
        url: url,
        auth: {
            bearer: token
        }
    })
        .then((response) => {
            // Stringify JSON the body.
            let body = JSON.stringify(response.body)
            cy.log(body)
        })
})

test file:

describe('Return value of 2nd API', ()=> {
    before(() => {
        cy.getToken() //Run this once to generate token for the entire test suite
        cy.saveLocalStorage()
    })

    beforeEach(() => {
        cy.restoreLocalStorage()
    })

    it('Return value of 2nd API', () => {
        cy.getLocalStorage('bearerToken').should('exist')
        cy.getLocalStorage('bearerToken').then(bearerToken => {
            const tokenJSON = JSON.parse(bearerToken)
            const url = 'https://someAPItoReturnJSONbody'
            cy.returnBody(url, tokenJSON.token).then((returned_value) => {
                cy.log(returned_value)
            })
        })

    })
})

body from the returnBody command returns the JSON response. However, returned_value from the test file displays null.


回答1:


As commented in this issue: "You cannot return a 3rd party promise from a custom command because this breaks the chaining between cypress commands. This is because the .then methods are not the same."

So, simply return the request body as:

Cypress.Commands.add('returnBody', (url, token) => {
  return cy.request({ /* options */ })
    .its("body");
});

Then, in your test you can do:

it("should return foo value", () => {
  cy.returnBody(url, token).then(returned_value => {
    cy.log(returned_value);
    expect(returned_value).to.deep.equal("foo-value");
  })
})



回答2:


You may need to return response body from your returnBody task:

Cypress.Commands.add('returnBody', (url, token) => {
  return cy.request({ /* options */ })
    .then(response => {
      let body = JSON.stringify(response.body);
      Cypress.log(body);
      return body; // Add this line
    });
});



回答3:


An alternative would be to store the token on cypress side using fixtures.

fixture.json:

{"bearerToken":""
.
.
.}

commands.js:

cy.fixture('testData.json').as('testData')
.
.
.then(bearerToken => {
            this.testData.bearerToken = JSON.stringify(bearerToken)
            cy.log('Token generated: ' + bearerToken.token)
            }
        )

test.js

describe('Return value of 2nd API', ()=> {
    before(() => {
        cy.getToken() //Run this once to generate token for the entire test suite
    })

    it('Return value of 2nd API', () => {
        cy.fixture('testData.json').as('testData')
        .then(testData => {
            const tokenJSON = JSON.parse(testData.bearerToken)
            const url = 'https://someAPItoReturnJSONbody'
            cy.returnBody(url, tokenJSON.token).then((returned_value) => {
                cy.log(returned_value)
            })
        })

    })
})


来源:https://stackoverflow.com/questions/59558827/cypress-get-token-from-api-then-save-in-local-storage-and-use-in-another-apis

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!