Skip to content

Commit

Permalink
patch: consolidate state into a single source of truth
Browse files Browse the repository at this point in the history
  • Loading branch information
ealush committed May 31, 2020
1 parent 2fcaeda commit 72decaf
Show file tree
Hide file tree
Showing 43 changed files with 1,520 additions and 997 deletions.
6 changes: 6 additions & 0 deletions packages/vest/src/__snapshots__/spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Object {
"tests": Object {
"doloribus-enim-quisquam": Object {
"errorCount": 0,
"testCount": 2,
"warnCount": 0,
},
},
Expand All @@ -41,13 +42,15 @@ Object {
"tests": Object {
"non-rem-dolorem": Object {
"errorCount": 0,
"testCount": 1,
"warnCount": 0,
},
"sed-minima-adipisci": Object {
"errorCount": 1,
"errors": Array [
"Aliquam reprehenderit iure omnis assumenda eligendi enim id praesentium numquam.",
],
"testCount": 1,
"warnCount": 0,
},
},
Expand All @@ -72,6 +75,7 @@ Object {
"tests": Object {
"doloribus-enim-quisquam": Object {
"errorCount": 0,
"testCount": 1,
"warnCount": 0,
},
},
Expand All @@ -96,6 +100,7 @@ Object {
"tests": Object {
"autem": Object {
"errorCount": 0,
"testCount": 1,
"warnCount": 1,
"warnings": Array [
"Temporibus ex ex.",
Expand Down Expand Up @@ -123,6 +128,7 @@ Object {
"tests": Object {
"autem": Object {
"errorCount": 0,
"testCount": 2,
"warnCount": 1,
"warnings": Array [
"Temporibus ex ex.",
Expand Down
23 changes: 8 additions & 15 deletions packages/vest/src/core/Context/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ class Context {
this.suite_id = suiteId;
}

get currentTest() {
return this.lookup('current_test');
}

set currentTest(testObject) {
this.current_test = testObject;
}

get groupName() {
return this.lookup('group_name');
}
Expand Down Expand Up @@ -70,21 +78,6 @@ class Context {
removeChildContext() {
this.childContext = null;
}

/**
* Sets a testObject reference on context.
* @param {VestTest} A VestTest instance.
*/
setCurrentTest(testObject) {
this.currentTest = testObject;
}

/**
* Removes current test from context.
*/
removeCurrentTest() {
delete this.currentTest;
}
}

export default Context;
5 changes: 2 additions & 3 deletions packages/vest/src/core/createSuite/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import validateSuiteParams from '../../lib/validateSuiteParams';
import produce from '../produce';
import getSuiteState from '../state/getSuiteState';
import registerSuite from '../state/registerSuite';
import { mergeSkipped } from '../test/lib/skipped';
import mergeExcludedTests from '../test/lib/mergeExcludedTests';
import runAsyncTest from '../test/runAsyncTest';

/**
Expand Down Expand Up @@ -34,12 +34,11 @@ const createSuite = (name, tests) => {
registerSuite();
const { suiteId } = context;
tests.apply(null, args);
mergeSkipped(suiteId);
mergeExcludedTests(suiteId);

[...getSuiteState(suiteId).pending].forEach(runAsyncTest);
return produce(getSuiteState(suiteId));
});

return output;
};
};
Expand Down
40 changes: 29 additions & 11 deletions packages/vest/src/core/produce/collectFailureMessages/index.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,39 @@
import { SEVERITY_GROUP_WARN } from '../../test/lib/VestTest/constants';

/**
* @param {string} suiteId Current suite id.
* @param {String} suiteId Current suite id.
* @param {'warn'|'error'} severity Filter by severity.
* @param {string} [group] Group to collect messages from.
* @param {Object} options
* @param {String} [options.group] Group name for error lookup.
* @param {String} [options.fieldName] Field name for error lookup.
* @returns all messages for given criteria.
*/
const collectFailureMessages = (state, severity, group) => {
const collector = {};
const collectFailureMessages = (state, severity, { group, fieldName } = {}) =>
state.testObjects.reduce((collector, testObject) => {
if (group && testObject.groupName !== group) {
return collector;
}

if (fieldName && testObject.fieldName !== fieldName) {
return collector;
}

const collectFrom = group ? state.groups[group] : state.tests;
if (!testObject.failed) {
return collector;
}

for (const fieldName in collectFrom) {
if (collectFrom?.[fieldName] && collectFrom?.[fieldName][severity]) {
collector[fieldName] = collectFrom[fieldName][severity];
if (
(severity !== SEVERITY_GROUP_WARN && testObject.isWarning) ||
(severity === SEVERITY_GROUP_WARN && !testObject.isWarning)
) {
return collector;
}
}

return collector;
};
collector[testObject.fieldName] = (
collector[testObject.fieldName] || []
).concat(testObject.statement);

return collector;
}, {});

export default collectFailureMessages;
82 changes: 82 additions & 0 deletions packages/vest/src/core/produce/genTestsSummary/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import {
SEVERITY_COUNT_WARN,
SEVERITY_COUNT_ERROR,
SEVERITY_GROUP_WARN,
SEVERITY_GROUP_ERROR,
TEST_COUNT,
} from '../../test/lib/VestTest/constants';

const genTestObject = (stateKey, testObject) => {
const { fieldName, isWarning, failed, statement } = testObject;

stateKey[fieldName] = stateKey[fieldName] || {
[SEVERITY_COUNT_WARN]: 0,
[SEVERITY_COUNT_ERROR]: 0,
[TEST_COUNT]: 0,
};

const testKey = stateKey[fieldName];

stateKey[fieldName][TEST_COUNT]++;

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);
}
}
}

return testKey;
};

/**
* Counts the failed tests and adds global counters
* @param {Object} state
*/
export const countFailures = state => {
state[SEVERITY_COUNT_ERROR] = 0;
state[SEVERITY_COUNT_WARN] = 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];
}
return state;
};

/**
* Reads the testObjects list and gets full validation result from it.
* @param {Object} state
*/
const genTestsSummary = state => {
state.tests = {};
state.groups = {};

state.testObjects.forEach(testObject => {
const { fieldName, groupName } = testObject;

state.tests[fieldName] = genTestObject(state.tests, testObject);

if (groupName) {
state.groups[groupName] = state.groups[groupName] || {};
state.groups[groupName][fieldName] = genTestObject(
state.groups[groupName],
testObject
);
}
});

return state;
};

export default genTestsSummary;
10 changes: 6 additions & 4 deletions packages/vest/src/core/produce/get/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import collectFailureMessages from '../collectFailureMessages';
* @returns suite or field's errors or warnings.
*/
const get = (state, severityKey, fieldName) => {
if (!fieldName) {
return collectFailureMessages(state, severityKey);
}
const res = collectFailureMessages(state, severityKey, { fieldName });

return state.tests?.[fieldName]?.[severityKey] ?? [];
if (fieldName) {
return res[fieldName] || [];
} else {
return res;
}
};

export default get;
10 changes: 6 additions & 4 deletions packages/vest/src/core/produce/getByGroup/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ const getByGroup = (state, severityKey, group, fieldName) => {
);
}

if (!fieldName) {
return collectFailureMessages(state, severityKey, group);
}
const res = collectFailureMessages(state, severityKey, { group, fieldName });

return state.groups?.[group]?.[fieldName]?.[severityKey] || [];
if (fieldName) {
return res[fieldName] || [];
} else {
return res;
}
};

export default getByGroup;
38 changes: 32 additions & 6 deletions packages/vest/src/core/produce/has/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,40 @@
import { SEVERITY_GROUP_WARN } from '../../test/lib/VestTest/constants';

/**
* Determines whether a certain test profile has failures.
* @param {string} suiteId
* @param {'errorCount'|'warnCount'} severityKey lookup severity
* @param {'warnings'|'errors'} severityKey lookup severity
* @param {string} [fieldName]
* @returns {Boolean} whether a suite or field have errors or warnings.
* @returns {Boolean}
*/
const has = (state, severityKey, fieldName) => {
if (!fieldName) {
return Boolean(state?.[severityKey]);
export const hasLogic = (testObject, severityKey, fieldName) => {
if (!testObject.failed) {
return false;
}

if (fieldName && fieldName !== testObject.fieldName) {
return false;
}
return Boolean(state?.tests?.[fieldName]?.[severityKey]);

if (
(severityKey === SEVERITY_GROUP_WARN && !testObject.isWarning) ||
(severityKey !== SEVERITY_GROUP_WARN && testObject.isWarning)
) {
return false;
}

return true;
};

/**
* @param {string} suiteId
* @param {'warnings'|'errors'} severityKey lookup severity
* @param {string} [fieldName]
* @returns {Boolean} whether a suite or field have errors or warnings.
*/
const has = (state, severityKey, fieldName) =>
state.testObjects.some(testObject =>
hasLogic(testObject, severityKey, fieldName)
);

export default has;
28 changes: 8 additions & 20 deletions packages/vest/src/core/produce/hasByGroup/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { hasLogic } from '../has';

/**
* Checks whether there are failures in a given group.
* @param {Object} state Reference to state object.
Expand All @@ -6,26 +8,12 @@
* @param {string} [fieldName] Field name.
* @return {boolean}
*/
const hasByGroup = (state, severityKey, group, fieldName) => {
// If no group is provided, or group does not exist
if (!(group && state.groups[group])) {
false;
}

// If field name is present, check if field has errors
if (fieldName) {
return Boolean(state.groups[group][fieldName]?.[severityKey]);
}

// If field name is not present, check if there's at least one failure in the group
for (const fieldName in state.groups[group]) {
if (state.groups[group][fieldName][severityKey]) {
return true;
const hasByGroup = (state, severityKey, group, fieldName) =>
state.testObjects.some(testObject => {
if (group !== testObject.groupName) {
return false;
}
}

// No failures
return false;
};
return hasLogic(testObject, severityKey, fieldName);
});

export default hasByGroup;
Loading

0 comments on commit 72decaf

Please sign in to comment.