Skip to content

Commit

Permalink
FEAT: use Jest assertion return api (#349)
Browse files Browse the repository at this point in the history
  • Loading branch information
vligas committed Sep 2, 2020
1 parent 1985f28 commit b633f09
Show file tree
Hide file tree
Showing 11 changed files with 245 additions and 8 deletions.
1 change: 0 additions & 1 deletion packages/n4s/dist/ensure.js

This file was deleted.

1 change: 0 additions & 1 deletion packages/n4s/dist/extended/enforce.js

This file was deleted.

1 change: 0 additions & 1 deletion packages/n4s/dist/extended/ensure.js

This file was deleted.

1 change: 0 additions & 1 deletion packages/n4s/dist/n4s.js

This file was deleted.

8 changes: 6 additions & 2 deletions packages/n4s/src/enforce/runner/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { transformResult } from '../../lib/transformResult';

/**
* Run a single rule against enforced value (e.g. `isNumber()`)
*
Expand All @@ -11,8 +13,10 @@ function runner(rule, value, ...args) {
return;
}

if (rule(value, ...args) !== true) {
throw new Error(`[Enforce]: invalid ${typeof value} value`);
const ruleResult = rule(value, ...args);
const result = transformResult(ruleResult, { rule, value });
if (!result.pass) {
throw new Error(result.message);
}
}

Expand Down
12 changes: 12 additions & 0 deletions packages/n4s/src/enforce/runner/spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,23 @@ describe('Test rule runner', () => {
it('Should throw', () => {
expect(() => rule(n => n === 2, 1)).toThrow(Error);
});

it('Should throw with verbose', () => {
expect(() =>
rule(() => ({ pass: false, message: 'Custom message' }))
).toThrow(Error);
});
});

describe('When passing output', () => {
it('Should return silently', () => {
expect(rule(n => n === 1, 1)).toBeUndefined();
});

it('Should return silently', () => {
expect(
rule(() => ({ pass: true, message: 'Custom message' }))
).toBeUndefined();
});
});
});
11 changes: 10 additions & 1 deletion packages/n4s/src/enforce/spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,13 @@ const suite = ({ withProxy, requirePath }) =>
let extended;
beforeEach(() => {
extended = enforce.extend({
isImpossible: v => !!v.match(/impossible/i),
endsWith: (v, arg) => v.endsWith(arg),
isImpossible: v => !!v.match(/impossible/i),
passVerbose: () => ({
pass: true,
message: "It shouldn't throw an error",
}),
throwVerbose: () => ({ pass: false, message: 'Custom error' }),
});
});

Expand All @@ -69,6 +74,10 @@ const suite = ({ withProxy, requirePath }) =>
.endsWith('Snowball')
.isImpossible();
});

it('Should return silently for custom verbose rule in regular test', () => {
enforce().passVerbose();
});
});

it('Should throw errors on failing enforces', () => {
Expand Down
5 changes: 4 additions & 1 deletion packages/n4s/src/ensure/runner/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { transformResult } from '../../lib/transformResult';

/**
* Run a single rule against ensured value (e.g. `isNumber()`)
* @param {Function} rule - rule to run
Expand All @@ -7,7 +9,8 @@
*/
function runner(rule, value, ...args) {
try {
return rule(value, ...args) === true;
const result = rule(value, ...args);
return transformResult(result, { rule, value }).pass;
} catch (err) {
return false;
}
Expand Down
54 changes: 54 additions & 0 deletions packages/n4s/src/lib/transformResult/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import throwError from '../throwError';

export function validateResult(result, rule) {
if (
typeof result !== 'boolean' &&
(!result || typeof result.pass !== 'boolean')
) {
throwError(
`/${rule.name} wrong return value for the rule please check that the return is valid`
);
}
}

// for easier testing and mocking
export function getDefaultResult(value, rule) {
return {
message: formatResultMessage(rule, `invalid ${typeof value} value`),
};
}

export function formatResultMessage(rule, msg) {
return `[${LIBRARY_NAME}]/${rule.name} ${msg}`;
}

/**
* Transform the result of a rule into a standard format
* @param {string} interfaceName to be used in the messages
* @param {*} result of the rule
* @param {Object} options
* @param {function} options.rule
* @param {*} options.value
* @returns {Object} result
* @returns {string} result.message
* @returns {boolean} result.pass indicates if the test passes or not
*/
export function transformResult(result, { rule, value }) {
const defaultResult = getDefaultResult(value, rule);
validateResult(result, rule);

if (typeof result === 'boolean') {
return { ...defaultResult, pass: result };
} else {
const formattedResult = {
pass: result.pass,
};
if (result.message) {
formattedResult.message = formatResultMessage(
rule,
typeof result.message === 'function' ? result.message() : result.message
);
}
return { ...defaultResult, ...formattedResult };
}
}
128 changes: 128 additions & 0 deletions packages/n4s/src/lib/transformResult/spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import {
goodBooleanRule,
goodObjectRule,
goodObjectMessageRule,
badObjectRule,
nullRule,
goodObjectMessageFunctionRule,
} from '../../testUtils/rules';
import {
transformResult,
getDefaultResult,
formatResultMessage,
validateResult,
} from '.';

describe('Tests `validateResult` helper', () => {
it('Should pass with boolean return values', () => {
const testRule = () => true;
validateResult(testRule());
});

it('Should pass with a verbose return value', () => {
const testRule = () => ({ pass: false, message: 'pass' });
validateResult(testRule());
});

it('Should throw error when reciving null', () => {
const testRule = () => null;
expect(() => validateResult(testRule())).toThrow(Error);
});

it("Should return false if it is a verbose result and doesn't have pass property", () => {
const missingPass = () => ({ message: 'missing pass' });
expect(() => validateResult(missingPass())).toThrow(Error);
});
});

describe.each([true, false])('Test transform result', bool => {
// to make sure we don't end up leaving some hardcoded value behind
it(`Should transform a boolean`, () => {
const { message: expectedMessage } = getDefaultResult(
bool,
goodBooleanRule
);
const result = goodBooleanRule(bool);
expect(
transformResult(result, { rule: goodBooleanRule, value: bool })
).toEqual({ pass: bool, message: expectedMessage });
});

it('Should transform a complete object', () => {
const result = goodObjectRule(bool);
expect(
transformResult(result, { rule: goodObjectRule, value: bool })
).toEqual({
pass: bool,
message: formatResultMessage(goodObjectRule, result.message),
});
});

it('Should add default message', () => {
const result = goodObjectMessageRule(bool);
const { message: expectedMessage } = getDefaultResult(
bool,
goodObjectMessageRule
);

expect(
transformResult(result, {
rule: goodObjectMessageRule,
value: bool,
})
).toEqual({
pass: bool,
message: expectedMessage,
});
});

it('Should get the message from the function', () => {
const result = goodObjectMessageFunctionRule(bool);
expect(
transformResult(result, {
rule: goodObjectMessageFunctionRule,
value: bool,
})
).toEqual({
pass: bool,
message: formatResultMessage(
goodObjectMessageFunctionRule,
result.message()
),
});
});

it('Should throw with malformed result', () => {
const result = badObjectRule(bool);
expect(() =>
transformResult(result, { rule: badObjectRule, value: bool })
).toThrow(Error);
});

it('Should throw with null result', () => {
const result = nullRule(bool);
expect(() =>
transformResult(result, { rule: nullRule, value: bool })
).toThrow(Error);
});
});

describe("Test transform result's message", () => {
[goodObjectMessageRule, goodObjectMessageRule, goodObjectRule].forEach(
rule => {
it('Should contain the library name', () => {
const result = rule(true);
expect(transformResult(result, { rule, value: true }).message).toMatch(
LIBRARY_NAME
);
});

it('Should contain the name of the rule', () => {
const result = rule(true);
expect(transformResult(result, { rule, value: true }).message).toMatch(
rule.name
);
});
}
);
});
31 changes: 31 additions & 0 deletions packages/n4s/src/testUtils/rules.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export function goodBooleanRule(bool) {
return bool;
}

export function goodObjectRule(bool) {
return {
pass: bool,
message: 'What did you do Carl!?',
};
}

export function goodObjectMessageRule(bool) {
return {
pass: bool,
};
}

export function goodObjectMessageFunctionRule(bool) {
return {
pass: bool,
message: () => `I passed with ${bool}`,
};
}

export function badObjectRule() {
return { message: 'Something went wrong' };
}

export function nullRule() {
return null;
}

0 comments on commit b633f09

Please sign in to comment.