Jasmine — Test Array, Strings, and Time-Dependent Code

John Au-Yeung - Jan 23 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

Testing is an important part of JavaScript.

In this article, we’ll look at how to create more complex tests with Jasmine.

Array Checks

We can use the jasmine.arrayContaining method to check the content of the array.

For example, we can write:

describe("jasmine.arrayContaining", function () {
  let foo;

  beforeEach(function () {
    foo = [1, 2, 3];
  });

  it("matches arrays with some of the values", function () {
    expect(foo).toEqual(jasmine.arrayContaining([3, 1]));
    expect(foo).not.toEqual(jasmine.arrayContaining([6]));
  });

  describe("when used with a spy", function () {
    it("is useful when comparing arguments", function () {
      const callback = jasmine.createSpy('callback');
      callback([1, 2, 3, 4]);
      expect(callback)
        .toHaveBeenCalledWith(
          jasmine.arrayContaining([4, 2, 3])
        );
      expect(callback)
        .not
        .toHaveBeenCalledWith(
          jasmine.arrayContaining([5, 2])
        );
    });
  });
});
Enter fullscreen mode Exit fullscreen mode

We have the jasmine.arrayContaining method to check for the numbers in the array.

It returns true if the array being checked has all the items in the array we passed into arrayContaining .

We can do the same with function arguments.

String Matches

We can use the jasmine.stringMatching to check if a string has a given substring or pattern.

For instance, we can write:

describe('jasmine.stringMatching', function () {
  it("matches as a regex", function () {
    expect({ foo: 'baz' })
      .toEqual({
        foo: jasmine.stringMatching(/^baz$/)
      });
    expect({ foo: 'foobarbaz' })
      .toEqual({
        foo: jasmine.stringMatching('bar')
      });
  });

  describe("when used with a spy", function () {
    it("is useful for comparing arguments", function () {
      const callback = jasmine.createSpy('callback');
      callback('foobarbaz');
      expect(callback)
        .toHaveBeenCalledWith(
          jasmine.stringMatching('baz')
        );
      expect(callback)
        .not
        .toHaveBeenCalledWith(
          jasmine.stringMatching(/^baz$/)
        );
    });
  });
});
Enter fullscreen mode Exit fullscreen mode

We have the jasmine.stringMatching method with a regex and a string.

It lets us check for a regex pattern and a substring.

Asymmetric Equality Tester

We can create our own equality tester to do our check.

For instance, we can write:

describe("custom asymmetry", function () {
  const tester = {
    asymmetricMatch(actual) {
      return actual.includes('bar');
    }
  };

  it("dives in deep", function () {
    expect("foo,bar,baz,quux").toEqual(tester);
  });

  describe("when used with a spy", function () {
    it("is useful for comparing arguments", function () {
      const callback = jasmine.createSpy('callback');
      callback('foo,bar,baz');
      expect(callback).toHaveBeenCalledWith(tester);
    });
  });
});
Enter fullscreen mode Exit fullscreen mode

We created our own tester object with the asymmericMatch method to check for what we want.

We just return a boolean expression with the condition we want to check.

Then we can use it with the toHaveBeenCalledWith or toEqual .

Therefore, we can check for the values and the arguments.

Jasmine Clock

We can test time-dependent code with the jasmine.clock method.

For example, we can write:

describe("custom asymmetry", function () {
  let timerCallback;

  beforeEach(function () {
    timerCallback = jasmine.createSpy("timerCallback");
    jasmine.clock().install();
  });

  afterEach(function () {
    jasmine.clock().uninstall();
  });

  it("causes a timeout to be called synchronously", function () {
    setTimeout(function () {
      timerCallback();
    }, 100);
    expect(timerCallback).not.toHaveBeenCalled();
    jasmine.clock().tick(101);
    expect(timerCallback).toHaveBeenCalled();
  });
});
Enter fullscreen mode Exit fullscreen mode

We have the jasmine.clock().install() to make Jasmine mock the time.

Then we call jasmine.clock().uninstall() to remove the Jasmine clock.

In our test, we can change the time to what we want.

And then we can do our checks after some amount of time is elapsed.

Conclusion

We can test time-dependent code with Jasmine’s clock methods.

Also, we can check for array and string items with built-in functions.

And we can make our own matches to test what we want.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .