简体   繁体   中英

Pass variable from before() to it() in mocha

Very new to automation, I am trying to pass the token value from before block() to it() and I am getting undefined.

Able to generate successfully and save it in token

const { spec } = require('pactum');
const request = require('request');
const userConfig = require('../config/credential.json')

process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

let token = "";
let authToken = "";

describe('POST /jobs', function () {
    before(function () {
        var option = {
            'method': 'POST',
            'url': 'https://login.microsoftonline.com/<tenant_id>/oauth2/v2.0/token',
            'headers': {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            form: {
                'client_id': `${userConfig.client_id}`,
                'grant_type': 'password',
                'Password': `${userConfig.Password}`,
                'UserName': `${userConfig.UserName}`,
                'scope': `${userConfig.scope}`,
                'client_secret': `${userConfig.client_secret}`
            }
        };
        request(option, function (error, response) {
            if (error) throw new Error(error)
            const modifyResponse = JSON.parse(response.body)
            token = modifyResponse["access_token"]
        })
    })
    it('Create Job should return 201 status code', async () => {
        authToken = this.token
        console.log('------------>', authToken)
        await spec()
            .post('https://localhost:3000/jobs')
            .withHeaders('Authorization', `Bearer ${authToken}`)
            .withHeaders('X-Client-Id', 'AzureDataLoaderUI')
            .withHeaders('X-Message-Created-Ts', '2022-JUN-07 04:06')
            .withHeaders('X-Message-Id', '4e8fb14c-c71f-46f8-b41a-561d393037ce')
            .withHeaders('X-Transaction-Created-Ts', '2022-JUN-07 04:06')
            .withHeaders('X-Transaction-Id', 'f11c97dc-a6eb-4ff7-aff6-de47c4686941')
            .withHeaders('X-User-Id', 'AutoTestUser')
            .withHeaders('Ocp-Apim-Subscription-Key', 'a731ccf0510849c690d23bb42ecef9d3')
            .withHeaders('aeg-sas-key', 'b6LrYspQUAY2XnxkrDFDFDYsb8U2zqMQAzaQoZcQ=')
            .withJson({ "product": "IRT", "entity": "CENTRE PROVISIONING AND RECIPIENT DETAILS", "operation": "UPDATE", "jobName": "AUTOPERF02", "studyId": "AUTO02" })
            .expectStatus(201);
    });
});

I think you also need to await the request() call, or perhaps use Cypress cy.request() instead.

let token = "";
let authToken = "";

describe('POST /jobs', function () {
    before(async function () {
        var option = {
            'method': 'POST',
            'url': 'https://login.microsoftonline.com/<tenant_id>/oauth2/v2.0/token',
            'headers': {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            form: {
                'client_id': `${userConfig.client_id}`,
                'grant_type': 'password',
                'Password': `${userConfig.Password}`,
                'UserName': `${userConfig.UserName}`,
                'scope': `${userConfig.scope}`,
                'client_secret': `${userConfig.client_secret}`
            }
        };
        await request(option, function (error, response) {
            if (error) throw new Error(error)
            const modifyResponse = JSON.parse(response.body)
            token = modifyResponse["access_token"]
        })
    })
    it('Create Job should return 201 status code', async () => {
        authToken = token
       ...

With cy.request , you don't have to await

cy.request(option)
  .then(response => {
    // if error, it's already thrown
    token = response.body["access_token"]
  })

Using Mocha done() to signal request is complete

Above async only works with Promise-based requests.

To wait for the request(options, callback) to complete pass in Mocha's done() function and call it after setting your token.

This is a simple example, using a JSONPlaceholder to request some data

const request = require('request');

let token;

before(function (done) {
  request({
    'method': 'GET', 
     'url': 'https://jsonplaceholder.typicode.com/todos/1' 
  }, function (error, response) {
    const modifyResponse = JSON.parse(response.body)
    token = modifyResponse.title
    done()                          // signal end of request
  })
})

it('sees the token', () => {
  expect(token).to.eq('delectus aut autem')   // passes
})

You can use the cypress environment variable Cypress.env to save the token and then use it anywhere throughout your test.

const {spec} = require('pactum')
const request = require('request')
const userConfig = require('../config/credential.json')

process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'

let token = ''
let authToken = ''

describe('POST /jobs', function () {
  before(function () {
    var option = {
      method: 'POST',
      url: 'https://login.microsoftonline.com/<tenant_id>/oauth2/v2.0/token',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      form: {
        client_id: `${userConfig.client_id}`,
        grant_type: 'password',
        Password: `${userConfig.Password}`,
        UserName: `${userConfig.UserName}`,
        scope: `${userConfig.scope}`,
        client_secret: `${userConfig.client_secret}`,
      },
    }
    request(option, function (error, response) {
      if (error) throw new Error(error)
      const modifyResponse = JSON.parse(response.body)
      //token = modifyResponse["access_token"]
      Cypress.env('token', modifyResponse['access_token']) //Set the token in env variable
    })
  })
  it('Create Job should return 201 status code', async () => {
    authToken = Cypress.env('token') //Get the token from env variable
    console.log('------------>', authToken)
    await spec()
      .post('https://localhost:3000/jobs')
      .withHeaders('Authorization', `Bearer ${authToken}`)
      .withHeaders('X-Client-Id', 'AzureDataLoaderUI')
      .withHeaders('X-Message-Created-Ts', '2022-JUN-07 04:06')
      .withHeaders('X-Message-Id', '4e8fb14c-c71f-46f8-b41a-561d393037ce')
      .withHeaders('X-Transaction-Created-Ts', '2022-JUN-07 04:06')
      .withHeaders('X-Transaction-Id', 'f11c97dc-a6eb-4ff7-aff6-de47c4686941')
      .withHeaders('X-User-Id', 'AutoTestUser')
      .withHeaders(
        'Ocp-Apim-Subscription-Key',
        'a731ccf0510849c690d23bb42ecef9d3'
      )
      .withHeaders('aeg-sas-key', 'b6LrYspQUAY2XnxkrDFDFDYsb8U2zqMQAzaQoZcQ=')
      .withJson({
        product: 'IRT',
        entity: 'CENTRE PROVISIONING AND RECIPIENT DETAILS',
        operation: 'UPDATE',
        jobName: 'AUTOPERF02',
        studyId: 'AUTO02',
      })
      .expectStatus(201)
  })
})

You can use the function() in the it() block as well, and set with an alias.

let authToken = "";

describe('POST /jobs', function () {
    before(function () {
      option = {...}
      cy.request(option)
        .then(response => {
          token = response.body["access_token"]
        })
        .as('token')   // alias will set "this.token"
    })

    it('Create Job should return 201 status code', async funtion() {
        authToken = this.token                           // "this" can be used here
        console.log('------------>', authToken)

Guess already the experts has been answered your question, as you have used pactnum, this can be done through it.

Now coming on to the problem, because you have a call back in it block that's why it is not working. But the experts are correct like Fody said.

Now using pactnum, please follow these steps.

  1. Create a file (name can be anything for example _base.spec.js in your test folder).

     const userConfig = require('../config/credential.json') before(async function () { await spec() .post('https://login.microsoftonline.com/oauth2/v2.0/token') .withForm({ 'client_id': `${userConfig.client_id}`, 'grant_type': 'password', 'Password': `${userConfig.Password}`, 'UserName': `${userConfig.UserName}`, 'scope': `${userConfig.scope}`, 'client_secret': `${userConfig.client_secret}` }) .expectStatus(200) .stores('AUTH_TOKEN',"access_token") })
  2. Now just call this in your code

            .post('https://<target_url>')
            .withHeaders('Authorization', `Bearer $S{AUTH_TOKEN}`)

在这种情况下,因为你有单独的块,只需使用

authToken = token  // no need for "this"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM