Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Add: custom assertion class for robust and type-safe testing ✨ #64

Open
wants to merge 38 commits into
base: master
Choose a base branch
from

Conversation

vidup
Copy link
Contributor

@vidup vidup commented Feb 9, 2025

Summary

This PR introduces a new, matcher-based, expect-style API assertion library within our @vdstack/mockit package. The goal is to provide developers with a more powerful, flexible, and type-safe way to write assertions, reducing test brittleness and focusing on the behavior that matters rather than requiring exact value matches.

Motivation:

Traditional assertions often force tests to assert on every detail of an object or value. This approach can lead to brittle tests that break due to non-critical changes. By using matcher-based assertions, tests can:

Decouple from implementation details: Only assert on the properties that truly matter.
Improve readability: The intent of tests becomes clear with matchers like m.anyString() or m.stringMatching(/@example\.com$/).
Enhance maintainability: Tests remain stable when the data structure evolves, unless the specific properties under test are changed.
Leverage type-safety: Our TypeScript integration ensures that assertions are checked at compile time, reducing runtime errors. It also helps developers at development time to write assertions faster.

Key Changes

Documentation Update

A new README is added that comprehensively documents the assertion library.
The README explains:

  • What matchers are and why they’re useful.
  • Detailed examples covering basic usage, primitive assertions, object matching (direct, partial, and deep), array matchers, string matchers, type matchers, error assertions, collection assertions, and custom validations.
  • Best practices for writing resilient tests.

Asserting on direct values

const user = {
  name: "John",
  age: 30,
  settings: {
    theme: "dark",
  },
};

m.expect(user).toEqual({
  name: "John",
  age: 30,
  settings: {
    theme: "dark",
  },
});

Partial Object Matching

When you only care about specific properties:

// Using nested objectContaining
m.expect(user).toEqual(
  m.objectContaining({
    settings: m.objectContaining({
      theme: "dark",
    }),
  })
);

Deep Object Matching

The most concise way to match nested objects:

// Using objectContainingDeep - cleaner and more maintainable
m.expect(user).toEqual(
  m.objectContainingDeep({
    settings: {
      theme: "dark",
    },
  })
);

Assertion Class Implementation

I added a new Assertion class that implements the following methods:

  • toEqual(expected: T): Supports both direct and function-based evaluations, enabling lazy assertions.
  • toThrow(expectedError?: unknown): Asserts that a function throws an error, optionally matching the error against a provided value.
  • toContain(expected): Checks if an array contains an element or if an object contains a subset of properties.
  • toResolve(expected?): Handles assertions for promises or functions returning promises.
  • toReject(expectedRejection?): Validates that a promise or async function rejects, with optional matching for the rejection value.

Exposed API

A new helper function expect<T>(actual: T) is exposed, which creates an instance of the Assertion class.
This API mirrors familiar patterns (similar to Jest's expect), making it easy for users to adopt:

import { m } from "@vdstack/mockit";
m.expect(something).toEqual(somethingElse);

@vidup vidup self-assigned this Feb 9, 2025
@vidup vidup added the enhancement New feature or request label Feb 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant