DOM-less simple JavaScript BDD testing framework for Node.js
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Core BDD functions for writing test suites and specifications with jasmine-node. Includes support for test organization, setup/teardown, assertions, spies, and asynchronous testing.
Define test suites using the describe function to group related specifications.
/**
* Define a test suite with a descriptive name and specification functions
* @param description - Descriptive name for the test suite
* @param specDefinitions - Function containing it() calls and setup
*/
function describe(description: string, specDefinitions: () => void): void;
/**
* Skip/disable a test suite (will not be executed)
* @param description - Descriptive name for the skipped test suite
* @param specDefinitions - Function containing it() calls and setup
*/
function xdescribe(description: string, specDefinitions: () => void): void;Usage Examples:
describe("User Authentication", function() {
// Test specifications go here
it("should validate user credentials", function() {
// Test implementation
});
describe("Password Reset", function() {
// Nested describe blocks for sub-functionality
it("should send reset email", function() {
// Test implementation
});
});
});
// Skip entire test suite during development/debugging
xdescribe("Feature Under Development", function() {
it("should work eventually", function() {
// This won't run
});
});Define individual test specifications within describe blocks.
/**
* Define a test specification with optional timeout
* @param description - Descriptive name for the test
* @param specFunction - Test function, optionally accepting done callback
* @param timeout - Optional timeout in milliseconds (default: 5000)
*/
function it(description: string, specFunction: (done?: () => void) => void, timeout?: number): void;
/**
* Skip/disable a test specification (will not be executed)
* @param description - Descriptive name for the skipped test
* @param specFunction - Test function that won't be executed
*/
function xit(description: string, specFunction: () => void): void;Usage Examples:
describe("Calculator", function() {
it("should add two numbers", function() {
const result = add(2, 3);
expect(result).toEqual(5);
});
it("should handle async operations", function(done) {
setTimeout(function() {
expect(true).toBe(true);
done();
}, 100);
});
it("should timeout after custom duration", function(done) {
// This test will timeout after 1 second instead of default 5 seconds
setTimeout(done, 500);
}, 1000);
it("should handle async errors", function(done) {
setTimeout(function() {
try {
expect(false).toBe(true);
done();
} catch (error) {
done(error); // Pass error to done() to fail the test
}
}, 100);
});
// Skip this test during development
xit("should handle edge case", function() {
// This won't run
});
});Functions to run setup and teardown code before and after each test specification.
/**
* Run setup function before each test specification in the suite
* @param setupFunction - Function to run before each test, optionally accepting done callback
* @param timeout - Optional timeout in milliseconds for async setup
*/
function beforeEach(setupFunction: (done?: () => void) => void, timeout?: number): void;
/**
* Run teardown function after each test specification in the suite
* @param teardownFunction - Function to run after each test, optionally accepting done callback
* @param timeout - Optional timeout in milliseconds for async teardown
*/
function afterEach(teardownFunction: (done?: () => void) => void, timeout?: number): void;Usage Examples:
describe("Database Operations", function() {
let database;
beforeEach(function() {
database = new MockDatabase();
database.connect();
});
afterEach(function() {
database.disconnect();
database = null;
});
// Async setup and teardown
beforeEach(function(done) {
initializeTestData(function() {
done();
});
});
afterEach(function(done) {
cleanupTestData(function() {
done();
});
});
it("should save user data", function() {
const user = { name: "John", email: "john@example.com" };
const result = database.save(user);
expect(result.success).toBe(true);
});
});Create expectations and assertions using the expect function and built-in matchers.
/**
* Create an expectation for testing actual values
* @param actual - The actual value to test
* @returns Matchers object with assertion methods
*/
function expect(actual: any): jasmine.Matchers;
interface jasmine.Matchers {
/** Assert strict equality (===) */
toBe(expected: any): boolean;
/** Assert deep equality for objects and arrays */
toEqual(expected: any): boolean;
/** Assert string or regex match */
toMatch(expected: string | RegExp): boolean;
/** Assert value is null */
toBeNull(): boolean;
/** Assert value is undefined */
toBeUndefined(): boolean;
/** Assert value is truthy */
toBeTruthy(): boolean;
/** Assert value is falsy */
toBeFalsy(): boolean;
/** Assert array/string contains value */
toContain(expected: any): boolean;
/** Assert numeric greater than */
toBeGreaterThan(expected: number): boolean;
/** Assert numeric less than */
toBeLessThan(expected: number): boolean;
/** Assert function throws exception */
toThrow(expected?: any): boolean;
/** Assert spy was called (from jasmine-reporters) */
toHaveBeenCalled(): boolean;
/** Assert spy was called with specific arguments (from jasmine-reporters) */
toHaveBeenCalledWith(...args: any[]): boolean;
/** Negate any matcher */
not: jasmine.Matchers;
}Usage Examples:
describe("Matchers", function() {
it("should demonstrate basic matchers", function() {
expect(5).toBe(5); // Strict equality
expect({name: "John"}).toEqual({name: "John"}); // Deep equality
expect("hello world").toMatch(/world/); // Regex match
expect(null).toBeNull(); // Null check
expect(undefined).toBeUndefined(); // Undefined check
expect("truthy").toBeTruthy(); // Truthy check
expect(0).toBeFalsy(); // Falsy check
expect([1, 2, 3]).toContain(2); // Array contains
expect(10).toBeGreaterThan(5); // Numeric comparison
expect(3).toBeLessThan(10); // Numeric comparison
});
it("should demonstrate negation", function() {
expect(5).not.toBe(10);
expect("hello").not.toMatch(/goodbye/);
});
it("should test exceptions", function() {
expect(function() {
throw new Error("Something went wrong");
}).toThrow();
expect(function() {
throw new Error("Specific error");
}).toThrow("Specific error");
});
});Create spies for testing function calls, arguments, and return values.
/**
* Create a spy on an object method to track calls and control behavior
* @param object - Object containing the method to spy on
* @param method - Method name to spy on
* @returns Spy object with tracking and stubbing methods
*/
function spyOn(object: any, method: string): jasmine.Spy;
interface jasmine.Spy {
/** Make spy return specific value */
andReturn(value: any): jasmine.Spy;
/** Make spy throw specific exception */
andThrow(exception: any): jasmine.Spy;
/** Make spy call through to original method */
andCallThrough(): jasmine.Spy;
/** Make spy call fake function instead */
andCallFake(fakeFunction: Function): jasmine.Spy;
/** Array of all call objects */
calls: any[];
/** Most recent call object with args */
mostRecentCall: { args: any[] };
/** Array of argument arrays for each call */
argsForCall: any[][];
/** Number of times spy was called */
callCount: number;
}Usage Examples:
describe("User Service", function() {
let userService, httpClient;
beforeEach(function() {
httpClient = {
get: function() {},
post: function() {}
};
userService = new UserService(httpClient);
});
it("should call HTTP client with correct URL", function() {
spyOn(httpClient, 'get').andReturn({id: 1, name: "John"});
const user = userService.getUser(123);
expect(httpClient.get).toHaveBeenCalled();
expect(httpClient.get).toHaveBeenCalledWith('/users/123');
expect(httpClient.get.callCount).toBe(1);
expect(user.name).toBe("John");
});
it("should handle errors from HTTP client", function() {
spyOn(httpClient, 'get').andThrow(new Error("Network error"));
expect(function() {
userService.getUser(123);
}).toThrow("Network error");
});
it("should use fake implementation", function() {
spyOn(httpClient, 'post').andCallFake(function(url, data) {
return { success: true, id: 999 };
});
const result = userService.createUser({name: "Jane"});
expect(result.id).toBe(999);
});
});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.
/**
* Wait for asynchronous condition to become true
* @param latchFunction - Function that returns true when condition is met
* @param timeoutMessage - Message to display if timeout occurs
* @param timeout - Timeout in milliseconds (default: 5000)
*/
function waitsFor(latchFunction: () => boolean, timeoutMessage?: string, timeout?: number): void;
/**
* Wait for specified duration
* @param timeout - Time to wait in milliseconds
*/
function waits(timeout: number): void;
/**
* Execute function in test context (used with waits/waitsFor)
* @param asyncMethod - Function to execute
*/
function runs(asyncMethod: () => void): void;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.
The async callback implementation wraps the original test function and:
done() callback that marks the test as completedone() is not called within the timeout perioddone(error)Usage Examples:
describe("Async Operations", function() {
it("should handle async with done callback", function(done) {
setTimeout(function() {
expect(true).toBe(true);
done();
}, 100);
});
it("should use waitsFor pattern", function() {
let completed = false;
runs(function() {
setTimeout(function() {
completed = true;
}, 100);
});
waitsFor(function() {
return completed;
}, "operation to complete", 1000);
runs(function() {
expect(completed).toBe(true);
});
});
it("should use waits pattern", function() {
let value = 0;
runs(function() {
setTimeout(function() {
value = 42;
}, 50);
});
waits(100);
runs(function() {
expect(value).toBe(42);
});
});
});/**
* Get current Jasmine environment for configuration
* @returns Jasmine environment object
*/
function jasmine.getEnv(): jasmine.Env;
interface jasmine.Env {
/** Default timeout for async operations in milliseconds */
defaultTimeoutInterval: number;
/** Execute all registered specs */
execute(): void;
/** Add reporter to environment */
addReporter(reporter: any): void;
}Usage Examples:
// Set default timeout for all async tests
jasmine.getEnv().defaultTimeoutInterval = 10000;
// Add custom reporter
jasmine.getEnv().addReporter(new CustomReporter());