4

If my code is:

context('The Test', () => {
  let testStr = 'Test A'
  it(`This test is ${testStr}`, () => {
    expect(testStr).to.eq('Test A')
  })

  testStr = 'Test B'
  it(`This test is ${testStr}`, () => {
    expect(testStr).to.eq('Test B')
  })

  testStr = 'Test C'
  it(`This test is ${testStr}`, () => {
    expect(testStr).to.eq('Test C')
  })
})

This image has the resulting tests -- My usage of testStr inside the backticks works the way I want it to (indicated by output having the correct test titles of Test A, Test B, and Test C), but the usage of testStr in the expect(testStr).to.eq cases fails the first 2 tests because testStr is always 'Test C' for these checks. Why does this occur, and how can I write this differently to do what I want?

2 Answers2

2

it()'s callbacks will be executed only after parent's one (context in your case). You can play with it in debugger and see it live: enter image description here

So mocha will assign the final 'Test C' value and call the first it() callback after that.

To solve the problem as close as possible to the structure of you current approach, you can use mocha context to capture the value at the time you define the it() case. Unfortunately, I found the mocha shares the context object between all of it siblings. So I had to wrap each of the case inside a child context:

context('The Test', function () {
  let curTestStr = 'Test A'

  context(`This test is ${curTestStr}`, () => {
    it("test", function() {
      expect(this.curTestStr).to.eq('Test A')
    })
  }).ctx.curTestStr = curTestStr;

  curTestStr = 'Test B'
  context(`This test is ${curTestStr}`, () => {
    it("test", function() {
      expect(this.curTestStr).to.eq('Test B')
    })
  }).ctx.curTestStr = curTestStr;

  curTestStr = 'Test C'
  context(`This test is ${curTestStr}`, () => {
    it("test", function() {
      expect(this.curTestStr).to.eq('Test C')
    })
  }).ctx.curTestStr = curTestStr;
})

Please also note that you have to use a function callback to access variables from this. It will not work with an arrow function expression () => {}

Mikhail Bolotov
  • 976
  • 1
  • 6
  • 13
  • Thanks. Good to know that's the order, though that's incredibly frustrating. Thanks for recommending a workaround-- hopefully I can find one that doesn't require creating a subsection for every test though – blake.vandercar Aug 05 '21 at 15:43
0

I don't have enough proof but i believe that it must be because it() must be asynchronous like the following code

let a= 10;
setTimeout(function(){ console.log(a); }, 1000);
a = 11;
setTimeout(function(){ console.log(a); }, 1000);

by the time setTimeout are executed the value of a becomes 11.

Found this for your use case

TheViralGriffin
  • 421
  • 1
  • 8
  • 21