Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/matchers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export { toHaveBeenCalledOnce } from './toHaveBeenCalledOnce';
export { toHaveBeenCalledOnceWith } from './toHaveBeenCalledOnceWith';
export { toInclude } from './toInclude';
export { toIncludeAllMembers } from './toIncludeAllMembers';
export { toIncludeAllMembersInOrder } from './toIncludeAllMembersInOrder';
export { toIncludeAllPartialMembers } from './toIncludeAllPartialMembers';
export { toIncludeAnyMembers } from './toIncludeAnyMembers';
export { toIncludeMultiple } from './toIncludeMultiple';
Expand Down
64 changes: 64 additions & 0 deletions src/matchers/toIncludeAllMembersInOrder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { contains } from '../utils';

export function toIncludeAllMembersInOrder(actual, expected) {
const { printReceived, printExpected, matcherHint } = this.utils;
const options = {
isNot: this.isNot,
promise: this.promise,
};

// First, check contents.
const passMessage =
matcherHint('.not.toIncludeAllMembers') +
'\n\n' +
'Expected list to not have all of the following members:\n' +
` ${printExpected(expected)}\n` +
'Received:\n' +
` ${printReceived(actual)}`;

const failMessage =
matcherHint('.toIncludeAllMembers') +
'\n\n' +
'Expected list to have all of the following members:\n' +
` ${printExpected(expected)}\n` +
'Received:\n' +
` ${printReceived(actual)}`;

let pass =
Array.isArray(actual) && Array.isArray(expected) && expected.every(val => contains(this.equals, actual, val));

if (!pass) return { pass, message: () => (pass ? passMessage : failMessage) };

let differingElementIdxs = [];
// Check if actual has additional items beyond expected.
if (actual.length > expected.length) {
differingElementIdxs = [expected.length];
} else {
// If not, check order. At this point, they must have the same length, so we
// can go element by element and fail at the first elements that don't
// match.

differingElementIdxs = expected
.map((element, idx) => {
return this.equals(element, actual[idx]) ? false : idx;
})
.filter(idx => idx !== false);
}

pass = differingElementIdxs.length === 0;

const message = () => {
return pass
? this.utils.matcherHint('toIncludeAllMembersInOrder', undefined, undefined, options) +
'\n\n' +
`Expected: not ${this.utils.printExpected(expected)}\n` +
`Received: ${this.utils.printReceived(actual)}`
: this.utils.matcherHint('toIncludeAllMembersInOrder', undefined, undefined, options) +
'\n\n' +
`First differing element (index ${differingElementIdxs[0]}):\n\n` +
`Expected: ${this.utils.printExpected(expected[differingElementIdxs[0]])}\n` +
`Received: ${this.utils.printReceived(actual[differingElementIdxs[0]])}`;
};

return { actual, message, pass };
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`.toIncludeAllMembersInOrder fails when array values do not contain all the members of the set 1`] = `
"<dim>expect(</intensity><red>received</color><dim>).</intensity>toIncludeAllMembersInOrder<dim>(</intensity><green>expected</color><dim>)</intensity>

First differing element (index 2):

Expected: <green>undefined</color>
Received: <red>3</color>"
`;

exports[`.toIncludeAllMembersInOrder fails when array values do not have the same order as the expected array 1`] = `
"<dim>expect(</intensity><red>received</color><dim>).</intensity>toIncludeAllMembersInOrder<dim>(</intensity><green>expected</color><dim>)</intensity>

First differing element (index 0):

Expected: <green>2</color>
Received: <red>1</color>"
`;

exports[`.toIncludeAllMembersInOrder fails when array values do not have the same order as the expected array 2`] = `
"<dim>expect(</intensity><red>received</color><dim>).</intensity>toIncludeAllMembersInOrder<dim>(</intensity><green>expected</color><dim>)</intensity>

First differing element (index 2):

Expected: <green>undefined</color>
Received: <red>2</color>"
`;

exports[`.toIncludeAllMembersInOrder fails when array values do not have the same order as the expected array 3`] = `
"<dim>expect(</intensity><red>received</color><dim>).</intensity>toIncludeAllMembersInOrder<dim>(</intensity><green>expected</color><dim>)</intensity>

First differing element (index 0):

Expected: <green>{"baz": "qux"}</color>
Received: <red>{"foo": "bar"}</color>"
`;

exports[`.toIncludeAllMembersInOrder fails when expected object is not an array 1`] = `
"<dim>expect(</intensity><red>received</color><dim>).toIncludeAllMembers(</intensity><green>expected</color><dim>)</intensity>

Expected list to have all of the following members:
<green>2</color>
Received:
<red>[1, 2, 3]</color>"
`;

exports[`.toIncludeAllMembersInOrder fails when given object is not an array 1`] = `
"<dim>expect(</intensity><red>received</color><dim>).toIncludeAllMembers(</intensity><green>expected</color><dim>)</intensity>

Expected list to have all of the following members:
<green>[1, 2, 3]</color>
Received:
<red>2</color>"
`;
50 changes: 50 additions & 0 deletions test/matchers/toIncludeAllMembersInOrder.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import * as matcher from 'src/matchers/toIncludeAllMembersInOrder';

expect.extend(matcher);

