Skip to content

Commit

Permalink
Merge e07d730 into e614375
Browse files Browse the repository at this point in the history
  • Loading branch information
novemberborn committed Apr 21, 2017
2 parents e614375 + e07d730 commit bbba2b6
Show file tree
Hide file tree
Showing 29 changed files with 1,403 additions and 694 deletions.
122 changes: 70 additions & 52 deletions lib/assert.js
@@ -1,12 +1,29 @@
'use strict';
const coreAssert = require('core-assert');
const deepEqual = require('lodash.isequal');
const kathryn = require('kathryn');
const observableToPromise = require('observable-to-promise');
const isObservable = require('is-observable');
const isPromise = require('is-promise');
const jestDiff = require('jest-diff');
const enhanceAssert = require('./enhance-assert');
const formatAssertError = require('./format-assert-error');
const kathrynOptions = require('./kathryn-options').recommended;

function formatDescriptorDiff(actualDescriptor, expectedDescriptor) {
return {
label: 'Difference:',
formatted: kathryn.diffDescriptors(actualDescriptor, expectedDescriptor, kathrynOptions)
};
}

function formatDescriptorWithLabel(label, descriptor) {
return {
label,
formatted: kathryn.formatDescriptor(descriptor, kathrynOptions)
};
}

function formatWithLabel(label, value) {
return formatDescriptorWithLabel(label, kathryn.describe(value));
}

class AssertionError extends Error {
constructor(opts) {
Expand Down Expand Up @@ -62,16 +79,12 @@ function wrapAssertions(callbacks) {
if (Object.is(actual, expected)) {
pass(this);
} else {
const diff = formatAssertError.formatDiff(actual, expected);
const values = diff ? [diff] : [
formatAssertError.formatWithLabel('Actual:', actual),
formatAssertError.formatWithLabel('Must be the same as:', expected)
];

const actualDescriptor = kathryn.describe(actual);
const expectedDescriptor = kathryn.describe(expected);
fail(this, new AssertionError({
assertion: 'is',
message,
values
values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)]
}));
}
},
Expand All @@ -81,37 +94,36 @@ function wrapAssertions(callbacks) {
fail(this, new AssertionError({
assertion: 'not',
message,
values: [formatAssertError.formatWithLabel('Value is the same as:', actual)]
values: [formatWithLabel('Value is the same as:', actual)]
}));
} else {
pass(this);
}
},

deepEqual(actual, expected, message) {
if (deepEqual(actual, expected)) {
const result = kathryn.compare(actual, expected);
if (result.pass) {
pass(this);
} else {
const diff = formatAssertError.formatDiff(actual, expected);
const values = diff ? [diff] : [
formatAssertError.formatWithLabel('Actual:', actual),
formatAssertError.formatWithLabel('Must be deeply equal to:', expected)
];

const actualDescriptor = result.actual || kathryn.describe(actual);
const expectedDescriptor = result.expected || kathryn.describe(expected);
fail(this, new AssertionError({
assertion: 'deepEqual',
message,
values
values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)]
}));
}
},

notDeepEqual(actual, expected, message) {
if (deepEqual(actual, expected)) {
const result = kathryn.compare(actual, expected);
if (result.pass) {
const actualDescriptor = result.actual || kathryn.describe(actual);
fail(this, new AssertionError({
assertion: 'notDeepEqual',
message,
values: [formatAssertError.formatWithLabel('Value is deeply equal:', actual)]
values: [formatDescriptorWithLabel('Value is deeply equal:', actualDescriptor)]
}));
} else {
pass(this);
Expand All @@ -129,7 +141,7 @@ function wrapAssertions(callbacks) {
assertion: 'throws',
improperUsage: true,
message: '`t.throws()` must be called with a function, Promise, or Observable',
values: [formatAssertError.formatWithLabel('Called with:', fn)]
values: [formatWithLabel('Called with:', fn)]
}));
return;
}
Expand Down Expand Up @@ -158,15 +170,13 @@ function wrapAssertions(callbacks) {
}, coreAssertThrowsErrorArg);
return actual;
} catch (err) {
const values = threw ?
[formatAssertError.formatWithLabel('Threw unexpected exception:', actual)] :
null;

throw new AssertionError({
assertion: 'throws',
message,
stack,
values
values: threw ?
[formatWithLabel('Threw unexpected exception:', actual)] :
null
});
}
};
Expand Down Expand Up @@ -200,7 +210,7 @@ function wrapAssertions(callbacks) {
assertion: 'notThrows',
improperUsage: true,
message: '`t.notThrows()` must be called with a function, Promise, or Observable',
values: [formatAssertError.formatWithLabel('Called with:', fn)]
values: [formatWithLabel('Called with:', fn)]
}));
return;
}
Expand All @@ -213,7 +223,7 @@ function wrapAssertions(callbacks) {
assertion: 'notThrows',
message,
stack,
values: [formatAssertError.formatWithLabel('Threw:', err.actual)]
values: [formatWithLabel('Threw:', err.actual)]
});
}
};
Expand All @@ -240,28 +250,36 @@ function wrapAssertions(callbacks) {
fail(this, new AssertionError({
assertion: 'ifError',
message,
values: [formatAssertError.formatWithLabel('Error:', actual)]
values: [formatWithLabel('Error:', actual)]
}));
} else {
pass(this);
}
},

