jasmine-tests
Configures and runs Jasmine - the original BDD-style JS test framework (predecessor to Jest) with built-in matchers + spies, no external assertion library; ships `jasmine-core` + `jasmine` runner; `spec_dir` + `helpers` convention; `jasmine.json` config; spy patterns (`spyOn`, `createSpy`); pairs with Karma for in-browser testing. Use when the user maintains legacy AngularJS / Karma+Jasmine codebases, or wants minimal BDD-style tests with no third-party assertion library.
Install with skills.sh (any agent)
npx skills add testland/qa --skill jasmine-testsjasmine-tests
Overview
Per jasmine.github.io/pages/getting_started.html (opens in new window):
Jasmine (~2010) is the original BDD-style JS test framework. Most of Jest's API descends from Jasmine - describe, it, beforeEach, expect(...).toBe(...), spies - were all Jasmine patterns first.
Modern usage:
For new browser-side projects, prefer vitest-tests or jest-tests. This skill covers the maintenance use case + the migration path.
When to use
How to use
Step 1 - Install
npm install --save-dev jasmine
npx jasmine initinit creates spec/support/jasmine.json:
{
"spec_dir": "spec",
"spec_files": [
"**/*[sS]pec.js"
],
"helpers": [
"helpers/**/*.js"
],
"stopSpecOnExpectationFailure": false,
"random": true
}Step 2 - First test
// spec/sumSpec.js
const { sum } = require('../src/sum');
describe('sum', () => {
it('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
});Wire package.json:
{
"scripts": {
"test": "jasmine"
}
}Step 3 - Built-in matchers
Per jasmine.github.io/api/edge/matchers.html:
| Matcher | Use |
|---|---|
toBe(expected) | Strict equality (===) |
toEqual(expected) | Deep equality |
toBeTruthy() / toBeFalsy() | Boolean coercion |
toBeGreaterThan(n) / toBeLessThan(n) | Numeric comparison |
toBeCloseTo(n, precision) | Float comparison |
toContain(substring) | String / array containment |
toMatch(regex) | Regex match |
toThrow() / toThrowError(...) | Sync throw |
toBeInstanceOf(Class) | Type check |
toBeDefined() / toBeUndefined() / toBeNull() | Existence |
No need for Chai's expect(x).to.equal(y) style - Jasmine's matchers are first-class.
Step 4 - Spies (built-in mocking)
describe('user service', () => {
it('calls api on save', () => {
spyOn(api, 'post').and.returnValue(Promise.resolve({ id: 1 }));
userService.save(user);
expect(api.post).toHaveBeenCalledWith('/users', user);
});
it('standalone spy', () => {
const spy = jasmine.createSpy('callback');
eventEmitter.on('save', spy);
eventEmitter.emit('save');
expect(spy).toHaveBeenCalled();
});
});Spy methods:
| Method | Effect |
|---|---|
spyOn(obj, 'method') | Replace method with spy; returns undefined by default |
.and.returnValue(value) | Configure return |
.and.callFake(fn) | Custom implementation |
.and.callThrough() | Spy + delegate to real impl |
jasmine.createSpy(name) | Standalone spy |
jasmine.createSpyObj(name, ['m1', 'm2']) | Object with multiple spies |
Step 5 - Async patterns
// async/await (Jasmine 3.x+)
it('async test', async () => {
const result = await fetchData();
expect(result).toBe('expected');
});
// Promise return (Jasmine 2.x+)
it('promise test', () => {
return fetchData().then(result => {
expect(result).toBe('expected');
});
});
// Done callback (legacy)
it('callback test', (done) => {
fetchData((err, result) => {
expect(result).toBe('expected');
done();
});
});Step 6 - Hooks
describe('User service', () => {
beforeAll(() => { /* once before all */ });
afterAll(() => { /* once after all */ });
beforeEach(() => { /* before each spec */ });
afterEach(() => { /* after each spec */ });
});Same pattern as Jest / Vitest.
Step 7 - CI integration
- run: npm ci
- run: npx jasmine --config=spec/support/jasmine.json --reporter=jasmine-spec-reporter
# Or with JUnit XML for CI dashboards:
- run: npx jasmine --reporter=jasmine-junit-xml-reporterBrowser tests and migrating off Jasmine
Running specs in a real browser (Karma, the legacy Angular CLI default) and moving a suite to Jest (jest-codemods handles ~80% of the syntax transformations) are covered in references/karma-and-migration.md.
Worked example
A legacy service userService.save(user) POSTs to an API; verify it calls the API without hitting the network.
const { userService } = require('../src/userService');
const api = require('../src/api');
describe('userService.save', () => {
it('posts the user to /users', () => {
spyOn(api, 'post').and.returnValue(Promise.resolve({ id: 1 }));
userService.save({ name: 'Alice' });
expect(api.post).toHaveBeenCalledWith('/users', { name: 'Alice' });
});
});Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Start new project with Jasmine + Karma in 2026 | Legacy stack; Karma in maintenance | Use Vitest / Jest for new (see references/karma-and-migration.md) |
spyOn without .and configurator | Spy returns undefined; tests pass-by-accident | Always configure (Step 4) |
Use fdescribe / fit (focus) accidentally | Suite runs only focused specs | Lint rule equivalent of mocha/no-exclusive-tests |
| Mix Jasmine assertions with Chai | Two assertion APIs in one suite; reader confusion | Pick one (Step 3 - Jasmine's are sufficient) |
| Skip migration codemods when moving to Jest | Manual rewrites slow + error-prone | jest-codemods (see references/karma-and-migration.md) |
Limitations
References
Jasmine: Karma browser tests and migrating to Jest
View source (opens in new window)Jasmine: Karma browser tests and migrating to Jest
Deep reference for jasmine-tests SKILL.md. Consult when running Jasmine specs in a real browser via Karma (the legacy Angular CLI default), or when moving a Jasmine suite to Jest.
Karma integration (browser tests)
For browser-environment tests (legacy Angular CLI default):
npm install --save-dev karma karma-jasmine karma-chrome-launcherkarma.conf.js:
module.exports = function(config) {
config.set({
frameworks: ['jasmine'],
files: ['src/**/*.spec.js'],
browsers: ['ChromeHeadless'],
singleRun: true,
reporters: ['progress', 'junit'],
});
};npx karma startImportant migration note: Karma is in maintenance-only mode as of 2023; AngularJS reached end-of-life Jan 2022; new Angular projects use Jest or Vitest. Karma + Jasmine setups are explicitly legacy.
Migration to Jest path
Jest's API is mostly compatible with Jasmine - typical migration steps:
For automated migration: jest-codemods package handles ~80% of the syntax transformations.
Related skills
ava-tests
Configures and runs AVA - concurrent-by-default JS/TS test framework with isolated test files (each file runs in its own Node process), no globals (explicit `import test from 'ava'`), async-first API, snapshot support, and TypeScript via `@ava/typescript`. Use when AVA is already the chosen framework and the user wants minimal-API parallel-by-default tests, works with libraries (vs apps) where per-file isolation prevents test interference, or is switching from Mocha for per-file process isolation Mocha cannot provide. For choosing between AVA and Mocha, or for Mocha-specific work, use mocha-tests.
jest-tests
Configures and runs Jest - Meta-built batteries-included JS/TS unit framework with built-in `expect`, snapshot testing, mocking (`jest.mock`, `jest.fn`, `jest.spyOn`, manual `__mocks__/`), test environment selection (`jsdom` / `node`), parallel workers, coverage via Istanbul, watch mode, and CI integration via `--ci` flag. Use when the user works with React (CRA / older Next.js) or Node services and needs the most ecosystem-supported JS test framework.
mocha-tests
Configures and runs Mocha - pluggable JS test runner pairable with Chai assertions, Sinon mocking, and nyc / c8 coverage; supports BDD interface (`describe` / `it`) and TDD interface (`suite` / `test`); async tests via callbacks / promises / async-await; `--parallel` mode (Mocha 8+); `.mocharc.json` config; per-test exclusivity via `.only()` / `.skip()`. Use when the user prefers a minimal pluggable runner (vs Jest's batteries-included) or maintains legacy Mocha codebases.
vitest-tests
Configures and runs Vitest - Vite-native unit framework with Jest-compatible API (`expect`, `vi.fn`, `vi.mock`, `vi.spyOn`); reads `vite.config.*` so existing Vite plugins work; supports in-source testing via `if (import.meta.vitest)`, browser-mode UI for headed tests, type-checking via `vitest --typecheck`, native ESM, and coverage via v8 (default) or istanbul providers. Use when the user works with Vite-based projects (Vue, Svelte, Solid, modern React with Vite) or is migrating from Jest on an existing Vite project (not bundler-free Node - use jest-tests for that).