Skip to content

Commit

Permalink
✨ Allow returning booleans and matchers from anonymous assertions
Browse files Browse the repository at this point in the history
  • Loading branch information
wwilsman committed Jul 7, 2023
1 parent c7a51c3 commit b9cf306
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 8 deletions.
17 changes: 12 additions & 5 deletions lib/assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ export function assertion(get, matcher = get) {
args = [value].concat(args);
}

let { message, result } = matcher.apply(this, args);

let { message, result } =
matcher.apply(this, args);
if (result !== expected)
throw error(message);
};
Expand Down Expand Up @@ -158,16 +158,23 @@ export default function InteractorAssert(i, expected = true) {

// assertions are called with an assert context and can be negated on error
return passert.call(i, defineProperties(function() {
let message;

try {
f.apply(context(this, expected), arguments);
if (expected) return;
let res = f.apply(context(this, expected), arguments);
if (typeof res === 'object' && 'message' in res) message = res.message;
if (typeof res === 'object' && 'result' in res) res = !!res.result;
if (expected === !!(res ?? true)) return;
} catch (err) {
if (err.name === 'InteractorError') err.bind(this, expected);
if (expected) throw err;
return;
}

throw error('expected assertion to fail but it passed');
throw error(message ?? [
'expected assertion to', expected ? 'pass' : 'fail',
'but it', expected ? 'failed' : 'passed'
].join(' '));
}, {
name: { value: f.name },
// used to determine invoking the interactor element
Expand Down
56 changes: 53 additions & 3 deletions tests/assert.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,33 @@ describe('InteractorAssert', () => {
assert.notEqual(I().assert, I().assert);
});

it('handles boolean return values', async () => {
await assert.doesNotReject(
Test().assert(() => true)
);

await assert.rejects(
Test().assert(() => false),
e('InteractorError', 'expected assertion to pass but it failed')
);
});

it('handles matcher return values', async () => {
await assert.doesNotReject(
Test().assert(() => ({ result: true }))
);

await assert.rejects(
Test().assert(() => ({ result: false })),
e('InteractorError', 'expected assertion to pass but it failed')
);

await assert.rejects(
Test().assert(() => ({ result: false, message: 'epic fail' })),
e('InteractorError', 'epic fail')
);
});

it('can be negated with .not', async () => {
let T = Test.extend({
assert: {
Expand All @@ -33,6 +60,29 @@ describe('InteractorAssert', () => {
e('InteractorError', 'expected assertion to fail but it passed')
);

await assert.doesNotReject(
T().assert.not(() => false)
);

await assert.rejects(
T().assert.not(() => true),
e('InteractorError', 'expected assertion to fail but it passed')
);

await assert.doesNotReject(
Test().assert.not(() => ({ result: false }))
);

await assert.rejects(
Test().assert.not(() => ({ result: true })),
e('InteractorError', 'expected assertion to fail but it passed')
);

await assert.rejects(
Test().assert.not(() => ({ result: true, message: 'nega fail' })),
e('InteractorError', 'nega fail')
);

await assert.doesNotReject(
T().assert.not(() => {
throw Error('failed successfully');
Expand All @@ -46,9 +96,9 @@ describe('InteractorAssert', () => {

await assert.doesNotReject(
Test()
.assert(() => (delta == null && (delta = 10)))
.assert(() => (delta += Date.now() - time))
.assert(() => (time = Date.now()))
.assert(() => void (delta == null && (delta = 10)))
.assert(() => void (delta += Date.now() - time))
.assert(() => void (time = Date.now()))
.assert.remains()
);

Expand Down

0 comments on commit b9cf306

Please sign in to comment.