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

asymmetric-matchers.mddocs/

Asymmetric Matchers

Special matchers for flexible pattern matching and partial object comparison. These matchers allow for more flexible assertions when exact matching is not practical or desired.

Capabilities

General Matching

expect.anything

Matches any value except null and undefined.

/**
 * Matches anything except null or undefined
 * @returns Anything matcher instance
 */
expect.anything(): Anything;

Usage Examples:

// Use in arrays
expect(['alice', 'bob', 'charlie']).toEqual([
  'alice',
  expect.anything(),
  'charlie'
]);

// Use in objects
expect({
  name: 'John',
  id: 123,
  timestamp: new Date()
}).toEqual({
  name: 'John',
  id: expect.anything(),
  timestamp: expect.anything()
});

// Use with function calls
const mockFn = jest.fn();
mockFn('hello', 42, true);

expect(mockFn).toHaveBeenCalledWith(
  'hello',
  expect.anything(),
  expect.anything()
);

// Won't match null or undefined
expect({value: null}).not.toEqual({value: expect.anything()});
expect({value: undefined}).not.toEqual({value: expect.anything()});

expect.any

Matches any instance of the specified constructor or type.

/**
 * Matches any instance of given constructor
 * @param constructor - Constructor function or class to match against
 * @returns Any matcher instance
 */
expect.any(constructor: Function): Any;

Usage Examples:

// Primitive types
expect('hello').toEqual(expect.any(String));
expect(42).toEqual(expect.any(Number));
expect(true).toEqual(expect.any(Boolean));

// Object types
expect(new Date()).toEqual(expect.any(Date));
expect([1, 2, 3]).toEqual(expect.any(Array));
expect(/regex/).toEqual(expect.any(RegExp));
expect(new Error('test')).toEqual(expect.any(Error));

// Custom classes
class User {
  constructor(name) {
    this.name = name;
  }
}

const user = new User('John');
expect(user).toEqual(expect.any(User));

// Use in complex objects
expect({
  user: new User('John'),
  createdAt: new Date(),
  tags: ['admin', 'active']
}).toEqual({
  user: expect.any(User),
  createdAt: expect.any(Date),
  tags: expect.any(Array)
});

// Use with mock function verification
const mockCallback = jest.fn();
mockCallback(new Error('something failed'));

expect(mockCallback).toHaveBeenCalledWith(expect.any(Error));

Object Matching

expect.objectContaining

Matches objects that contain the specified properties (subset matching).

/**
 * Matches objects containing provided properties
 * @param object - Object with properties that should be present
 * @returns ObjectContaining matcher instance
 */
expect.objectContaining(object: Object): ObjectContaining;

Usage Examples:

// Basic object containment
const user = {
  id: 1,
  name: 'John',
  email: 'john@example.com',
  preferences: {theme: 'dark'},
  roles: ['user', 'admin']
};

expect(user).toEqual(expect.objectContaining({
  name: 'John',
  email: 'john@example.com'
}));

// Nested object containment
expect(user).toEqual(expect.objectContaining({
  preferences: expect.objectContaining({
    theme: 'dark'
  })
}));

// Use in arrays
expect([
  {id: 1, name: 'John'},
  {id: 2, name: 'Jane'},
  {id: 3, name: 'Bob'}
]).toContainEqual(expect.objectContaining({name: 'Jane'}));

// API response testing
const apiResponse = {
  data: {id: 123, name: 'John'},
  metadata: {timestamp: '2023-01-01', version: '1.0'},
  status: 'success'
};

expect(apiResponse).toEqual(expect.objectContaining({
  data: expect.objectContaining({id: 123}),
  status: 'success'
}));

// Mock function verification
const mockFn = jest.fn();
mockFn({name: 'John', age: 30, city: 'New York'});

expect(mockFn).toHaveBeenCalledWith(
  expect.objectContaining({name: 'John', age: 30})
);

Array Matching

