jest-traitful

A bundle of Jest matchers for simplifying testing traitful JavaScript

Usage no npm install needed!

<script type="module">
  import jestTraitful from 'https://cdn.skypack.dev/jest-traitful';
</script>

README

jest-traitful

🃏🐯

A bundle of Jest matchers for simplifying testing traitful JavaScript


Build Status version downloads MIT License PRs Welcome

Problem

While using Traitful JavaScript it could often be hard to assert your structs

Solution

jest-traitful aims to add additional matchers to Jest's default ones that simplifying testing traitful structs

Contributing

If you've come here to help contribute - Sweet! Thanks! Take a look at the contributing and read the Code of Conduct docs as a way of getting started!


Installation

With npm:

npm install -D jest-traitful

With yarn:

yarn add -D jest-traitful

Setup

Jest >v24

Add jest-traitful to your Jest setupFilesAfterEnv configuration. See for help

"jest": {
  "setupFilesAfterEnv": ["jest-traitful"]
}

Asymmetric matchers

All matchers described below have asymmetric variants. Example:

test("symmetric vs asymmetric", () => {
  expect({ a: 1, x: () => {} }).toEqualWithoutMethods({ a: 1 });
  expect({ a: 1, x: () => {} }).toEqual(expect.methodlessly({ a: 1 }));
});

API

.toEqualWithoutMethods(object)

Asserts that two objects are deeply equal if all their methods were completely ignored

expect({ a: 1 }).toEqualWithoutMethods({ a: 1 }); // true
expect({ a: 1 }).toEqualWithoutMethods({ a: 1, x: () => {} }); // true
expect({ a: 1, x: () => {} }).toEqualWithoutMethods({ a: 1 }); // true
expect({ a: 1 }).toEqualWithoutMethods({ a: expect.any(Number) }); // true, allows use of other asymmetric within it
expect({ a: 1, x: () => {} }).toEqualWithoutMethods({ a: 1, x: () => {} }); // true
expect({ a: 1, x: () => {} }).toEqualWithoutMethods({ a: 1, y: () => {} }); // true

expect({ b: 1, x: () => {} }).not.toEqualWithoutMethods({ a: 1, x: () => {} }); // true

// It should be noted that by using expect.any(Function) or expect.anything() or similar
// you are explicitly opting out of methodlessly's function === undefined equality.
// Example:
expect({ a: 1, x: () => {} }).toEqualWithoutMethods({
  a: 1,
  x: () => {},
  y: expect.any(Function), // or expect.anything()
}); // false!
// But of course this will work as expected:
expect({ a: 1, x: () => {} }).toEqualWithoutMethods({
  a: 1,
  x: expect.any(Function),
}); // true

expect.methodlessly(object)

The asymmetric variant of .toEqualWithoutMethods.

expect({ a: 1 }).toEqual(expect.methodlessly({ a: 1 })); // true
expect({ a: 1 }).toEqual(expect.methodlessly({ a: 1, x: () => {} })); // true
expect({ a: 1, x: () => {} }).toEqual(expect.methodlessly({ a: 1 })); // true
expect({ a: 1 }).toEqual(expect.methodlessly({ a: expect.any(Number) })); // true, allows use of other asymmetric within it
expect({ a: 1, x: () => {} }).toEqual(
  expect.methodlessly({ a: 1, x: () => {} }),
); // true
expect({ a: 1, x: () => {} }).toEqual(
  expect.methodlessly({ a: 1, y: () => {} }),
); // true

expect({ b: 1, x: () => {} }).toEqual(
  expect.not.methodlessly({ a: 1, x: () => {} }),
); // true

// Same as .toEqualWithoutMethods() above
expect({ a: 1, x: () => {} }).toEqual(
  expect.methodlessly({ a: 1, x: () => {}, y: expect.any(Function) }),
); // false!
expect({ a: 1, x: () => {} }).toEqual(
  expect.methodlessly({ a: 1, x: expect.any(Function) }),
); // true

.toEqualTraitfully(object)

Asserts that two objects are deeply equal if all properties were identical but their methods were compared ONLY by name
Whatever the methods' implementations or their signatures doesn't matter to this matcher
If Traitful JavaScript was followed this should basically assert full equality including functionality

expect({a: 1}).toEqualTraitfully({a: 1}); // true
expect({a: 1, x: () => {}}).toEqualTraitfully({a: 1, x: () => {}}); // true
expect({a: 1, x: () => true}).toEqualTraitfully({a: 1, x: () => false); // true
expect({a: 1, x: () => {}}).toEqualTraitfully({a: expect.any(Number), x: () => {}}); // true, allows use of other asymmetric within it

expect({a: 1, x: () => {}}).not.toEqualTraitfully({a: 1}); // true
expect({a: 1, x: () => {}}).not.toEqualTraitfully({a: 1, y: () => {}}); // true
expect({b: 1, x: () => {}}).not.toEqualTraitfully({a: 1, x: () => {}}); // true

expect.traitfully(object)

The asymmetric variant of .toEqualTraitfully.

expect({a: 1}).toEqual(expect.traitfully({a: 1})); // true
expect({a: 1, x: () => {}}).toEqual(expect.traitfully({a: 1, x: () => {}})); // true
expect({a: 1, x: () => true}).toEqual(expect.traitfully({a: 1, x: () => false)); // true
expect({a: 1, x: () => {}}).toEqual(expect.traitfully({a: expect.any(Number), x: () => {}})); // true, allows use of other asymmetric within it

expect({a: 1, x: () => {}}).toEqual(expect.traitfully({a: 1})); // true
expect({a: 1, x: () => {}}).toEqual(expect.traitfully({a: 1, y: () => {}})); // true
expect({b: 1, x: () => {}}).toEqual(expect.traitfully({a: 1, x: () => {}})); // true

LICENSE

MIT