describe('.toIncludeAllMembersInOrder', () => {
const array1 = [1, 2, 3];
const array2 = [1, 2, 2];

test('passes when array values match in order the expected array', () => {
expect(array1).toIncludeAllMembersInOrder([1, 2, 3]);
expect([{ foo: 'bar' }, { baz: 'qux' }]).toIncludeAllMembersInOrder([{ foo: 'bar' }, { baz: 'qux' }]);
});

test('fails when array values do not have the same order as the expected array', () => {
expect(() => expect(array1).toIncludeAllMembersInOrder([2, 1, 3])).toThrowErrorMatchingSnapshot();
expect(() => expect(array2).toIncludeAllMembersInOrder([2, 1])).toThrowErrorMatchingSnapshot();
expect(() =>
expect([{ foo: 'bar' }, { baz: 'qux' }]).toIncludeAllMembersInOrder([{ baz: 'qux' }, { foo: 'bar' }]),
).toThrowErrorMatchingSnapshot();
});

test('fails when array values do not contain all the members of the set', () => {
expect(() => expect([1, 2, 3]).toIncludeAllMembersInOrder([1, 2])).toThrowErrorMatchingSnapshot();
});

test('fails when given object is not an array', () => {
expect(() => expect(2).toIncludeAllMembersInOrder([1, 2, 3])).toThrowErrorMatchingSnapshot();
});

test('fails when expected object is not an array', () => {
expect(() => expect(array1).toIncludeAllMembersInOrder(2)).toThrowErrorMatchingSnapshot();
});
});

describe('.not.toIncludeAllMembersInOrder', () => {
const array1 = [1, 2, 3];

test('passes when array values does not contain any members of the set', () => {
expect(array1).not.toIncludeAllMembersInOrder([4, 5, 6]);
expect([{ foo: 'bar' }, { baz: 'qux' }]).not.toIncludeAllMembersInOrder([{ hello: 'world' }]);
});

test('passes when given object is not an array', () => {
expect(4).not.toIncludeAllMembersInOrder([4, 5, 6]);
});

test('passes when array values matches the members of the set', () => {
expect(array1).not.toIncludeAllMembersInOrder([2, 1, 3]);
});
});
18 changes: 18 additions & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ interface CustomMatchers<R> {
*/
toIncludeAllMembers<E = unknown>(members: readonly E[]): R;

/**
* Use `.toIncludeAllMembersInOrder` when checking if an `Array` contains all of the same members of a given array in the same order.
* @param {Array.<*>} members
*/
toIncludeAllMembersInOrder<E = unknown>(members: readonly E[]): R;

/**
* Use `.toIncludeAllPartialMembers` when checking if an `Array` contains all of the same partial members of a given set.
* @param {Array.<*>} members
*/
toIncludeAllPartialMembers<E = unknown>(members: readonly E[]): R;

/**
* Use `.toIncludeAnyMembers` when checking if an `Array` contains any of the members of a given set.
* @param {Array.<*>} members
Expand Down Expand Up @@ -496,6 +508,12 @@ declare namespace jest {
*/
toIncludeAllMembers<E = unknown>(members: readonly E[]): R;

/**
* Use `.toIncludeAllMembersInOrder` when checking if an `Array` contains all of the same members of a given array in the same order.
* @param {Array.<*>} members
*/
toIncludeAllMembersInOrder<E = unknown>(members: readonly E[]): R;

/**
* Use `.toIncludeAllPartialMembers` when checking if an `Array` contains all of the same partial members of a given set.
* @param {Array.<*>} members
Expand Down
7 changes: 3 additions & 4 deletions website/docs/getting-started/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ sidebar_position: 2
Create a setup script with the following:

```javascript title="testSetup.js"

// add all jest-extended matchers
import * as matchers from 'jest-extended';
expect.extend(matchers);
Expand Down Expand Up @@ -42,8 +41,8 @@ To automatically extend `expect` with all matchers, you can use
`jest-extended` works with `vitest` because their `expect.extend` API is compatible. In your setup script:

```javascript title="testSetup.js"
import {expect} from "vitest";
import * as matchers from "jest-extended";
import { expect } from 'vitest';
import * as matchers from 'jest-extended';
expect.extend(matchers);
```

Expand All @@ -52,7 +51,7 @@ Add this setup script to your `vitest.config.js`:
```javascript title="vitest.config.js"
export default defineConfig({
test: {
setupFiles: ["./testSetup.js"],
setupFiles: ['./testSetup.js'],
},
});
```
11 changes: 11 additions & 0 deletions website/docs/matchers/Array.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ Use `.toIncludeAllMembers` when checking if an `Array` contains all of the same
});`}
</TestFile>

### .toIncludeAllMembersInOrder([members])

Use `.toIncludeAllMembersInOrder` when checking if an `Array` contains all of the same members of a given array in the same order.

<TestFile name="toIncludeAllMembersInOrder">
{`test('passes when given array values match the members and order of array', () => {
expect([1, 2, 3]).toIncludeAllMembersInOrder([1, 2, 3]);
expect([{ foo: 'bar', }, { baz: 'qux' }]).toIncludeAllMembersInOrder([{ foo: 'bar' }, { baz: 'qux' }]);
});`}
</TestFile>

### .toIncludeAllPartialMembers([members])

Use `.toIncludeAllPartialMembers` when checking if an `Array` contains all of the same partial members of a given set.
Expand Down
1 change: 1 addition & 0 deletions website/docs/matchers/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ sidebar_position: 1
- [.toBeArray()](/docs/matchers/array/#tobearray)
- [.toBeArrayOfSize()](/docs/matchers/array/#tobearrayofsize)
- [.toIncludeAllMembers([members])](/docs/matchers/array/#toincludeallmembersmembers)
- [.toIncludeAllMembersInOrder([members])](/docs/matchers/array/#toincludeallmembersmembersinorder)
- [.toIncludeAllPartialMembers([members])](/docs/matchers/array/#toincludeallpartialmembersmembers)
- [.toIncludeAnyMembers([members])](/docs/matchers/array/#toincludeanymembersmembers)
- [.toIncludeSameMembers([members])](/docs/matchers/array/#toincludesamemembersmembers)
Expand Down