0
# Test Writing
1
2
Core BDD functions for writing test suites and specifications with jasmine-node. Includes support for test organization, setup/teardown, assertions, spies, and asynchronous testing.
3
4
## Capabilities
5
6
### Test Suite Definition
7
8
Define test suites using the describe function to group related specifications.
9
10
```javascript { .api }
11
/**
12
* Define a test suite with a descriptive name and specification functions
13
* @param description - Descriptive name for the test suite
14
* @param specDefinitions - Function containing it() calls and setup
15
*/
16
function describe(description: string, specDefinitions: () => void): void;
17
18
/**
19
* Skip/disable a test suite (will not be executed)
20
* @param description - Descriptive name for the skipped test suite
21
* @param specDefinitions - Function containing it() calls and setup
22
*/
23
function xdescribe(description: string, specDefinitions: () => void): void;
24
```
25
26
**Usage Examples:**
27
28
```javascript
29
describe("User Authentication", function() {
30
// Test specifications go here
31
it("should validate user credentials", function() {
32
// Test implementation
33
});
34
35
describe("Password Reset", function() {
36
// Nested describe blocks for sub-functionality
37
it("should send reset email", function() {
38
// Test implementation
39
});
40
});
41
});
42
43
// Skip entire test suite during development/debugging
44
xdescribe("Feature Under Development", function() {
45
it("should work eventually", function() {
46
// This won't run
47
});
48
});
49
```
50
51
### Test Specification
52
53
Define individual test specifications within describe blocks.
54
55
```javascript { .api }
56
/**
57
* Define a test specification with optional timeout
58
* @param description - Descriptive name for the test
59
* @param specFunction - Test function, optionally accepting done callback
60
* @param timeout - Optional timeout in milliseconds (default: 5000)
61
*/
62
function it(description: string, specFunction: (done?: () => void) => void, timeout?: number): void;
63
64
/**
65
* Skip/disable a test specification (will not be executed)
66
* @param description - Descriptive name for the skipped test
67
* @param specFunction - Test function that won't be executed
68
*/
69
function xit(description: string, specFunction: () => void): void;
70
```
71
72
**Usage Examples:**
73
74
```javascript
75
describe("Calculator", function() {
76
it("should add two numbers", function() {
77
const result = add(2, 3);
78
expect(result).toEqual(5);
79
});
80
81
it("should handle async operations", function(done) {
82
setTimeout(function() {
83
expect(true).toBe(true);
84
done();
85
}, 100);
86
});
87
88
it("should timeout after custom duration", function(done) {
89
// This test will timeout after 1 second instead of default 5 seconds
90
setTimeout(done, 500);
91
}, 1000);
92
93
it("should handle async errors", function(done) {
94
setTimeout(function() {
95
try {
96
expect(false).toBe(true);
97
done();
98
} catch (error) {
99
done(error); // Pass error to done() to fail the test
100
}
101
}, 100);
102
});
103
104
// Skip this test during development
105
xit("should handle edge case", function() {
106
// This won't run
107
});
108
});
109
```
110
111
### Setup and Teardown
112
113
Functions to run setup and teardown code before and after each test specification.
114
115
```javascript { .api }
116
/**
117
* Run setup function before each test specification in the suite
118
* @param setupFunction - Function to run before each test, optionally accepting done callback
119
* @param timeout - Optional timeout in milliseconds for async setup
120
*/
121
function beforeEach(setupFunction: (done?: () => void) => void, timeout?: number): void;
122
123
/**
124
* Run teardown function after each test specification in the suite
125
* @param teardownFunction - Function to run after each test, optionally accepting done callback
126
* @param timeout - Optional timeout in milliseconds for async teardown
127
*/
128
function afterEach(teardownFunction: (done?: () => void) => void, timeout?: number): void;
129
```
130
131
**Usage Examples:**
132
133
```javascript
134
describe("Database Operations", function() {
135
let database;
136
137
beforeEach(function() {
138
database = new MockDatabase();
139
database.connect();
140
});
141
142
afterEach(function() {
143
database.disconnect();
144
database = null;
145
});
146
147
// Async setup and teardown
148
beforeEach(function(done) {
149
initializeTestData(function() {
150
done();
151
});
152
});
153
154
afterEach(function(done) {
155
cleanupTestData(function() {
156
done();
157
});
158
});
159
160
it("should save user data", function() {
161
const user = { name: "John", email: "john@example.com" };
162
const result = database.save(user);
163
expect(result.success).toBe(true);
164
});
165
});
166
```
167
168
### Expectations and Matchers
169
170
Create expectations and assertions using the expect function and built-in matchers.
171
172
```javascript { .api }
173
/**
174
* Create an expectation for testing actual values
175
* @param actual - The actual value to test
176
* @returns Matchers object with assertion methods
177
*/
178
function expect(actual: any): jasmine.Matchers;
179
180
interface jasmine.Matchers {
181
/** Assert strict equality (===) */
182
toBe(expected: any): boolean;
183
/** Assert deep equality for objects and arrays */
184
toEqual(expected: any): boolean;
185
/** Assert string or regex match */
186
toMatch(expected: string | RegExp): boolean;
187
/** Assert value is null */
188
toBeNull(): boolean;
189
/** Assert value is undefined */
190
toBeUndefined(): boolean;
191
/** Assert value is truthy */
192
toBeTruthy(): boolean;
193
/** Assert value is falsy */
194
toBeFalsy(): boolean;
195
/** Assert array/string contains value */
196
toContain(expected: any): boolean;
197
/** Assert numeric greater than */
198
toBeGreaterThan(expected: number): boolean;
199
/** Assert numeric less than */
200
toBeLessThan(expected: number): boolean;
201
/** Assert function throws exception */
202
toThrow(expected?: any): boolean;
203
/** Assert spy was called (from jasmine-reporters) */
204
toHaveBeenCalled(): boolean;
205
/** Assert spy was called with specific arguments (from jasmine-reporters) */
206
toHaveBeenCalledWith(...args: any[]): boolean;
207
/** Negate any matcher */
208
not: jasmine.Matchers;
209
}
210
```
211
212
**Usage Examples:**
213
214
```javascript
215
describe("Matchers", function() {
216
it("should demonstrate basic matchers", function() {
217
expect(5).toBe(5); // Strict equality
218
expect({name: "John"}).toEqual({name: "John"}); // Deep equality
219
expect("hello world").toMatch(/world/); // Regex match
220
expect(null).toBeNull(); // Null check
221
expect(undefined).toBeUndefined(); // Undefined check
222
expect("truthy").toBeTruthy(); // Truthy check
223
expect(0).toBeFalsy(); // Falsy check
224
expect([1, 2, 3]).toContain(2); // Array contains
225
expect(10).toBeGreaterThan(5); // Numeric comparison
226
expect(3).toBeLessThan(10); // Numeric comparison
227
});
228
229
it("should demonstrate negation", function() {
230
expect(5).not.toBe(10);
231
expect("hello").not.toMatch(/goodbye/);
232
});
233
234
it("should test exceptions", function() {
235
expect(function() {
236
throw new Error("Something went wrong");
237
}).toThrow();
238
239
expect(function() {
240
throw new Error("Specific error");
241
}).toThrow("Specific error");
242
});
243
});
244
```
245
246
### Spies and Mocking
247
248
Create spies for testing function calls, arguments, and return values.
249
250
```javascript { .api }
251
/**
252
* Create a spy on an object method to track calls and control behavior
253
* @param object - Object containing the method to spy on
254
* @param method - Method name to spy on
255
* @returns Spy object with tracking and stubbing methods
256
*/
257
function spyOn(object: any, method: string): jasmine.Spy;
258
259
interface jasmine.Spy {
260
/** Make spy return specific value */
261
andReturn(value: any): jasmine.Spy;
262
/** Make spy throw specific exception */
263
andThrow(exception: any): jasmine.Spy;
264
/** Make spy call through to original method */
265
andCallThrough(): jasmine.Spy;
266
/** Make spy call fake function instead */
267
andCallFake(fakeFunction: Function): jasmine.Spy;
268
/** Array of all call objects */
269
calls: any[];
270
/** Most recent call object with args */
271
mostRecentCall: { args: any[] };
272
/** Array of argument arrays for each call */
273
argsForCall: any[][];
274
/** Number of times spy was called */
275
callCount: number;
276
}
277
```
278
279
**Usage Examples:**
280
281
```javascript
282
describe("User Service", function() {
283
let userService, httpClient;
284
285
beforeEach(function() {
286
httpClient = {
287
get: function() {},
288
post: function() {}
289
};
290
userService = new UserService(httpClient);
291
});
292
293
it("should call HTTP client with correct URL", function() {
294
spyOn(httpClient, 'get').andReturn({id: 1, name: "John"});
295
296
const user = userService.getUser(123);
297
298
expect(httpClient.get).toHaveBeenCalled();
299
expect(httpClient.get).toHaveBeenCalledWith('/users/123');
300
expect(httpClient.get.callCount).toBe(1);
301
expect(user.name).toBe("John");
302
});
303
304
it("should handle errors from HTTP client", function() {
305
spyOn(httpClient, 'get').andThrow(new Error("Network error"));
306
307
expect(function() {
308
userService.getUser(123);
309
}).toThrow("Network error");
310
});
311
312
it("should use fake implementation", function() {
313
spyOn(httpClient, 'post').andCallFake(function(url, data) {
314
return { success: true, id: 999 };
315
});
316
317
const result = userService.createUser({name: "Jane"});
318
expect(result.id).toBe(999);
319
});
320
});
321
```
322
323
### Asynchronous Testing
324
325
jasmine-node provides multiple patterns for handling asynchronous operations in tests. The primary approach uses the `done` callback pattern, with additional support for waits, waitsFor, and runs.
326
327
```javascript { .api }
328
/**
329
* Wait for asynchronous condition to become true
330
* @param latchFunction - Function that returns true when condition is met
331
* @param timeoutMessage - Message to display if timeout occurs
332
* @param timeout - Timeout in milliseconds (default: 5000)
333
*/
334
function waitsFor(latchFunction: () => boolean, timeoutMessage?: string, timeout?: number): void;
335
336
/**
337
* Wait for specified duration
338
* @param timeout - Time to wait in milliseconds
339
*/
340
function waits(timeout: number): void;
341
342
/**
343
* Execute function in test context (used with waits/waitsFor)
344
* @param asyncMethod - Function to execute
345
*/
346
function runs(asyncMethod: () => void): void;
347
```
348
349
#### Done Callback Pattern
350
351
jasmine-node enhances the standard Jasmine framework with automatic detection of asynchronous specs. When a test function accepts a parameter (typically named `done`), jasmine-node automatically treats it as an asynchronous test and provides a callback function that must be called to complete the test.
352
353
The async callback implementation wraps the original test function and:
354
- Detects when a function parameter is present (indicating async)
355
- Provides a `done()` callback that marks the test as complete
356
- Automatically fails the test if `done()` is not called within the timeout period
357
- Supports error handling by passing an error to `done(error)`
358
359
**Usage Examples:**
360
361
```javascript
362
describe("Async Operations", function() {
363
it("should handle async with done callback", function(done) {
364
setTimeout(function() {
365
expect(true).toBe(true);
366
done();
367
}, 100);
368
});
369
370
it("should use waitsFor pattern", function() {
371
let completed = false;
372
373
runs(function() {
374
setTimeout(function() {
375
completed = true;
376
}, 100);
377
});
378
379
waitsFor(function() {
380
return completed;
381
}, "operation to complete", 1000);
382
383
runs(function() {
384
expect(completed).toBe(true);
385
});
386
});
387
388
it("should use waits pattern", function() {
389
let value = 0;
390
391
runs(function() {
392
setTimeout(function() {
393
value = 42;
394
}, 50);
395
});
396
397
waits(100);
398
399
runs(function() {
400
expect(value).toBe(42);
401
});
402
});
403
});
404
```
405
406
## Global Environment Access
407
408
```javascript { .api }
409
/**
410
* Get current Jasmine environment for configuration
411
* @returns Jasmine environment object
412
*/
413
function jasmine.getEnv(): jasmine.Env;
414
415
interface jasmine.Env {
416
/** Default timeout for async operations in milliseconds */
417
defaultTimeoutInterval: number;
418
/** Execute all registered specs */
419
execute(): void;
420
/** Add reporter to environment */
421
addReporter(reporter: any): void;
422
}
423
```
424
425
**Usage Examples:**
426
427
```javascript
428
// Set default timeout for all async tests
429
jasmine.getEnv().defaultTimeoutInterval = 10000;
430
431
// Add custom reporter
432
jasmine.getEnv().addReporter(new CustomReporter());
433
```