CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-jest-matchers

A comprehensive matcher library for Jest testing framework providing assertion utilities for test expectations

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

spy-mock-matchers.mddocs/

Spy and Mock Matchers

Verification matchers for Jest mock functions and spies, essential for testing function calls and interactions. These matchers allow you to verify that functions were called with the correct arguments, the right number of times, and in the expected order.

Capabilities

Basic Call Verification

toBeCalled / toHaveBeenCalled

Verifies that a mock function was called at least once.

/**
 * Checks if mock function was called at least once
 */
ExpectationObject.toBeCalled(): void;

/**
 * Alias for toBeCalled - checks if mock function was called
 */
ExpectationObject.toHaveBeenCalled(): void;

Usage Examples:

// Basic mock function testing
const mockFn = jest.fn();
mockFn();
expect(mockFn).toBeCalled();
expect(mockFn).toHaveBeenCalled();  // same as toBeCalled

// Testing event handlers
const onClickHandler = jest.fn();
const button = {
  click: () => onClickHandler()
};

button.click();
expect(onClickHandler).toHaveBeenCalled();

// Testing callback functions
function processData(data, callback) {
  // process data...
  callback(data);
}

const callback = jest.fn();
processData({id: 1}, callback);
expect(callback).toHaveBeenCalled();

Argument Verification

toBeCalledWith / toHaveBeenCalledWith

Verifies that a mock function was called with specific arguments at least once.

/**
 * Checks if mock function was called with specific arguments
 * @param args - Expected arguments the function should have been called with
 */
ExpectationObject.toBeCalledWith(...args: any[]): void;

/**
 * Alias for toBeCalledWith - checks function was called with specific arguments
 * @param args - Expected arguments the function should have been called with
 */
ExpectationObject.toHaveBeenCalledWith(...args: any[]): void;

Usage Examples:

const mockFn = jest.fn();
mockFn('hello', 42, {active: true});

expect(mockFn).toBeCalledWith('hello', 42, {active: true});
expect(mockFn).toHaveBeenCalledWith('hello', 42, {active: true});

// Testing API calls
const apiClient = {
  get: jest.fn()
};

await apiClient.get('/users', {limit: 10});
expect(apiClient.get).toHaveBeenCalledWith('/users', {limit: 10});

// Testing with partial matching using asymmetric matchers
const logger = jest.fn();
logger('Error', 'Something went wrong', {timestamp: new Date()});

expect(logger).toHaveBeenCalledWith(
  'Error',
  'Something went wrong',
  expect.objectContaining({timestamp: expect.any(Date)})
);

Call Count Verification

toHaveBeenCalledTimes

Verifies that a mock function was called a specific number of times.

/**
 * Checks if mock function was called specific number of times
 * @param number - Expected number of calls
 */
ExpectationObject.toHaveBeenCalledTimes(number: number): void;

Usage Examples:

const mockFn = jest.fn();

// Initially not called
expect(mockFn).toHaveBeenCalledTimes(0);

mockFn();
expect(mockFn).toHaveBeenCalledTimes(1);

mockFn();
mockFn();
expect(mockFn).toHaveBeenCalledTimes(3);

// Testing initialization functions
const initializeApp = jest.fn();
const app = new Application();
app.init();

expect(initializeApp).toHaveBeenCalledTimes(1);

// Testing event listeners
const eventHandler = jest.fn();
const emitter = new EventEmitter();
emitter.on('data', eventHandler);

emitter.emit('data', 'test1');
emitter.emit('data', 'test2');

expect(eventHandler).toHaveBeenCalledTimes(2);

Last Call Verification

lastCalledWith / toHaveBeenLastCalledWith

Verifies the arguments of the most recent call to a mock function.

/**
 * Checks if mock function was last called with specific arguments
 * @param args - Expected arguments from the most recent call
 */
ExpectationObject.lastCalledWith(...args: any[]): void;

/**
 * Alias for lastCalledWith - checks most recent call arguments
 * @param args - Expected arguments from the most recent call
 */
ExpectationObject.toHaveBeenLastCalledWith(...args: any[]): void;

Usage Examples:

const mockFn = jest.fn();

mockFn('first call');
mockFn('second call');
mockFn('third call');

expect(mockFn).lastCalledWith('third call');
expect(mockFn).toHaveBeenLastCalledWith('third call');

// Testing progressive updates
const updateProgress = jest.fn();

updateProgress('Starting...');
updateProgress('Processing...', 50);
updateProgress('Completed!', 100);

expect(updateProgress).toHaveBeenLastCalledWith('Completed!', 100);
expect(updateProgress).toHaveBeenCalledTimes(3);

