When testing reactivity with Jasmine some Tracker computations started behaving in a very intriguing way: Exactly half the computations are reactive, the other half is not.

What I did to test this behaviour is the following:

//In a describe block
var foo = new ReactiveVar(false);

it('should react to the changes of foo (1)', function(done) {
  Tracker.autorun(function observeFoo(fooComputation) {
    var fooValue = foo.get();
    console.log('foo in its computation is', fooValue);
    if ( fooValue === true ) {
      fooComputation.stop();
      done();
    }
  });

  setTimeout(function setFoo() {
    foo.set(true);
  }, 100);
});

So basically:

  1. Initialize a reactive foo to false.
  2. Start tracking it, waiting for it to get to true so that the test is declared to be done().
  3. Use a timeout to foo.set(true) and thus resolve the test.
  4. Stop this computation because it's not needed any more.

Now, let's do that very same thing with a different variable:

var foo = new ReactiveVar(false),
    bar = new ReactiveVar(false);

it('should react to the changes of foo (1)', function(done) { /* ... */ });

it('should react to the changes of bar (2)', function(done) {
  Tracker.autorun(function observeBar(barComputation) {
    var barValue = bar.get();
    console.log('bar in its computation is', barValue);
    if ( barValue === true ) {
      barComputation.stop();
      done();
    }
  });

  setTimeout(function setBar() {
    bar.set(true);
  }, 100);
});

That's where the fun begins. While this test is the very same code with a different name, and has exactly the same written logic, it fails because the computation tracking bar is never rerun.

The console.log shows it very well:

foo in its computation is: false
foo in its computation is: true - reactivity kicked in!
bar in its computation is: false
[Nothing]

While it is very clear that the computation for foo was rerun and thus its test was completed, the computation for bar is never invalidated and thus the test fails.

However this does not stop here. If we add a third test case for a new reactive variable (say, baz) and follow the same procedure as before (initializing it with the others, adding the test at the end in the same describe function) then it works perfectly!

var foo = new ReactiveVar(false),
    bar = new ReactiveVar(false),
    baz = new ReactiveVar(false);

it('should react to the changes of foo (1)', function(done) { /* ... */ });
it('should react to the changes of bar (2)', function(done) { /* ... */ });

it('should react to the changes of baz (3)', function(done) { /* ... */ });

Here test (1) succeeds, test (2) fails, test (3) succeeds.

Now if we add a fourth test, with a new cat for example, following the same procedure... Then test (4) will fail with the following log.

foo in its computation is false
foo in its computation is true
bar in its computation is false bar is not rerun and fails
baz in its computation is false
baz in its computation is true
cat in its computation is false cat is not rerun and fails
[Nothing]

foo and baz have been reacted unto, not bar and cat.

I have done it with two others (fifth and sixth), same result: (5) succeeds, (6) fails.
The "odd" tests succeed, the "even" ones fail.

Full reproduction code:

describe('Tracker usage with Jasmine', function() {
  var foo = new ReactiveVar(false),
      bar = new ReactiveVar(false),
      baz = new ReactiveVar(false),
      cat = new ReactiveVar(false),
      pup = new ReactiveVar(false),
      elf = new ReactiveVar(false);

  it('should react to the changes of foo (1)', function(done) {
    Tracker.autorun(function observeFoo(fooComputation) {
      var fooValue = foo.get();
      console.log('foo in its computation is', fooValue);
      if ( fooValue === true ) {
        fooComputation.stop();
        done();
      }
    });

    setTimeout(function setFoo() {
      foo.set(true);
    }, 100);
  });

  it('should react to the changes of bar (2)', function(done) {
    Tracker.autorun(function observeBar(barComputation) {
      var barValue = bar.get();
      console.log('bar in its computation is', barValue);
      if ( barValue === true ) {
        barComputation.stop();
        done();
      }
    });

    setTimeout(function setBar() {
      bar.set(true);
    }, 100);
  });

  it('should react to the changes of baz (3)', function(done) {
    Tracker.autorun(function observeBaz(bazComputation) {
      var bazValue = baz.get();
      console.log('baz in its computation is', bazValue);
      if ( bazValue === true ) {
        bazComputation.stop();
        done();
      }
    });

    setTimeout(function setBaz() {
      baz.set(true);
    }, 100);
  });

  it('should react to the changes of cat (4)', function(done) {
    Tracker.autorun(function observeCat(catComputation) {
      var catValue = cat.get();
      console.log('cat in its computation is', catValue);
      if ( catValue === true ) {
        catComputation.stop();
        done();
      }
    });

    setTimeout(function setCat() {
      cat.set(true);
    }, 100);
  });

  it('should react to the changes of pup (5)', function(done) {
    Tracker.autorun(function observePup(pupComputation) {
      var pupValue = pup.get();
      console.log('pup in its computation is', pupValue);
      if ( pupValue === true ) {
        pupComputation.stop();
        done();
      }
    });

    setTimeout(function setPup() {
      pup.set(true);
    }, 100);
  });

  it('should react to the changes of elf (6)', function(done) {
    Tracker.autorun(function observeElf(elfComputation) {
      var elfValue = elf.get();
      console.log('elf in its computation is', elfValue);
      if ( elfValue === true ) {
        elfComputation.stop();
        done();
      }
    });

    setTimeout(function setElf() {
      elf.set(true);
    }, 100);
  });
});

Why is this happening?
How can I solve this matter while keeping all these reactive variables in the same describe function?


I have tried to add nested describe functions without success.
This issue magically disappears when isolating the tests in their own non-related describe functions, please do not answer in such a way.

0

There are 0 best solutions below