Skip to content

Commit

Permalink
Implement exhaustively flag for to contain
Browse files Browse the repository at this point in the history
  • Loading branch information
gustavnikolaj committed Sep 8, 2020
1 parent 3e56f88 commit dfd6a7f
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 34 deletions.
86 changes: 54 additions & 32 deletions lib/assertions.js
Expand Up @@ -766,39 +766,61 @@ module.exports = (expect) => {
);
});

expect.addAssertion('<array-like> [not] to contain <any+>', function (
expect,
subject
) {
const args = Array.prototype.slice.call(arguments, 2);
expect.withError(
() => {
args.forEach((arg) => {
expect(
subject &&
Array.prototype.some.call(subject, (item) =>
expect.equal(item, arg)
),
'[not] to be truthy'
);
});
},
(e) => {
expect.fail({
diff:
expect.flags.not &&
((output, diff, inspect, equal) =>
diff(
subject,
Array.prototype.filter.call(
subject,
(item) => !args.some((arg) => equal(item, arg))
)
)),
});
expect.addAssertion(
'<array-like> [not] to [exhaustively] contain <any+>',
function (expect, subject) {
const args = Array.prototype.slice.call(arguments, 2);

if (expect.flags.exhaustively && expect.flags.not) {
expect.errorMode = 'bubble';
expect.fail(
'The "not" flag cannot be used together with "to exhaustively contain".'
);
}
);
});

expect.withError(
() => {
args.forEach((arg) => {
expect(
subject &&
Array.prototype.some.call(subject, (item) =>
expect.equal(item, arg)
),
'[not] to be truthy'
);
});
if (expect.flags.exhaustively) {
expect(subject.length, 'to be', args.length);
}
},
(e) => {
expect.fail({
diff(output, diff, inspect, equal) {
if (expect.flags.not) {
return diff(
subject,
Array.prototype.filter.call(
subject,
(item) => !args.some((arg) => equal(item, arg))
)
);
} else if (expect.flags.exhaustively) {
var excessItems = Array.prototype.filter.call(subject, (item) =>
args.some((arg) => equal(item, arg))
);
var missingItems = Array.prototype.filter.call(
args,
(arg) => !subject.some((item) => equal(arg, item))
);

return diff(subject, excessItems.concat(missingItems));
}
},
});
}
);
}
);

expect.addAssertion(
[
Expand Down
69 changes: 67 additions & 2 deletions test/assertions/to-contain.spec.js
Expand Up @@ -32,7 +32,7 @@ describe('to contain assertion', () => {
' The assertion does not have a matching signature for:\n' +
' <null> not to contain <string>\n' +
' did you mean:\n' +
' <array-like> [not] to contain <any+>\n' +
' <array-like> [not] to [exhaustively] contain <any+>\n' +
' <string> [not] to contain <string+>'
);

Expand Down Expand Up @@ -80,7 +80,7 @@ describe('to contain assertion', () => {
' The assertion does not have a matching signature for:\n' +
' <number> to contain <number>\n' +
' did you mean:\n' +
' <array-like> [not] to contain <any+>\n' +
' <array-like> [not] to [exhaustively] contain <any+>\n' +
' <string> [not] to contain <string+>'
);
});
Expand Down Expand Up @@ -166,6 +166,71 @@ describe('to contain assertion', () => {
});
});

describe('with the exhaustively flag', () => {
it('should not throw when all items are included in the subject', () => {
expect(function () {
expect(
[{ bar: 456 }, { foo: 123 }],
'to exhaustively contain',
{ foo: 123 },
{ bar: 456 }
);
}, 'not to throw');
});

it('should throw when all items are not included in the subject', () => {
expect(
function () {
expect(
[{ bar: 456 }],
'to exhaustively contain',
{ foo: 123 },
{ bar: 456 }
);
},
'to throw exception',
'expected [ { bar: 456 } ] to exhaustively contain { foo: 123 }, { bar: 456 }\n' +
'\n' +
'[\n' +
' { bar: 456 }\n' +
' // missing { foo: 123 }\n' +
']'
);
});

it('should throw when all items are included in the subject but subject has other items as well', () => {
expect(
function () {
expect(
[{ bar: 456 }, { foo: 123 }, { baz: 789 }],
'to exhaustively contain',
{ foo: 123 },
{ bar: 456 }
);
},
'to throw exception',
'expected [ { bar: 456 }, { foo: 123 }, { baz: 789 } ]\n' +
'to exhaustively contain { foo: 123 }, { bar: 456 }\n' +
'\n' +
'[\n' +
' { bar: 456 },\n' +
' { foo: 123 },\n' +
' { baz: 789 } // should be removed\n' +
']'
);
});

it('should throw when combining the not and exhaustively flags', () => {
expect(
function () {
expect([{ foo: 123 }], 'not to exhaustively contain', { foo: 123 });
},
'to throw exception',
'The "not" flag cannot be used together with "to exhaustively contain".'
);
});
});

it('should not highlight overlapping partial matches', () => {
expect(
function () {
Expand Down

0 comments on commit dfd6a7f

Please sign in to comment.