Jasmine Testing Skill
Core Patterns
Basic Test
describe('Calculator', () => {
let calc;
beforeEach(() => { calc = new Calculator(); });
it('should add two numbers', () => {
expect(calc.add(2, 3)).toBe(5);
});
it('should throw on divide by zero', () => {
expect(() => calc.divide(10, 0)).toThrowError('Division by zero');
});
});
Matchers
expect(value).toBe(exact); // === strict
expect(value).toEqual(object); // Deep equality
expect(value).toBeTruthy();
expect(value).toBeFalsy();
expect(value).toBeNull();
expect(value).toBeUndefined();
expect(value).toBeDefined();
expect(value).toBeNaN();
expect(value).toBeGreaterThan(3);
expect(value).toBeCloseTo(0.3, 5);
expect(str).toContain('sub');
expect(str).toMatch(/pattern/);
expect(arr).toContain(item);
expect(fn).toThrow();
expect(fn).toThrowError('message');
// Negation
expect(value).not.toBe(other);
Spies
describe('UserService', () => {
let service, api;
beforeEach(() => {
api = jasmine.createSpyObj('api', ['get', 'post']);
service = new UserService(api);
});
it('fetches user from API', async () => {
api.get.and.returnValue(Promise.resolve({ name: 'Alice' }));
const user = await service.getUser(1);
expect(user.name).toBe('Alice');
expect(api.get).toHaveBeenCalledWith('/users/1');
expect(api.get).toHaveBeenCalledTimes(1);
});
});
// Spy on existing method
spyOn(obj, 'method').and.returnValue(42);
spyOn(obj, 'method').and.callThrough(); // Call original
spyOn(obj, 'method').and.throwError('err');
Async Testing
it('fetches data', async () => {
const data = await fetchData();
expect(data).toBeDefined();
});
// With done callback
it('fetches data', (done) => {
fetchData().then(data => {
expect(data).toBeDefined();
done();
});
});
// Clock control
beforeEach(() => { jasmine.clock().install(); });
afterEach(() => { jasmine.clock().uninstall(); });
it('handles timeout', () => {
const callback = jasmine.createSpy();
setTimeout(callback, 1000);
jasmine.clock().tick(1001);
expect(callback).toHaveBeenCalled();
});
Setup: npm install jasmine --save-dev && npx jasmine init
Run: npx jasmine or npx jasmine spec/calculatorSpec.js
Deep Patterns
See reference/playbook.md for production-grade patterns:
| Section |
What You Get |
| §1 Project Setup |
jasmine.json, TypeScript, spec reporter config |
| §2 Spies — Complete API |
spyOn, createSpyObj, callFake, returnValues, call tracking |
| §3 Async Testing |
async/await, expectAsync, promise matchers |
| §4 Custom Matchers |
Domain-specific matchers, asymmetric matchers |
| §5 Test Organization |
Nested describe, shared state, focused/excluded |
| §6 Fetch & Module Mocking |
globalThis.fetch spy, HTTP error handling |
| §7 Browser Testing |
DOM creation, keyboard events, focus trapping with Karma |
| §8 CI/CD Integration |
GitHub Actions with coverage, browser testing |
| §9 Debugging Table |
12 common problems with causes and fixes |
| §10 Best Practices |
14-item checklist for production Jasmine testing |
1---2name: jasmine-skill3description: Generates Jasmine tests in JavaScript. BDD-style framework with spies and async support. Use when user mentions "Jasmine", "jasmine.createSpy", "toHaveBeenCalled". Triggers on: "Jasmine", "jasmine test", "createSpy", "Jasmine spec".4license: MIT5---6
7# Jasmine Testing Skill
8
9## Core Patterns
10
11### Basic Test
12
13```javascript
14describe('Calculator', () => {
15 let calc;
16
17 beforeEach(() => { calc = new Calculator(); });
18
19 it('should add two numbers', () => {
20 expect(calc.add(2, 3)).toBe(5);
21 });
22
23 it('should throw on divide by zero', () => {
24 expect(() => calc.divide(10, 0)).toThrowError('Division by zero');
25 });
26});
27```
28
29### Matchers
30
31```javascript
32expect(value).toBe(exact); // === strict
33expect(value).toEqual(object); // Deep equality
34expect(value).toBeTruthy();
35expect(value).toBeFalsy();
36expect(value).toBeNull();
37expect(value).toBeUndefined();
38expect(value).toBeDefined();
39expect(value).toBeNaN();
40expect(value).toBeGreaterThan(3);
41expect(value).toBeCloseTo(0.3, 5);
42expect(str).toContain('sub');
43expect(str).toMatch(/pattern/);
44expect(arr).toContain(item);
45expect(fn).toThrow();
46expect(fn).toThrowError('message');
47
48// Negation
49expect(value).not.toBe(other);
50```
51
52### Spies
53
54```javascript
55describe('UserService', () => {
56 let service, api;
57
58 beforeEach(() => {
59 api = jasmine.createSpyObj('api', ['get', 'post']);
60 service = new UserService(api);
61 });
62
63 it('fetches user from API', async () => {
64 api.get.and.returnValue(Promise.resolve({ name: 'Alice' }));
65 const user = await service.getUser(1);
66 expect(user.name).toBe('Alice');
67 expect(api.get).toHaveBeenCalledWith('/users/1');
68 expect(api.get).toHaveBeenCalledTimes(1);
69 });
70});
71
72// Spy on existing method
73spyOn(obj, 'method').and.returnValue(42);
74spyOn(obj, 'method').and.callThrough(); // Call original
75spyOn(obj, 'method').and.throwError('err');
76```
77
78### Async Testing
79
80```javascript
81it('fetches data', async () => {
82 const data = await fetchData();
83 expect(data).toBeDefined();
84});
85
86// With done callback
87it('fetches data', (done) => {
88 fetchData().then(data => {
89 expect(data).toBeDefined();
90 done();
91 });
92});
93
94// Clock control
95beforeEach(() => { jasmine.clock().install(); });
96afterEach(() => { jasmine.clock().uninstall(); });
97
98it('handles timeout', () => {
99 const callback = jasmine.createSpy();
100 setTimeout(callback, 1000);
101 jasmine.clock().tick(1001);
102 expect(callback).toHaveBeenCalled();
103});
104```
105
106## Setup: `npm install jasmine --save-dev && npx jasmine init`
107## Run: `npx jasmine` or `npx jasmine spec/calculatorSpec.js`
108
109## Deep Patterns
110
111See `reference/playbook.md` for production-grade patterns:
112
113| Section | What You Get |
114|---------|-------------|
115| §1 Project Setup | jasmine.json, TypeScript, spec reporter config |
116| §2 Spies — Complete API | spyOn, createSpyObj, callFake, returnValues, call tracking |
117| §3 Async Testing | async/await, expectAsync, promise matchers |
118| §4 Custom Matchers | Domain-specific matchers, asymmetric matchers |
119| §5 Test Organization | Nested describe, shared state, focused/excluded |
120| §6 Fetch & Module Mocking | globalThis.fetch spy, HTTP error handling |
121| §7 Browser Testing | DOM creation, keyboard events, focus trapping with Karma |
122| §8 CI/CD Integration | GitHub Actions with coverage, browser testing |
123| §9 Debugging Table | 12 common problems with causes and fixes |
124| §10 Best Practices | 14-item checklist for production Jasmine testing |