Jest Snippets
Mocking
- Mocking method-by-method
let state = {
set: jest.fn(),
get: jest.fn()
} as unknown as Map<string, string>;
- Spying on a method to verify behaviour
const state = new Map<string, string>();
const setSpy = jest.spyOn(state, 'set');
Matching
- Partial and nested object matching using
objectContaining
vstoMatchObject
// objectContaining, with nested object, containing full props/values
// PASSES
expect({ position: { x: 0, y: 0 } }).toEqual(expect.objectContaining({
position: {
x: expect.any(Number),
y: expect.any(Number)
}
}));
// objectContaining, with nested object, containing partial props/values
// FAILS
expect({ position: { x: 0, y: 0 } }).toEqual(expect.objectContaining({
position: {
x: expect.any(Number)
}
}));
// objectContaining, with nested object, also declared with objectContaining, containing partial props/values
// PASSES
expect({ position: { x: 0, y: 0 } }).toEqual(expect.objectContaining({
position: expect.objectContaining({
x: expect.any(Number)
})
}));
// toMatchObject, with nested object, containing full props/values
// PASSES
expect({ position: { x: 0, y: 0 } }).toMatchObject({
position: {
x: expect.any(Number),
y: expect.any(Number)
}
});
// toMatchObject, with nested object, containing partial props/values
// PASSES
expect({ position: { x: 0, y: 0 } }).toMatchObject({
position: {
x: expect.any(Number)
}
});
Jest Config
- jest.config.js
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
moduleFileExtensions: ['ts', 'js'],
transform: {
'^.+\\.ts?$': 'ts-jest',
},
collectCoverage: true,
coverageDirectory: 'coverage',
coverageReporters: ['text', 'lcov'],
verbose: true,
};
Custom Matchers
- Create matcher
custom-matcher.ts
// Function to check is UUID is valid
const isUUIDv4 = (str: string): boolean => {
const parts = str.split('-');
// Check if the UUID has the correct parts and lengths
if (
parts.length !== 5 ||
parts[0].length !== 8 ||
parts[1].length !== 4 ||
parts[2].length !== 4 ||
parts[3].length !== 4 ||
parts[4].length !== 12
) {
return false;
}
// Validate each part for correct hex characters
const isValidHex = (part: string) => /^[0-9a-f]+$/i.test(part);
if (!isValidHex(parts[0]) || !isValidHex(parts[1]) || !isValidHex(parts[2]) || !isValidHex(parts[3]) || !isValidHex(parts[4])) {
return false;
}
// Check that the version bit (4) is correct in the third section
if (parts[2][0] !== '4') {
return false;
}
// Check that the variant bits are correct (8, 9, a, b) in the fourth section
if (!/^[89ab]$/i.test(parts[3][0])) {
return false;
}
return true;
};
// Matchers
export const customMatchers = {
toBeUUIDv4(received: string) {
const pass = isUUIDv4(received);
if (pass) {
return {
message: () => `expected ${received} not to be a valid UUID`,
pass: true,
};
} else {
return {
message: () => `expected ${received} to be a valid UUID`,
pass: false,
};
}
},
- Extend matchers
expect.extend(customMatchers);
- Attach to
expect
injest.custom-matchers.d.ts
for Typescript
import 'jest';
declare global {
namespace jest {
interface Matchers<R> {
toBeUUIDv4(): R;
}
interface InverseAsymmetricMatchers {
toBeUUIDv4(): any
}
interface Expect {
toBeUUIDv4(): any
}
}
}