← All skills

Jasmine Skill

Unit testingJavaScriptTypeScript

Copy and Paste in your Terminal

npx skills add https://github.com/LambdaTest/agent-skills.git --skill jasmine-skill

Advanced patterns

Advanced topics and patterns for experienced users.

Jasmine — Advanced Patterns & Playbook

Custom Matchers

beforeEach(() => {
  jasmine.addMatchers({
    toBeValidEmail: () => ({
      compare: (actual) => {
        const pass = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(actual);
        return { pass, message: `Expected "${actual}" ${pass ? 'not ' : ''}to be a valid email` };
      }
    }),
    toHaveBeenCalledWithMatch: () => ({
      compare: (spy, ...matchers) => {
        const calls = spy.calls.allArgs();
        const pass = calls.some(args => matchers.every((m, i) =>
          jasmine.matchersUtil.equals(args[i], m)));
        return { pass, message: `Expected spy to have been called with matching args` };
      }
    })
  });
});

Spy Patterns

describe('SpyPatterns', () => {
  it('tracks calls and arguments', () => {
    const obj = { process: (x) => x * 2 };
    spyOn(obj, 'process').and.callThrough();
    obj.process(5);
    expect(obj.process).toHaveBeenCalledWith(5);
    expect(obj.process).toHaveReturnedWith(10);
    expect(obj.process.calls.count()).toBe(1);
  });

  it('stubs return values', () => {
    const api = { fetch: () => {} };
    spyOn(api, 'fetch').and.returnValues(
      Promise.resolve({ id: 1 }),  // first call
      Promise.resolve({ id: 2 })   // second call
    );
  });

  it('creates standalone spy', () => {
    const callback = jasmine.createSpy('callback').and.callFake((x) => x + 1);
    [1, 2, 3].forEach(callback);
    expect(callback).toHaveBeenCalledTimes(3);
    expect(callback.calls.argsFor(0)).toEqual([1, 0, [1, 2, 3]]);
  });

  it('spies on property', () => {
    const obj = { get value() { return 42; } };
    spyOnProperty(obj, 'value', 'get').and.returnValue(100);
    expect(obj.value).toBe(100);
  });
});

Async Testing

describe('Async', () => {
  it('resolves promise', async () => {
    const result = await fetchData();
    expect(result).toBeDefined();
  });

  it('uses done callback', (done) => {
    fetchData().then(result => {
      expect(result.status).toBe('ok');
      done();
    }).catch(done.fail);
  });

  // Clock for timers
  beforeEach(() => jasmine.clock().install());
  afterEach(() => jasmine.clock().uninstall());

  it('debounces', () => {
    const spy = jasmine.createSpy();
    const d = debounce(spy, 500);
    d(); d();
    jasmine.clock().tick(500);
    expect(spy).toHaveBeenCalledTimes(1);
  });
});

Configuration

// jasmine.json
{
  "spec_dir": "test",
  "spec_files": ["**/*[sS]pec.?(m)js"],
  "helpers": ["helpers/**/*.?(m)js"],
  "random": true,
  "seed": null,
  "stopSpecOnExpectationFailure": false,
  "failSpecWithNoExpectations": true
}

Anti-Patterns

  • fit()/fdescribe() committed to source — skips other tests in CI
  • ❌ Shared state via closure without beforeEach reset
  • jasmine.clock().install() without corresponding uninstall() in afterEach
  • ❌ Nested describe blocks more than 3 levels deep — flatten test structure