From 797fe4e466d23eb382763266f2ea0b0d4c84417b Mon Sep 17 00:00:00 2001 From: Evyatar Date: Sat, 24 Oct 2020 00:43:55 +0300 Subject: [PATCH] patch: reduce built size (#465) --- .eslintrc.js | 1 + .travis.yml | 2 +- .../src/core/produce/genTestsSummary/index.js | 119 +++++++++--------- packages/vest/src/core/produce/index.js | 36 +++--- packages/vest/src/core/produce/spec.js | 10 +- packages/vest/src/core/state/index.js | 10 +- packages/vest/src/core/suite/create/index.js | 9 +- packages/vest/src/core/suite/create/spec.js | 5 - packages/vest/src/core/test/index.js | 11 +- .../vest/src/core/test/runAsyncTest/index.js | 7 +- packages/vest/src/hooks/draft/index.js | 2 +- packages/vest/src/hooks/exclusive/index.js | 15 +-- packages/vest/src/lib/callEach/index.js | 3 + 13 files changed, 119 insertions(+), 111 deletions(-) create mode 100644 packages/vest/src/lib/callEach/index.js diff --git a/.eslintrc.js b/.eslintrc.js index fa57fa1bf..1b056cff1 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -55,6 +55,7 @@ module.exports = { 'no-implicit-globals': 2, 'no-lonely-if': 2, 'no-multi-spaces': 1, + 'no-prototype-builtins': 0, 'no-trailing-spaces': [2, { ignoreComments: false }], 'no-unneeded-ternary': 2, 'no-unused-expressions': 2, diff --git a/.travis.yml b/.travis.yml index 49ef065b3..d59444a0e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ jobs: - yarn test - yarn lint - stage: Release - if: type = push AND fork = false + if: branch = release AND type = push AND fork = false install: yarn install --frozen-lockfile script: - echo //registry.npmjs.org/:_authToken=$NPM_TOKEN > ~/.npmrc diff --git a/packages/vest/src/core/produce/genTestsSummary/index.js b/packages/vest/src/core/produce/genTestsSummary/index.js index df3901135..9f215c72f 100644 --- a/packages/vest/src/core/produce/genTestsSummary/index.js +++ b/packages/vest/src/core/produce/genTestsSummary/index.js @@ -9,90 +9,87 @@ import { } from '../../test/lib/VestTest/constants'; /** - * - * @param {Object} summaryKey The container for the test result data - * @param {VestTest} testObject - * @returns {Object} Test result summary + * Reads the testObjects list and gets full validation result from it. */ -const genTestObject = (summaryKey, testObject) => { - const { fieldName, isWarning, failed, statement } = testObject; +const genTestsSummary = () => { + const [testObjects] = useTestObjects(); + const [suiteIdState] = useSuiteId(); - summaryKey[fieldName] = summaryKey[fieldName] || { - [SEVERITY_COUNT_WARN]: 0, - [SEVERITY_COUNT_ERROR]: 0, - [TEST_COUNT]: 0, + const summary = { + tests: {}, + groups: {}, + name: suiteIdState.name, }; - const testKey = summaryKey[fieldName]; + testObjects.forEach(testObject => { + const { fieldName, groupName } = testObject; - summaryKey[fieldName][TEST_COUNT]++; + summary.tests[fieldName] = genTestObject(summary.tests, testObject); - if (failed) { - if (isWarning) { - testKey[SEVERITY_COUNT_WARN]++; - if (statement) { - testKey[SEVERITY_GROUP_WARN] = ( - testKey[SEVERITY_GROUP_WARN] || [] - ).concat(statement); - } - } else { - testKey[SEVERITY_COUNT_ERROR]++; - if (statement) { - testKey[SEVERITY_GROUP_ERROR] = ( - testKey[SEVERITY_GROUP_ERROR] || [] - ).concat(statement); - } + if (groupName) { + summary.groups[groupName] = summary.groups[groupName] || {}; + summary.groups[groupName][fieldName] = genTestObject( + summary.groups[groupName], + testObject + ); } - } + }); - return testKey; + return countFailures(summary); }; /** * Counts the failed tests and adds global counters - * @param {Object} state + * @param {Object} summary (generated by genTestsSummary) */ -export const countFailures = state => { - state[SEVERITY_COUNT_ERROR] = 0; - state[SEVERITY_COUNT_WARN] = 0; - state[TEST_COUNT] = 0; - for (const test in state.tests) { - state[SEVERITY_COUNT_ERROR] += state.tests[test][SEVERITY_COUNT_ERROR]; - state[SEVERITY_COUNT_WARN] += state.tests[test][SEVERITY_COUNT_WARN]; - state[TEST_COUNT] += state.tests[test][TEST_COUNT]; +export const countFailures = summary => { + summary[SEVERITY_COUNT_ERROR] = 0; + summary[SEVERITY_COUNT_WARN] = 0; + summary[TEST_COUNT] = 0; + + for (const test in summary.tests) { + summary[SEVERITY_COUNT_ERROR] += summary.tests[test][SEVERITY_COUNT_ERROR]; + summary[SEVERITY_COUNT_WARN] += summary.tests[test][SEVERITY_COUNT_WARN]; + summary[TEST_COUNT] += summary.tests[test][TEST_COUNT]; } - return state; + return summary; }; +export default genTestsSummary; + /** - * Reads the testObjects list and gets full validation result from it. - * @param {Object} state + * + * @param {Object} summaryKey The container for the test result data + * @param {VestTest} testObject + * @returns {Object} Test result summary */ -const genTestsSummary = () => { - const [testObjects] = useTestObjects(); - const [suiteIdState] = useSuiteId(); +const genTestObject = (summaryKey, testObject) => { + const { fieldName, isWarning, failed, statement } = testObject; - const state = { - tests: {}, - groups: {}, - name: suiteIdState.name, + summaryKey[fieldName] = summaryKey[fieldName] || { + [SEVERITY_COUNT_WARN]: 0, + [SEVERITY_COUNT_ERROR]: 0, + [TEST_COUNT]: 0, }; - testObjects.forEach(testObject => { - const { fieldName, groupName } = testObject; + const testKey = summaryKey[fieldName]; - state.tests[fieldName] = genTestObject(state.tests, testObject); + summaryKey[fieldName][TEST_COUNT]++; - if (groupName) { - state.groups[groupName] = state.groups[groupName] || {}; - state.groups[groupName][fieldName] = genTestObject( - state.groups[groupName], - testObject - ); + const addTo = (count, group) => { + testKey[count]++; + if (statement) { + testKey[group] = (testKey[group] || []).concat(statement); } - }); + }; - return state; -}; + if (failed) { + if (isWarning) { + addTo(SEVERITY_COUNT_WARN, SEVERITY_GROUP_WARN); + } else { + addTo(SEVERITY_COUNT_ERROR, SEVERITY_GROUP_ERROR); + } + } -export default genTestsSummary; + return testKey; +}; diff --git a/packages/vest/src/core/produce/index.js b/packages/vest/src/core/produce/index.js index 8f2c48e83..ea01c69d8 100644 --- a/packages/vest/src/core/produce/index.js +++ b/packages/vest/src/core/produce/index.js @@ -8,7 +8,7 @@ import { SEVERITY_GROUP_ERROR, SEVERITY_GROUP_WARN, } from '../test/lib/VestTest/constants'; -import genTestsSummary, { countFailures } from './genTestsSummary'; +import genTestsSummary from './genTestsSummary'; import get from './get'; import getByGroup from './getByGroup'; import has from './has'; @@ -36,7 +36,7 @@ const done = (...args) => { } const cb = context.bind({ stateRef }, () => - callback(produce({ draft: true })) + callback(produce(/*isDraft:*/ true)) ); // is suite finished || field name exists, and test is finished @@ -63,19 +63,18 @@ const done = (...args) => { }; /** - * @param {Object} Options - * @param {boolean} [Options.draft] + * @param {boolean} [isDraft] * @returns Vest output object. */ -const produce = ({ draft } = {}) => { +const produce = isDraft => { const { stateRef } = context.use(); const [testObjects] = useTestObjects(); return cache( - [testObjects, draft], + [testObjects, isDraft], context.bind({ stateRef }, () => Object.defineProperties( - countFailures(genTestsSummary()), + genTestsSummary(), [ ['hasErrors', context.bind({ stateRef }, has, SEVERITY_GROUP_ERROR)], ['hasWarnings', context.bind({ stateRef }, has, SEVERITY_GROUP_WARN)], @@ -98,16 +97,19 @@ const produce = ({ draft } = {}) => { context.bind({ stateRef }, getByGroup, SEVERITY_GROUP_WARN), ], ] - .concat(draft ? [] : [['done', context.bind({ stateRef }, done)]]) - .reduce((properties, [name, value]) => { - properties[name] = { - configurable: true, - enumerable: true, - value, - writeable: true, - }; - return properties; - }, {}) + .concat(isDraft ? [] : [['done', context.bind({ stateRef }, done)]]) + .reduce( + (properties, [name, value]) => ( + (properties[name] = { + configurable: true, + enumerable: true, + value, + writeable: true, + }), + properties + ), + {} + ) ) ) ); diff --git a/packages/vest/src/core/produce/spec.js b/packages/vest/src/core/produce/spec.js index e7a14f1ef..0bef195f8 100644 --- a/packages/vest/src/core/produce/spec.js +++ b/packages/vest/src/core/produce/spec.js @@ -109,7 +109,7 @@ describe('module: produce', () => { describe('When draft: true', () => { beforeEach(() => { runCreateSuite('suiteName'); - produced = runProduce({ draft: true }); + produced = runProduce(/*isDraft:*/ true); }); it.each(DRAFT_EXCLUDED_METHODS)( @@ -726,7 +726,7 @@ describe('module: produce', () => { draft = vest.draft(); getStateFromContext(); expect(draft).toBe(vest.draft()); - expect(produce({ draft: true })).toBe(validate.get()); + expect(produce(/*isDraft:*/ true)).toBe(validate.get()); testDummy(vest).failing(); expect(produce()).not.toBe(validate.get()); expect(draft).not.toBe(vest.draft()); @@ -742,15 +742,15 @@ describe('module: produce', () => { }); expect(control).toHaveBeenCalledTimes(1); context.run({ stateRef }, () => { - expect(produce({ draft: true })).toBe(validate.get()); + expect(produce(/*isDraft:*/ true)).toBe(validate.get()); expect(res).not.toBe(draft); - expect(res).not.toBe(produce({ draft: true })); + expect(res).not.toBe(produce(/*isDraft:*/ true)); expect(draft).not.toBe(validate.get()); res = validate().done(result => { expect(result).toBe(validate.get()); }); expect(res).not.toBe(draft); - expect(res).not.toBe(produce({ draft: true })); + expect(res).not.toBe(produce(/*isDraft:*/ true)); expect(control).toHaveBeenCalledTimes(2); }); } diff --git a/packages/vest/src/core/state/index.js b/packages/vest/src/core/state/index.js index 089f53377..7af37b9ad 100644 --- a/packages/vest/src/core/state/index.js +++ b/packages/vest/src/core/state/index.js @@ -1,3 +1,4 @@ +import callEach from '../../lib/callEach'; import isFunction from '../../lib/isFunction'; import context from '../context'; @@ -10,7 +11,7 @@ export default (function createState() { // Register state handler if (reg) { key = reg.key; - if (!Object.prototype.hasOwnProperty.call(stateRef.current(), key)) { + if (!stateRef.current().hasOwnProperty(key)) { stateRef.set( key, isFunction(initialValue) @@ -50,17 +51,14 @@ export default (function createState() { } function set(key, value) { - state = { - ...state, - [key]: value, - }; + Object.assign(state, { [key]: value }); } function reset() { state.length = 0; state = {}; - registeredHandlers.forEach(fn => fn()); + callEach(registeredHandlers); } const stateRef = { diff --git a/packages/vest/src/core/suite/create/index.js b/packages/vest/src/core/suite/create/index.js index 42196de15..080e25e2b 100644 --- a/packages/vest/src/core/suite/create/index.js +++ b/packages/vest/src/core/suite/create/index.js @@ -31,6 +31,12 @@ const createSuite = (...args) => { useTestObjects, }); + /* + context.bind returns our `validate` function + We then wrap it with defineProperties to add + the `get`, and `reset` functions. + + */ return Object.defineProperties( context.bind({ stateRef }, function () { const [previousTestObjects] = useTestObjects(); @@ -43,9 +49,8 @@ const createSuite = (...args) => { }), { get: { - value: context.bind({ stateRef }, produce, { draft: true }), + value: context.bind({ stateRef }, produce, /*isDraft:*/ true), }, - name: { value: 'validate' }, reset: { value: stateRef.reset }, } ); diff --git a/packages/vest/src/core/suite/create/spec.js b/packages/vest/src/core/suite/create/spec.js index eb6e9982f..249bc8edf 100644 --- a/packages/vest/src/core/suite/create/spec.js +++ b/packages/vest/src/core/suite/create/spec.js @@ -7,7 +7,6 @@ describe('Test createSuite module', () => { describe('Test suite Arguments', () => { it('allows omitting suite name', () => { expect(typeof create(Function.prototype)).toBe('function'); - expect(create(Function.prototype).name).toBe('validate'); expect(typeof create(Function.prototype).get).toBe('function'); expect(typeof create(Function.prototype).reset).toBe('function'); expect(create(Function.prototype).get()).toMatchSnapshot(); @@ -30,10 +29,6 @@ describe('Test createSuite module', () => { it('should be a function', () => { expect(typeof create('suiteName', noop)).toBe('function'); }); - - test('returned function name is `validate`', () => { - expect(create('boop', noop).name).toBe('validate'); - }); }); describe('When returned function is invoked', () => { diff --git a/packages/vest/src/core/test/index.js b/packages/vest/src/core/test/index.js index ada8a39c0..72b94cc75 100644 --- a/packages/vest/src/core/test/index.js +++ b/packages/vest/src/core/test/index.js @@ -102,6 +102,15 @@ const test = (fieldName, ...args) => { return testObject; }; +/** + * Caches, or returns an already cached test call + * @param {String} fieldName Name of the field to test. + * @param {String} [statement] The message returned in case of a failure. + * @param {function} testFn The actual test callback. + * @param {any[]} deps Dependency array. + * @return {VestTest} A VestTest instance. + + */ test.memo = (fieldName, ...args) => { cache = cache || createCache(100); @@ -119,7 +128,7 @@ test.memo = (fieldName, ...args) => { return cache(dependencies, () => test(fieldName, msg, testFn)); } - const { 1: testObject } = cached; + const [, testObject] = cached; if (isExcluded(testObject)) { return testObject; diff --git a/packages/vest/src/core/test/runAsyncTest/index.js b/packages/vest/src/core/test/runAsyncTest/index.js index bce9b3522..3f6763f9e 100644 --- a/packages/vest/src/core/test/runAsyncTest/index.js +++ b/packages/vest/src/core/test/runAsyncTest/index.js @@ -1,3 +1,4 @@ +import callEach from '../../../lib/callEach'; import context from '../../context'; import useTestCallbacks from '../../state/useTestCallbacks'; import useTestObjects from '../../state/useTestObjects'; @@ -28,7 +29,7 @@ const runAsyncTest = testObject => { testObject.fail(); // Spreading the array to invalidate the cache - useTestObjects(testObjects => [...testObjects]); + useTestObjects(testObjects => testObjects.slice()); done(); }); try { @@ -50,11 +51,11 @@ const runDoneCallbacks = fieldName => { !hasRemainingTests(fieldName) && Array.isArray(fieldCallbacks[fieldName]) ) { - fieldCallbacks[fieldName].forEach(cb => cb()); + callEach(fieldCallbacks[fieldName]); } } if (!hasRemainingTests()) { - doneCallbacks.forEach(cb => cb()); + callEach(doneCallbacks); } }; diff --git a/packages/vest/src/hooks/draft/index.js b/packages/vest/src/hooks/draft/index.js index eadc47546..29f97ff62 100644 --- a/packages/vest/src/hooks/draft/index.js +++ b/packages/vest/src/hooks/draft/index.js @@ -14,7 +14,7 @@ const draft = () => { return; } - return produce({ draft: true }); + return produce(/*isDraft:*/ true); }; export default draft; diff --git a/packages/vest/src/hooks/exclusive/index.js b/packages/vest/src/hooks/exclusive/index.js index 56f0e7dd4..cf76cbf22 100644 --- a/packages/vest/src/hooks/exclusive/index.js +++ b/packages/vest/src/hooks/exclusive/index.js @@ -64,9 +64,9 @@ skip.group = item => const isExcluded = testObject => { const { fieldName, groupName } = testObject; - const ctx = context.use(); + const { exclusion } = context.use(); - const keyTests = ctx.exclusion[EXCLUSION_ITEM_TYPE_TESTS]; + const keyTests = exclusion[EXCLUSION_ITEM_TYPE_TESTS]; const testValue = keyTests[fieldName]; // if test is skipped @@ -83,7 +83,7 @@ const isExcluded = testObject => { return true; // field excluded by group // if group is `only`ed - } else if (ctx.exclusion[EXCLUSION_ITEM_TYPE_GROUPS][groupName] === true) { + } else if (exclusion[EXCLUSION_ITEM_TYPE_GROUPS][groupName] === true) { if (isTestIncluded) { return false; } @@ -127,13 +127,10 @@ const hasIncludedTests = keyTests => { * @return {Boolean} */ const isGroupExcluded = groupName => { - const ctx = context.use(); - const keyGroups = ctx.exclusion[EXCLUSION_ITEM_TYPE_GROUPS]; + const { exclusion } = context.use(); + const keyGroups = exclusion[EXCLUSION_ITEM_TYPE_GROUPS]; - const groupPresent = Object.prototype.hasOwnProperty.call( - keyGroups, - groupName - ); + const groupPresent = keyGroups.hasOwnProperty(groupName); // When group is either only'ed or skipped if (groupPresent) { diff --git a/packages/vest/src/lib/callEach/index.js b/packages/vest/src/lib/callEach/index.js new file mode 100644 index 000000000..8f8b20e16 --- /dev/null +++ b/packages/vest/src/lib/callEach/index.js @@ -0,0 +1,3 @@ +export default function callEach(arr) { + return arr.forEach(fn => fn()); +}