diff --git a/packages/vest/src/core/test/runAsyncTest.ts b/packages/vest/src/core/test/runAsyncTest.ts index c6259d2d4..c857c0032 100644 --- a/packages/vest/src/core/test/runAsyncTest.ts +++ b/packages/vest/src/core/test/runAsyncTest.ts @@ -36,6 +36,8 @@ export default function runAsyncTest(testObject: VestTest): void { try { asyncTest.then(done, fail); } catch (e) { + // We will probably never get here, unless the consumer uses a buggy custom Promise + // implementation that behaves differently than the native one, or if they for some fail(); } } diff --git a/packages/vest/src/hooks/__tests__/exclusive.test.ts b/packages/vest/src/hooks/__tests__/exclusive.test.ts index 8cfe11d46..bf615c1e5 100644 --- a/packages/vest/src/hooks/__tests__/exclusive.test.ts +++ b/packages/vest/src/hooks/__tests__/exclusive.test.ts @@ -214,7 +214,29 @@ describe('exclusive hooks', () => { vest.skip(['group_1', 'group_2']); res = isGroupExcluded('group_3'); })(); - expect(res).toEqual(false); + expect(res).toBe(false); + }); + }); + + describe('Field is in a non included group', () => { + let suite; + + beforeEach(() => { + suite = vest.create(() => { + vest.only.group('group_1'); + + vest.group('group_1', () => { + vest.test('field_1', jest.fn()); + }); + vest.group('group_2', () => { + vest.test('field_2', jest.fn()); + }); + }); + suite(); + }); + + it('Should exclude test', () => { + expect(suite.get().tests.field_2.testCount).toBe(0); }); }); }); diff --git a/packages/vest/src/hooks/__tests__/include.test.ts b/packages/vest/src/hooks/__tests__/include.test.ts index 417ec0edf..a9fe0749a 100644 --- a/packages/vest/src/hooks/__tests__/include.test.ts +++ b/packages/vest/src/hooks/__tests__/include.test.ts @@ -280,6 +280,21 @@ describe('include', () => { expect(res).toMatchSnapshot(); }); }); + + describe('Field is included via `only`', () => { + it('Should disregard `when` condition and test the field anyway', () => { + const suite = vest.create(() => { + vest.only('field_1'); + vest.include('field_1').when(false); + + vest.test('field_1', () => false); + }); + + const res = suite(); + expect(res.hasErrors('field_1')).toBe(true); + expect(res.tests.field_1.testCount).toBe(1); + }); + }); describe('Test is excluded by being out of an included group', () => { it('Should disregard `include` and avoid running the test', () => { const suite = vest.create(() => { diff --git a/packages/vest/src/hooks/exclusive.ts b/packages/vest/src/hooks/exclusive.ts index 819494f24..5a85702e2 100644 --- a/packages/vest/src/hooks/exclusive.ts +++ b/packages/vest/src/hooks/exclusive.ts @@ -75,7 +75,7 @@ export function isExcluded(testObject: VestTest): boolean { } } - if (isMissingFromIncludedGroup(groupName)) { + if (isTopLevelWhenThereIsAnIncludedGroup(groupName)) { return true; } @@ -85,6 +85,8 @@ export function isExcluded(testObject: VestTest): boolean { // If there is _ANY_ `only`ed test (and we already know this one isn't) return true if (hasIncludedTests(keyTests)) { // Check if inclusion rules for this field (`include` hook) + // TODO: Check if this may need to be moved outside of the condition. + // What if there are no included tests? This shouldn't run then? return !optionalFunctionValue(inclusion[fieldName]); } @@ -92,41 +94,6 @@ export function isExcluded(testObject: VestTest): boolean { return false; } -// eslint-disable-next-line max-statements -function isMissingFromIncludedGroup(groupName?: string): boolean { - const context = ctx.useX(); - const exclusion = context.exclusion; - - if (!hasIncludedGroups()) { - return false; - } - - if (!groupName) { - return true; - } - - if (groupName in exclusion.groups) { - if (exclusion.groups[groupName]) { - return false; - } - return true; - } - - return true; -} - -function hasIncludedGroups(): boolean { - const context = ctx.useX(); - const exclusion = context.exclusion; - - for (const group in exclusion.groups) { - if (exclusion.groups[group]) { - return true; - } - } - return false; -} - /** * Checks whether a given group is excluded from running. */ @@ -144,14 +111,9 @@ export function isGroupExcluded(groupName: string): boolean { } // Group is not present - for (const group in keyGroups) { - // If any other group is only'ed - if (keyGroups[group] === true) { - return true; - } - } - return false; + // Return whether other groups are included + return hasIncludedGroups(); } /** @@ -190,6 +152,28 @@ function hasIncludedTests(keyTests: Record): boolean { return false; } +// are we not in a group and there is an included group? +function isTopLevelWhenThereIsAnIncludedGroup(groupName?: string): boolean { + if (!hasIncludedGroups()) { + return false; + } + + // Return whether there's an included group, and we're not inside a group + return !groupName; +} + +function hasIncludedGroups(): boolean { + const context = ctx.useX(); + const exclusion = context.exclusion; + + for (const group in exclusion.groups) { + if (exclusion.groups[group]) { + return true; + } + } + return false; +} + const enum ExclusionGroup { ONLY, SKIP, diff --git a/packages/vest/src/hooks/include.ts b/packages/vest/src/hooks/include.ts index 59c6687a7..bc008fbbe 100644 --- a/packages/vest/src/hooks/include.ts +++ b/packages/vest/src/hooks/include.ts @@ -27,8 +27,12 @@ export default function include(fieldName: string): { const context = ctx.useX(); const { inclusion, exclusion } = context; + // This callback will run as part of the "isExcluded" series of checks inclusion[fieldName] = (): boolean => { if (hasOwnProperty(exclusion.tests, fieldName)) { + // I suspect this code is technically unreachable because + // if there are any skip/only rules applied to the current + // field, the "isExcluded" function will have already bailed return defaultTo(exclusion.tests[fieldName], true); }