expect.arrayContaining

Matches arrays that contain all of the specified elements.

/**
 * Matches arrays containing all provided elements
 * @param array - Array with elements that should be present
 * @returns ArrayContaining matcher instance
 */
expect.arrayContaining(array: Array): ArrayContaining;

Usage Examples:

// Basic array containment
expect(['a', 'b', 'c', 'd', 'e']).toEqual(
  expect.arrayContaining(['a', 'c', 'e'])
);

// Order doesn't matter
expect(['z', 'y', 'x']).toEqual(
  expect.arrayContaining(['x', 'z'])
);

// Works with objects
expect([
  {name: 'Alice', age: 25},
  {name: 'Bob', age: 30},
  {name: 'Charlie', age: 35}
]).toEqual(expect.arrayContaining([
  {name: 'Alice', age: 25},
  {name: 'Charlie', age: 35}
]));

// Nested in objects
expect({
  users: ['john', 'jane', 'bob'],
  admins: ['alice', 'charlie']
}).toEqual({
  users: expect.arrayContaining(['john', 'jane']),
  admins: expect.arrayContaining(['alice'])
});

// Testing API responses
const searchResults = {
  results: [
    {id: 1, title: 'First Post'},
    {id: 2, title: 'Second Post'},
    {id: 3, title: 'Third Post'}
  ]
};

expect(searchResults).toEqual({
  results: expect.arrayContaining([
    expect.objectContaining({title: 'First Post'}),
    expect.objectContaining({title: 'Third Post'})
  ])
});

String Matching

expect.stringContaining

Matches strings that contain the specified substring.

/**
 * Matches strings containing provided substring
 * @param string - Substring that should be present
 * @returns StringContaining matcher instance
 */
expect.stringContaining(string: string): StringContaining;

Usage Examples:

// Basic substring matching
expect('Hello World').toEqual(expect.stringContaining('World'));
expect('JavaScript is awesome').toEqual(expect.stringContaining('Script'));

// Case sensitive
expect('Hello World').toEqual(expect.stringContaining('World'));
expect('Hello World').not.toEqual(expect.stringContaining('world'));

// Use in objects
expect({
  message: 'User registration successful',
  details: 'Account created for user@example.com'
}).toEqual({
  message: expect.stringContaining('successful'),
  details: expect.stringContaining('user@example.com')
});

// Use in arrays
expect(['error: file not found', 'warning: deprecated method']).toEqual([
  expect.stringContaining('error:'),
  expect.stringContaining('warning:')
]);

// Testing log messages
const logMessages = [
  'INFO: Application started',
  'DEBUG: Database connected',
  'ERROR: Failed to process request'
];

expect(logMessages).toEqual(expect.arrayContaining([
  expect.stringContaining('Application started'),
  expect.stringContaining('ERROR:')
]));

expect.stringMatching

Matches strings that match the specified regular expression pattern.

/**
 * Matches strings matching provided pattern or regex
 * @param pattern - String pattern or RegExp to match against
 * @returns StringMatching matcher instance
 */
expect.stringMatching(pattern: string | RegExp): StringMatching;

Usage Examples:

// Basic regex matching
expect('hello@example.com').toEqual(
  expect.stringMatching(/^[\w\.-]+@[\w\.-]+\.\w+$/)
);

expect('2023-12-25').toEqual(
  expect.stringMatching(/^\d{4}-\d{2}-\d{2}$/)
);

// String pattern matching
expect('user123').toEqual(expect.stringMatching('user'));

// Case insensitive matching
expect('JavaScript').toEqual(expect.stringMatching(/javascript/i));

// Use in complex objects
expect({
  user: {
    email: 'john.doe@company.com',
    phone: '(555) 123-4567',
    id: 'user_abc123'
  }
}).toEqual({
  user: {
    email: expect.stringMatching(/@company\.com$/),
    phone: expect.stringMatching(/^\(\d{3}\) \d{3}-\d{4}$/),
    id: expect.stringMatching(/^user_/)
  }
});

