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

Address a number of issues with array-like "to satisfy". #550

Merged
merged 3 commits into from
Dec 31, 2018
Merged
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
17 changes: 11 additions & 6 deletions lib/assertions.js
Original file line number Diff line number Diff line change
Expand Up @@ -1487,7 +1487,8 @@ module.exports = expect => {
const valueKeyType = expect.findTypeOf(valueKey);

if (valueKeyType.is('expect.it')) {
return valueKey(subjectKey);
expect.context.thisObject = subject;
return valueKey(subjectKey, expect.context);
} else {
return expect(subjectKey, 'to [exhaustively] satisfy', valueKey);
}
Expand All @@ -1498,24 +1499,28 @@ module.exports = expect => {
expect.promise(() => {
// create subject key presence object
const remainingKeysInSubject = {};
subjectType.getKeys(subject).forEach(key => {
subjectKeys.forEach(key => {
remainingKeysInSubject[key] = 1; // present in subject
});
// discard or mark missing each previously seen value key
valueKeys.forEach(key => {
if (!remainingKeysInSubject[key]) {
if (
!remainingKeysInSubject[key] &&
(utils.numericalRegExp.test(key) || expect.flags.exhaustively)
) {
remainingKeysInSubject[key] = 2; // present in value
} else {
delete remainingKeysInSubject[key];
}
});
// filter outstanding keys which should not lead to an error
// check whether there are any outstanding keys we cannot account for
const outstandingKeys = Object.keys(remainingKeysInSubject).filter(
key =>
utils.numericalRegExp.test(key) ||
typeof key === 'symbol' ||
typeof subjectType.valueForKey(subject, key) !== 'undefined' ||
remainingKeysInSubject[key] === 2
(typeof subjectType.valueForKey(subject, key) !== 'undefined' &&
// key was only in the value
remainingKeysInSubject[key] === 2)
);
// key checking succeeds with no outstanding keys
expect(outstandingKeys.length === 0, 'to be truthy');
Expand Down
59 changes: 59 additions & 0 deletions test/assertions/to-satisfy.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1451,6 +1451,65 @@ describe('to satisfy assertion', () => {
')'
);
});

it('should support context correctly with expect.it (numerical)', () => {
function Greeter(folks) {
this.push(...(folks || []));

this.greet = function(prefix) {
return prefix + this.join(' & ');
};
}

Greeter.prototype = [];

const clonedExpect = expect.clone();
clonedExpect.addType({
name: 'Greeter',
base: 'array-like',
identify: obj => obj instanceof Greeter
});

const expected = ['Alice', 'Bob'];
expected.greet = expect.it(
'when called with',
['Hello, '],
'to equal',
'Hello, Alice & Bob'
);

clonedExpect(new Greeter(['Alice', 'Bob']), 'to satisfy', expected);
});

it('should support context correctly with expect.it (non-numerical)', () => {
function Greeter(folks) {
this.push(...(folks || []));

this.greet = function(prefix) {
return prefix + this.join(' & ');
};
}

Greeter.prototype = [];

const clonedExpect = expect.clone();
clonedExpect.addType({
name: 'Greeter',
base: 'array-like',
identify: obj => obj instanceof Greeter,
numericalPropertiesOnly: false
});

const expected = ['Alice', 'Bob'];
expected.greet = expect.it(
'when called with',
['Hello, '],
'to equal',
'Hello, Alice & Bob'
);

clonedExpect(new Greeter(['Alice', 'Bob']), 'to satisfy', expected);
});
});

describe('on arrays', () => {
Expand Down