最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Cypress: Re-use auth token across multiple API tests - Stack Overflow

programmeradmin4浏览0评论

I have a Rest API which generates a token. This session token is used across multiple REST API's as an authorization Bearer token. I used this as reference: .js

However, in that example, the function to generate token is embedded in the test. I tried to create a custom command for which should store locally but it is not being picked up by the test. Note that no return value is included in the custom command.

My code below under support/commands.js:

let identity
Cypress.Commands.add('postToken', () => {
    cy.request({
        method: 'POST',
        url: Cypress.env('api_identity_url'), //get from cypress.env.json
        form: true, //sets to application/x-www-form-urlencoded
        body: {
            grant_type: 'client_credentials',
            scope: 'xero_all-apis'
        },
        auth: {
            username: Cypress.env('api_identity_username'),
            password: Cypress.env('api_identity_password')
        }
    })
        .its('body')
        .then((response) => {
            identity = response
            window.localStorage.setItem('identity', JSON.stringify(identity))
            cy.log(identity.access_token)
        })
})

My test:

context('Check token details', () => {
  it('Check token', () => {
      cy.postToken()
      const bToken = window.localStorage.getItem('identity')
      cy.log(bToken)
  })
})

When I run the test, the log shows null value for 'identity'. However, it shows the current value in the custom command where I placed cy.log(identity.access_token) I tried using cy.writeFile but I don't think this is a clean method. There must be some way data can be passed between functions, and different classes.

Sample JSON format:

{
  "token": "<this is the value I would like to use for other API's authorisation bearer token>",
  "expires_in": 1200,
  "token_type": "Bearer"
}

I have a Rest API which generates a token. This session token is used across multiple REST API's as an authorization Bearer token. I used this as reference: https://github.com/cypress-io/cypress-example-recipes/blob/master/examples/logging-in__jwt/cypress/integration/spec.js

However, in that example, the function to generate token is embedded in the test. I tried to create a custom command for which should store locally but it is not being picked up by the test. Note that no return value is included in the custom command.

My code below under support/commands.js:

let identity
Cypress.Commands.add('postToken', () => {
    cy.request({
        method: 'POST',
        url: Cypress.env('api_identity_url'), //get from cypress.env.json
        form: true, //sets to application/x-www-form-urlencoded
        body: {
            grant_type: 'client_credentials',
            scope: 'xero_all-apis'
        },
        auth: {
            username: Cypress.env('api_identity_username'),
            password: Cypress.env('api_identity_password')
        }
    })
        .its('body')
        .then((response) => {
            identity = response
            window.localStorage.setItem('identity', JSON.stringify(identity))
            cy.log(identity.access_token)
        })
})

My test:

context('Check token details', () => {
  it('Check token', () => {
      cy.postToken()
      const bToken = window.localStorage.getItem('identity')
      cy.log(bToken)
  })
})

When I run the test, the log shows null value for 'identity'. However, it shows the current value in the custom command where I placed cy.log(identity.access_token) I tried using cy.writeFile but I don't think this is a clean method. There must be some way data can be passed between functions, and different classes.

Sample JSON format:

{
  "token": "<this is the value I would like to use for other API's authorisation bearer token>",
  "expires_in": 1200,
  "token_type": "Bearer"
}
Share Improve this question edited Nov 24, 2019 at 11:48 ebanster asked Nov 23, 2019 at 14:19 ebansterebanster 1,0863 gold badges14 silver badges32 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 15

You can use the cypress-localstorage-commands package to persist localStorage between tests.

In support/commands.js:

import "cypress-localstorage-commands";

Cypress.Commands.add('postToken', () => {
  cy.request({
    method: 'POST',
    url: Cypress.env('api_identity_url'), //get from cypress.env.json
    form: true, //sets to application/x-www-form-urlencoded
    body: {
      grant_type: 'client_credentials',
      scope: 'xero_all-apis'
    },
    auth: {
      username: Cypress.env('api_identity_username'),
      password: Cypress.env('api_identity_password')
    }
  })
  .its('body')
  .then(identity => {
    cy.setLocalStorage("identity_token", identity.token);
  });
});

Inside your tests:

describe("postToken", ()=> {
  before(() => {
    cy.postToken();
    cy.saveLocalStorage();
  });

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

  it("should exist identity in localStorage", () => {
    cy.getLocalStorage("identity_token").should("exist");
    cy.getLocalStorage("identity_token").then(token => {
      console.log("Identity token", token);
    });
  });

  it("should still exist identity in localStorage", () => {
    cy.getLocalStorage("identity_token").should("exist");
    cy.getLocalStorage("identity_token").then(token => {
      console.log("Identity token", token);
    });
  });
});

Thank you Javier for showing me the cypress-localstorage-commands package. I started using it. Until that I used to get the login token like this.

describe('Record audit', () => {
    let token = null;

    before(() => {
        cy.login().then((responseToken) => { // or postToken() in your case
            token = responseToken;
        });
    });

    it('I can use the token here', () => {
        cy.log(token);
    });
});

The only difference is that my login command returns the token. It should look like this in your code

// commands.js

.then((response) => {
    identity = response
    window.localStorage.setItem('identity', JSON.stringify(identity))
    cy.log(identity.access_token)
    return identity.access_token
})

I used this code in commmand.js

var headers_login = new Headers()
headers_login.append('Content-Type', 'application/json')

Cypress.Commands.add('get_token', (username, password)=>{
var token = ""
cy.request({
    method: 'POST',
    url: Cypress.env("api") + "users/getToken",
    failOnStatusCode: false,
    json: true,
    form: true,
    body: {username: username, password: password},
    headers: headers_login
 }).then((json) => {
    //cy.setLocalStorage('token', json.body.response.data.token)   
    token = json.body.response.data.token
    return token;
 }) }) 

After in your test add this code

describe('test', ()=>{
 before(()=>{
    cy.get_token('username', 'password').then(youToken => {
        cy.visit('/', {
             onBeforeLoad: function (window) {
                window.localStorage.setItem('token', youToken);
             }
         })
     }) 
     cy.close_welcome()        
 })
 it('test 001', ()=>{
       // contain test 
 })})
afterEach(()=>{cy.clearLocalStorage('token')})
发布评论

评论列表(0)

  1. 暂无评论