snapshot(actual, message) {
const state = this._test.getSnapshotState();
const result = state.match(this.title, actual);
snapshot(expected, optionsOrMessage, message) {
const options = {};
if (typeof optionsOrMessage === 'string') {
message = optionsOrMessage;
} else if (optionsOrMessage) {
options.id = optionsOrMessage.id;
}
options.expected = expected;
options.message = message;

const result = this._test.compareWithSnapshot(options);
if (result.pass) {
pass(this);
} else {
const diff = jestDiff(result.expected.trim(), result.actual.trim(), {expand: true})
// Remove annotation
.split('\n')
.slice(3)
.join('\n');
} else if (result.actual) {
fail(this, new AssertionError({
assertion: 'snapshot',
message: message || 'Did not match snapshot',
values: [{label: 'Difference:', formatted: diff}]
values: [formatDescriptorDiff(result.actual, result.expected)]
}));
} else {
fail(this, new AssertionError({
assertion: 'snapshot',
message: message || 'No snapshot available, run with --update-snapshots'
}));
}
}
Expand All @@ -274,7 +292,7 @@ function wrapAssertions(callbacks) {
assertion: 'truthy',
message,
operator: '!!',
values: [formatAssertError.formatWithLabel('Value is not truthy:', actual)]
values: [formatWithLabel('Value is not truthy:', actual)]
});
}
},
Expand All @@ -285,7 +303,7 @@ function wrapAssertions(callbacks) {
assertion: 'falsy',
message,
operator: '!',
values: [formatAssertError.formatWithLabel('Value is not falsy:', actual)]
values: [formatWithLabel('Value is not falsy:', actual)]
});
}
},
Expand All @@ -295,7 +313,7 @@ function wrapAssertions(callbacks) {
throw new AssertionError({
assertion: 'true',
message,
values: [formatAssertError.formatWithLabel('Value is not `true`:', actual)]
values: [formatWithLabel('Value is not `true`:', actual)]
});
}
},
Expand All @@ -305,7 +323,7 @@ function wrapAssertions(callbacks) {
throw new AssertionError({
assertion: 'false',
message,
values: [formatAssertError.formatWithLabel('Value is not `false`:', actual)]
values: [formatWithLabel('Value is not `false`:', actual)]
});
}
},
Expand All @@ -316,15 +334,15 @@ function wrapAssertions(callbacks) {
assertion: 'regex',
improperUsage: true,
message: '`t.regex()` must be called with a string',
values: [formatAssertError.formatWithLabel('Called with:', string)]
values: [formatWithLabel('Called with:', string)]
});
}
if (!(regex instanceof RegExp)) {
throw new AssertionError({
assertion: 'regex',
improperUsage: true,
message: '`t.regex()` must be called with a regular expression',
values: [formatAssertError.formatWithLabel('Called with:', regex)]
values: [formatWithLabel('Called with:', regex)]
});
}

Expand All @@ -333,8 +351,8 @@ function wrapAssertions(callbacks) {
assertion: 'regex',
message,
values: [
formatAssertError.formatWithLabel('Value must match expression:', string),
formatAssertError.formatWithLabel('Regular expression:', regex)
formatWithLabel('Value must match expression:', string),
formatWithLabel('Regular expression:', regex)
]
});
}
Expand All @@ -346,15 +364,15 @@ function wrapAssertions(callbacks) {
assertion: 'notRegex',
improperUsage: true,
message: '`t.notRegex()` must be called with a string',
values: [formatAssertError.formatWithLabel('Called with:', string)]
values: [formatWithLabel('Called with:', string)]
});
}
if (!(regex instanceof RegExp)) {
throw new AssertionError({
assertion: 'notRegex',
improperUsage: true,
message: '`t.notRegex()` must be called with a regular expression',
values: [formatAssertError.formatWithLabel('Called with:', regex)]
values: [formatWithLabel('Called with:', regex)]
});
}

Expand All @@ -363,8 +381,8 @@ function wrapAssertions(callbacks) {
assertion: 'notRegex',
message,
values: [
formatAssertError.formatWithLabel('Value must not match expression:', string),
formatAssertError.formatWithLabel('Regular expression:', regex)
formatWithLabel('Value must not match expression:', string),
formatWithLabel('Regular expression:', regex)
]
});
}
Expand Down
8 changes: 6 additions & 2 deletions lib/enhance-assert.js
@@ -1,6 +1,7 @@
'use strict';
const dotProp = require('dot-prop');
const formatValue = require('./format-assert-error').formatValue;
const kathryn = require('kathryn');
const kathrynOptions = require('./kathryn-options').recommended;

// When adding patterns, don't forget to add to
// https://github.com/avajs/babel-preset-transform-test-files/blob/master/espower-patterns.json
Expand Down Expand Up @@ -37,7 +38,10 @@ const formatter = context => {
return args
.map(arg => {
const range = getNode(ast, arg.espath).range;
return [computeStatement(tokens, range), formatValue(arg.value, {maxDepth: 1})];
const statement = computeStatement(tokens, range);

const formatted = kathryn.format(arg.value, kathrynOptions);
return [statement, formatted];
})
.reverse();
};
Expand Down

0 comments on commit bbba2b6

Please sign in to comment.