// Testing URL patterns
const apiUrls = [
  'https://api.example.com/v1/users',
  'https://api.example.com/v1/posts',
  'https://api.example.com/v2/comments'
];

expect(apiUrls).toEqual(expect.arrayContaining([
  expect.stringMatching(/\/v1\/users$/),
  expect.stringMatching(/\/v2\//)
]));

Advanced Usage Patterns

Combining Asymmetric Matchers

// Complex nested matching
const complexObject = {
  user: {
    id: 'user_123',
    profile: {
      name: 'John Doe',
      email: 'john@example.com',
      settings: {
        notifications: true,
        preferences: ['email', 'sms']
      }
    }
  },
  metadata: {
    createdAt: new Date(),
    version: '1.2.3'
  }
};

expect(complexObject).toEqual({
  user: expect.objectContaining({
    id: expect.stringMatching(/^user_/),
    profile: expect.objectContaining({
      name: expect.any(String),
      email: expect.stringContaining('@'),
      settings: expect.objectContaining({
        preferences: expect.arrayContaining(['email'])
      })
    })
  }),
  metadata: expect.objectContaining({
    createdAt: expect.any(Date),
    version: expect.stringMatching(/^\d+\.\d+\.\d+$/)
  })
});

Testing API Responses

// Testing flexible API response structure
const apiResponse = {
  data: [
    {id: 1, name: 'John', email: 'john@test.com', createdAt: '2023-01-01T00:00:00Z'},
    {id: 2, name: 'Jane', email: 'jane@test.com', createdAt: '2023-01-02T00:00:00Z'}
  ],
  pagination: {
    total: 2,
    page: 1,
    perPage: 10
  },
  meta: {
    requestId: 'req_abc123',
    timestamp: 1672531200000
  }
};

expect(apiResponse).toEqual({
  data: expect.arrayContaining([
    expect.objectContaining({
      id: expect.any(Number),
      name: expect.any(String),
      email: expect.stringMatching(/@test\.com$/),
      createdAt: expect.stringMatching(/^\d{4}-\d{2}-\d{2}T/)
    })
  ]),
  pagination: expect.objectContaining({
    total: expect.any(Number),
    page: 1
  }),
  meta: expect.objectContaining({
    requestId: expect.stringMatching(/^req_/),
    timestamp: expect.any(Number)
  })
});

Testing Event Data

// Testing event payloads with flexible structure
function trackEvent(eventName, properties) {
  // Event tracking implementation
}

const trackEventSpy = jest.fn();
trackEventSpy('user_signup', {
  userId: 'user_123',
  email: 'user@example.com',
  timestamp: Date.now(),
  source: 'web',
  properties: {
    plan: 'premium',
    referrer: 'google'
  }
});

expect(trackEventSpy).toHaveBeenCalledWith(
  'user_signup',
  expect.objectContaining({
    userId: expect.stringMatching(/^user_/),
    email: expect.stringContaining('@'),
    timestamp: expect.any(Number),
    source: expect.any(String),
    properties: expect.objectContaining({
      plan: expect.any(String)
    })
  })
);

Using with Regular Matchers

Asymmetric matchers can be combined with regular matchers:

const mockFn = jest.fn();
mockFn('hello', {id: 123, name: 'John'}, ['a', 'b', 'c']);

expect(mockFn).toHaveBeenCalledWith(
  'hello',  // exact match
  expect.objectContaining({id: 123}),  // asymmetric match
  expect.arrayContaining(['a', 'c'])   // asymmetric match
);

Negation Support

Asymmetric matchers support negation:

expect('hello').not.toEqual(expect.stringContaining('world'));
expect([1, 2, 3]).not.toEqual(expect.arrayContaining([4, 5]));
expect({a: 1}).not.toEqual(expect.objectContaining({b: 2}));

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