rino
rino

Reputation: 333

Variable is empty when logged outside the block in which it is set

    let studentName: any = '';
    cy.get('app-screen').find('input[id="studentName"]').invoke('val').as('name')
    cy.get('@name').then((name) => {
      studentName = name;
      cy.log('Student Name: ' + studentName )
    })
    cy.log('Student Name: ' + studentName )

The code above prints the student name for the first log statement.

The log statement outside the then block is empty in test runner.

Any help as to why the value studentName is not printing outside then block? How do I get the value outside the then block?

Upvotes: 1

Views: 1256

Answers (1)

Fody
Fody

Reputation: 32044

What happens is the test runner runs through the test and adds the commands it finds to the Cypress Command Queue.

When it adds the line cy.log('Student Name: ' + studentName ), it gets the value of studentName as it is before the command queue starts running, i.e when studentName = ''.

But it only performs the cy.log() later when the queue gets to that command, giving the impression studentName has not been updated.

You can defer the reading of studentName until later with a .then() Anything inside a .then callback will execute only after preceding queue commands.

let studentName: any = '';
cy.get('app-screen').find('input[id="studentName"]').invoke('val').as('name')
cy.get('@name').then((name) => {
  studentName = name;
  cy.log('Student Name: ' + studentName )
})

// Now get the updated studentName
cy.then(() => {
  cy.log('Student Name: ' + studentName )  // adds this to the queue after 
                                           // all previous commands have run
})

Other options

If student object is important in a lot of tests, consider creating it in a beforeEach() and using function() form of the test

beforeEach(() => {
  cy.get('app-screen')
    .find('input[id="studentName"]')
    .invoke('val')
    .as('name')
})

it('tests the student', function() {  // NOTE function not arrow function
  
  expect(this.name).to.eq('Saran')    // access with "this" prefix

})

it('also tests the student', function() {  // NOTE function not arrow function
  
  cy.log("Student: ' + this.name)    // still has value

})

Script1.js

cy.fixture('studentData.json').then(studentData => {

  cy.get('app-screen')
    .find('input[id="studentName"]')
    .invoke('val')
    .then(name => {
      studentData.name = name
      cy.writeFile('cypress/fixtures/studentData.json', studentData)
    })
})

Script2.js

import studentData from 'cypress/fixtures/studentData.json'

// Don't use cy.fixture('studentData.json') here 
// because the fixture command caches the data
// so update will not always be seen

Upvotes: 4

Related Questions