// Testing state changes
const setState = jest.fn();

setState({loading: true});
setState({loading: false, data: []});
setState({loading: false, data: [1, 2, 3]});

expect(setState).toHaveBeenLastCalledWith({
  loading: false, 
  data: [1, 2, 3]
});

Advanced Usage Patterns

Testing Function Compositions

const mockTransform = jest.fn(x => x * 2);
const mockFilter = jest.fn(x => x > 5);
const mockMap = jest.fn(x => x.toString());

const pipeline = [1, 2, 3, 4, 5, 6]
  .map(mockTransform)
  .filter(mockFilter)
  .map(mockMap);

// Verify each function was called the right number of times
expect(mockTransform).toHaveBeenCalledTimes(6);
expect(mockFilter).toHaveBeenCalledTimes(6);
expect(mockMap).toHaveBeenCalledTimes(3);  // only items > 5 after transform

// Verify specific calls
expect(mockTransform).toHaveBeenCalledWith(1);
expect(mockTransform).toHaveBeenCalledWith(6);
expect(mockFilter).toHaveBeenCalledWith(12);  // 6 * 2
expect(mockMap).toHaveBeenLastCalledWith(12);

Testing Async Operations

const mockCallback = jest.fn();

async function processAsync(items, callback) {
  for (const item of items) {
    await new Promise(resolve => setTimeout(resolve, 10));
    callback(item);
  }
}

await processAsync(['a', 'b', 'c'], mockCallback);

expect(mockCallback).toHaveBeenCalledTimes(3);
expect(mockCallback).toHaveBeenNthCalledWith(1, 'a');
expect(mockCallback).toHaveBeenNthCalledWith(2, 'b');
expect(mockCallback).toHaveBeenLastCalledWith('c');

Testing Error Handling

const mockErrorHandler = jest.fn();
const mockSuccessHandler = jest.fn();

function processWithHandlers(data) {
  try {
    if (!data) throw new Error('No data provided');
    mockSuccessHandler(data);
  } catch (error) {
    mockErrorHandler(error);
  }
}

// Test error case
processWithHandlers(null);
expect(mockErrorHandler).toHaveBeenCalledWith(
  expect.objectContaining({message: 'No data provided'})
);
expect(mockSuccessHandler).not.toHaveBeenCalled();

// Reset mocks
mockErrorHandler.mockReset();
mockSuccessHandler.mockReset();

// Test success case
processWithHandlers({id: 1});
expect(mockSuccessHandler).toHaveBeenCalledWith({id: 1});
expect(mockErrorHandler).not.toHaveBeenCalled();

Testing Class Methods

class UserService {
  constructor(apiClient) {
    this.apiClient = apiClient;
  }

  async createUser(userData) {
    const user = await this.apiClient.post('/users', userData);
    this.logActivity('user_created', user.id);
    return user;
  }

  logActivity(action, userId) {
    // logging implementation
  }
}

// Test with mocked dependencies
const mockApiClient = {
  post: jest.fn().mockResolvedValue({id: 123, name: 'John'})
};

const userService = new UserService(mockApiClient);
userService.logActivity = jest.fn();

const userData = {name: 'John', email: 'john@example.com'};
const result = await userService.createUser(userData);

expect(mockApiClient.post).toHaveBeenCalledWith('/users', userData);
expect(userService.logActivity).toHaveBeenCalledWith('user_created', 123);
expect(mockApiClient.post).toHaveBeenCalledTimes(1);

Integration with Asymmetric Matchers

Spy matchers work well with asymmetric matchers for flexible argument verification:

const mockFn = jest.fn();

mockFn('test', {timestamp: new Date(), id: 123});

expect(mockFn).toHaveBeenCalledWith(
  expect.any(String),
  expect.objectContaining({
    timestamp: expect.any(Date),
    id: expect.any(Number)
  })
);

Negation Support

All spy matchers support negation:

const mockFn = jest.fn();

expect(mockFn).not.toHaveBeenCalled();

mockFn('test');
expect(mockFn).not.toHaveBeenCalledWith('different');
expect(mockFn).not.toHaveBeenCalledTimes(2);

Promise Support

Spy matchers work with promises when testing async mock functions:

const asyncMock = jest.fn().mockResolvedValue('result');

await asyncMock('test');

await expect(Promise.resolve(asyncMock)).resolves.toHaveBeenCalledWith('test');

docs

asymmetric-matchers.md

collection-string-matchers.md

configuration-extension.md

core-matchers.md

exception-matchers.md

index.md

numeric-matchers.md

spy-mock-matchers.md

tile.json