import { describe, it, expect, vi } from 'vitest'; import * as vest from '../../vest'; enum GroupNames { G1 = 'g1', G2 = 'g2', } enum FieldNames { F1 = 'f1', F2 = 'f2', F3 = 'f3', F4 = 'f4', } describe('named group', () => { it('should run the group callback', () => { const groupName = 'groupName'; const callback = vi.fn(); vest .create(() => { vest.group(groupName, callback); }) .run(); expect(callback).toHaveBeenCalled(); }); it('should run the tests inside the named group', () => { const cb1 = vi.fn(() => false); const cb2 = vi.fn(() => false); const cb3 = vi.fn(() => {}); const suite = vest.create(() => { vest.mode(vest.Modes.ALL); vest.test(FieldNames.F1, () => false); vest.group(GroupNames.G1, () => { vest.test(FieldNames.F1, cb1); vest.test(FieldNames.F2, cb2); vest.test(FieldNames.F3, cb3); }); }); const res = suite.run(); expect(res.hasErrors(FieldNames.F1)).toBe(true); expect(res.hasErrors(FieldNames.F2)).toBe(true); expect(res.hasErrors(FieldNames.F3)).toBe(false); expect(res.hasErrorsByGroup(GroupNames.G1)).toBe(true); expect(res.hasErrorsByGroup(GroupNames.G1, FieldNames.F1)).toBe(true); expect(res.hasErrorsByGroup(GroupNames.G1, FieldNames.F2)).toBe(true); expect(res.hasErrorsByGroup(GroupNames.G1, FieldNames.F3)).toBe(false); expect(cb1).toHaveBeenCalled(); expect(cb2).toHaveBeenCalled(); expect(cb3).toHaveBeenCalled(); expect(res.isValid()).toBe(false); expect(res.tests[FieldNames.F1].testCount).toBe(2); expect(res.tests[FieldNames.F1].pendingCount).toBe(0); expect(res.tests[FieldNames.F2].testCount).toBe(1); expect(res.tests[FieldNames.F3].testCount).toBe(1); expect(res.tests[FieldNames.F2].pendingCount).toBe(0); expect(res.tests[FieldNames.F1].errorCount).toBe(2); expect(res.tests[FieldNames.F2].errorCount).toBe(1); expect(res.tests[FieldNames.F3].errorCount).toBe(0); expect(res.tests[FieldNames.F3].pendingCount).toBe(0); expect(res.groups[GroupNames.G1][FieldNames.F1].errorCount).toBe(1); expect(res.groups[GroupNames.G1][FieldNames.F1].testCount).toBe(1); expect(res.groups[GroupNames.G1][FieldNames.F1].pendingCount).toBe(0); expect(res.groups[GroupNames.G1][FieldNames.F2].errorCount).toBe(1); expect(res.groups[GroupNames.G1][FieldNames.F2].testCount).toBe(1); expect(res.groups[GroupNames.G1][FieldNames.F2].pendingCount).toBe(0); expect(res.groups[GroupNames.G1][FieldNames.F3].errorCount).toBe(0); expect(res.groups[GroupNames.G1][FieldNames.F3].testCount).toBe(1); expect(res.groups[GroupNames.G1][FieldNames.F3].pendingCount).toBe(0); expect(suite.get()).toMatchSnapshot(); }); describe('multiple named groups', () => { it('should run the tests inside each named group', () => { const cb1 = vi.fn(() => false); const cb2 = vi.fn(() => false); const cb3 = vi.fn(() => {}); const suite = vest.create(() => { vest.mode(vest.Modes.ALL); vest.test(FieldNames.F1, () => false); vest.group(GroupNames.G1, () => { vest.test(FieldNames.F1, cb1); vest.test(FieldNames.F2, cb2); vest.test(FieldNames.F3, cb3); }); vest.group(GroupNames.G2, () => { vest.test(FieldNames.F1, cb1); vest.test(FieldNames.F2, cb2); vest.test(FieldNames.F3, cb3); }); }); const res = suite.run(); expect(res.hasErrors(FieldNames.F1)).toBe(true); expect(res.hasErrors(FieldNames.F2)).toBe(true); expect(res.hasErrors(FieldNames.F3)).toBe(false); expect(res.hasErrorsByGroup(GroupNames.G1)).toBe(true); expect(res.hasErrorsByGroup(GroupNames.G1, FieldNames.F1)).toBe(true); expect(res.hasErrorsByGroup(GroupNames.G1, FieldNames.F2)).toBe(true); expect(res.hasErrorsByGroup(GroupNames.G1, FieldNames.F3)).toBe(false); expect(res.hasErrorsByGroup(GroupNames.G2)).toBe(true); expect(res.hasErrorsByGroup(GroupNames.G2, FieldNames.F1)).toBe(true); expect(res.hasErrorsByGroup(GroupNames.G2, FieldNames.F2)).toBe(true); expect(res.hasErrorsByGroup(GroupNames.G2, FieldNames.F3)).toBe(false); expect(cb1).toHaveBeenCalledTimes(2); expect(cb2).toHaveBeenCalledTimes(2); expect(cb3).toHaveBeenCalledTimes(2); expect(res.isValid()).toBe(false); expect(res.tests[FieldNames.F1].testCount).toBe(3); expect(res.tests[FieldNames.F2].testCount).toBe(2); expect(res.tests[FieldNames.F3].testCount).toBe(2); expect(res.tests[FieldNames.F1].errorCount).toBe(3); expect(res.tests[FieldNames.F2].errorCount).toBe(2); expect(res.tests[FieldNames.F3].errorCount).toBe(0); expect(res.groups[GroupNames.G1][FieldNames.F1].errorCount).toBe(1); expect(res.groups[GroupNames.G1][FieldNames.F1].testCount).toBe(1); expect(res.groups[GroupNames.G1][FieldNames.F2].errorCount).toBe(1); expect(res.groups[GroupNames.G1][FieldNames.F2].testCount).toBe(1); expect(res.groups[GroupNames.G1][FieldNames.F3].errorCount).toBe(0); expect(res.groups[GroupNames.G1][FieldNames.F3].testCount).toBe(1); expect(res.groups[GroupNames.G2][FieldNames.F1].errorCount).toBe(1); expect(res.groups[GroupNames.G2][FieldNames.F1].testCount).toBe(1); expect(res.groups[GroupNames.G2][FieldNames.F2].errorCount).toBe(1); expect(res.groups[GroupNames.G2][FieldNames.F2].testCount).toBe(1); expect(res.groups[GroupNames.G2][FieldNames.F3].errorCount).toBe(0); expect(res.groups[GroupNames.G2][FieldNames.F3].testCount).toBe(1); expect(suite.get()).toMatchSnapshot(); }); }); describe('focus behavior', () => { describe('skip outside of group', () => { it('should skip tests for a field both inside and outside the group when skipped before grouping', () => { const cb1 = vi.fn(() => false); const cb2 = vi.fn(() => false); const suite = vest.create(() => { vest.mode(vest.Modes.ALL); vest.skip(FieldNames.F1); vest.test(FieldNames.F1, cb1); vest.group(GroupNames.G1, () => { vest.test(FieldNames.F1, cb1); vest.test(FieldNames.F2, cb2); }); }); const res = suite.run(); expect(cb1).not.toHaveBeenCalled(); expect(cb2).toHaveBeenCalledTimes(1); expect(res.tests[FieldNames.F1].testCount).toBe(0); expect(res.tests[FieldNames.F2].testCount).toBe(1); expect(res.groups[GroupNames.G1][FieldNames.F1].testCount).toBe(0); expect(res.groups[GroupNames.G1][FieldNames.F2].testCount).toBe(1); expect(res.isValid()).toBe(false); expect(res.hasErrors(FieldNames.F1)).toBe(false); expect(res.hasErrors(FieldNames.F2)).toBe(true); expect(suite.get()).toMatchSnapshot(); }); }); describe('skip inside the group', () => { it('should skip the field only within the current group', () => { const cb1 = vi.fn(() => false); const cb2 = vi.fn(() => false); const cb3 = vi.fn(() => false); const suite = vest.create(() => { vest.mode(vest.Modes.ALL); vest.test(FieldNames.F1, cb1); vest.group(GroupNames.G1, () => { vest.skip(FieldNames.F2); vest.test(FieldNames.F1, cb1); vest.test(FieldNames.F2, cb2); }); vest.test(FieldNames.F2, cb3); }); const res = suite.run(); expect(cb1).toHaveBeenCalledTimes(2); expect(cb2).toHaveBeenCalledTimes(0); expect(cb3).toHaveBeenCalledTimes(1); expect(res.tests[FieldNames.F1].testCount).toBe(2); expect(res.tests[FieldNames.F2].testCount).toBe(1); expect(res.groups[GroupNames.G1][FieldNames.F1].testCount).toBe(1); expect(res.groups[GroupNames.G1][FieldNames.F2].testCount).toBe(0); expect(res.isValid()).toBe(false); expect(res.hasErrors(FieldNames.F1)).toBe(true); expect(res.hasErrors(FieldNames.F2)).toBe(true); expect(suite.get()).toMatchSnapshot(); }); it('should skip the field only within the current group and not affect the next group', () => { const cb1 = vi.fn(() => false); const cb2 = vi.fn(() => false); const cb3 = vi.fn(() => false); const suite = vest.create(() => { vest.mode(vest.Modes.ALL); vest.test(FieldNames.F1, cb1); vest.group(GroupNames.G1, () => { vest.skip(FieldNames.F2); vest.test(FieldNames.F1, cb1); vest.test(FieldNames.F2, cb2); }); vest.group(GroupNames.G2, () => { vest.test(FieldNames.F2, cb3); }); }); const res = suite.run(); expect(cb1).toHaveBeenCalledTimes(2); expect(cb2).toHaveBeenCalledTimes(0); expect(cb3).toHaveBeenCalledTimes(1); expect(res.tests[FieldNames.F1].testCount).toBe(2); expect(res.tests[FieldNames.F2].testCount).toBe(1); expect(res.groups[GroupNames.G1][FieldNames.F1].testCount).toBe(1); expect(res.groups[GroupNames.G1][FieldNames.F2].testCount).toBe(0); expect(res.groups[GroupNames.G2][FieldNames.F2].testCount).toBe(1); expect(res.isValid()).toBe(false); expect(res.hasErrors(FieldNames.F1)).toBe(true); expect(res.hasErrors(FieldNames.F2)).toBe(true); expect(suite.get()).toMatchSnapshot(); }); describe('skip(true)', () => { it('should skip all tests in the current group only', () => { const cb1 = vi.fn(() => false); const cb2 = vi.fn(() => false); const cb3 = vi.fn(() => false); const suite = vest.create(() => { vest.mode(vest.Modes.ALL); vest.group(GroupNames.G1, () => { vest.skip(true); vest.test(FieldNames.F1, cb1); vest.test(FieldNames.F2, cb1); }); vest.group(GroupNames.G2, () => { vest.test(FieldNames.F2, cb3); vest.test(FieldNames.F3, cb3); }); vest.test(FieldNames.F1, cb2); vest.test(FieldNames.F2, cb2); vest.test(FieldNames.F3, cb3); }); const res = suite.run(); expect(cb1).toHaveBeenCalledTimes(0); expect(cb2).toHaveBeenCalledTimes(2); expect(cb3).toHaveBeenCalledTimes(3); expect(res.tests[FieldNames.F1].testCount).toBe(1); expect(res.tests[FieldNames.F2].testCount).toBe(2); expect(res.tests[FieldNames.F3].testCount).toBe(2); expect(res.groups[GroupNames.G1][FieldNames.F1].testCount).toBe(0); expect(res.groups[GroupNames.G1][FieldNames.F2].testCount).toBe(0); expect(res.groups[GroupNames.G2][FieldNames.F2].testCount).toBe(1); expect(res.groups[GroupNames.G2][FieldNames.F3].testCount).toBe(1); expect(res.isValid()).toBe(false); expect(res.hasErrors(FieldNames.F1)).toBe(true); expect(res.hasErrors(FieldNames.F2)).toBe(true); expect(res.hasErrors(FieldNames.F3)).toBe(true); expect(suite.get()).toMatchSnapshot(); }); }); }); describe('only', () => { describe('top level only', () => { it('should run only tests for the focused field across all groups', () => { const cb1 = vi.fn(() => false); const cb2 = vi.fn(() => false); const cb3 = vi.fn(() => false); const cb4 = vi.fn(() => false); const suite = vest.create(() => { vest.mode(vest.Modes.ALL); vest.only(FieldNames.F1); vest.test(FieldNames.F1, cb1); vest.test(FieldNames.F2, cb4); vest.test(FieldNames.F3, cb4); vest.group(GroupNames.G1, () => { vest.test(FieldNames.F1, cb2); vest.test(FieldNames.F2, cb4); vest.test(FieldNames.F3, cb4); }); vest.group(GroupNames.G2, () => { vest.test(FieldNames.F1, cb3); vest.test(FieldNames.F2, cb4); vest.test(FieldNames.F3, cb4); }); }); const res = suite.run(); expect(cb1).toHaveBeenCalledTimes(1); expect(cb2).toHaveBeenCalledTimes(1); expect(cb3).toHaveBeenCalledTimes(1); expect(cb4).toHaveBeenCalledTimes(0); expect(res.tests[FieldNames.F1].testCount).toBe(3); expect(res.tests[FieldNames.F2].testCount).toBe(0); expect(res.tests[FieldNames.F3].testCount).toBe(0); expect(res.groups[GroupNames.G1][FieldNames.F1].testCount).toBe(1); expect(res.groups[GroupNames.G1][FieldNames.F2].testCount).toBe(0); expect(res.groups[GroupNames.G1][FieldNames.F3].testCount).toBe(0); expect(res.groups[GroupNames.G2][FieldNames.F1].testCount).toBe(1); expect(res.groups[GroupNames.G2][FieldNames.F2].testCount).toBe(0); expect(res.groups[GroupNames.G2][FieldNames.F3].testCount).toBe(0); expect(res.isValid()).toBe(false); expect(res.hasErrors(FieldNames.F1)).toBe(true); expect(res.hasErrors(FieldNames.F2)).toBe(false); expect(res.hasErrors(FieldNames.F3)).toBe(false); expect(suite.get()).toMatchSnapshot(); }); }); describe('group only', () => { it('should run only tests for the focused field within the group and run everything in other groups', () => { const cb1 = vi.fn(() => false); const cb2 = vi.fn(() => false); const cb3 = vi.fn(() => false); const suite = vest.create(() => { vest.mode(vest.Modes.ALL); vest.group(GroupNames.G1, () => { vest.only(FieldNames.F1); vest.test(FieldNames.F1, cb1); vest.test(FieldNames.F2, cb2); vest.test(FieldNames.F3, cb2); }); vest.group(GroupNames.G2, () => { vest.test(FieldNames.F1, cb3); vest.test(FieldNames.F2, cb3); vest.test(FieldNames.F3, cb3); }); }); const res = suite.run(); expect(cb1).toHaveBeenCalledTimes(1); expect(cb2).toHaveBeenCalledTimes(0); expect(cb3).toHaveBeenCalledTimes(3); expect(res.tests[FieldNames.F1].testCount).toBe(2); expect(res.tests[FieldNames.F2].testCount).toBe(1); expect(res.tests[FieldNames.F3].testCount).toBe(1); expect(res.groups[GroupNames.G1][FieldNames.F1].testCount).toBe(1); expect(res.groups[GroupNames.G1][FieldNames.F2].testCount).toBe(0); expect(res.groups[GroupNames.G1][FieldNames.F3].testCount).toBe(0); expect(res.groups[GroupNames.G2][FieldNames.F1].testCount).toBe(1); expect(res.groups[GroupNames.G2][FieldNames.F2].testCount).toBe(1); expect(res.groups[GroupNames.G2][FieldNames.F3].testCount).toBe(1); expect(res.isValid()).toBe(false); expect(res.hasErrors(FieldNames.F1)).toBe(true); expect(res.hasErrors(FieldNames.F2)).toBe(true); expect(res.hasErrors(FieldNames.F3)).toBe(true); expect(suite.get()).toMatchSnapshot(); }); }); }); }); }); describe('unnamed groups', () => { it('should run tests inside the unnamed group normally', () => { const cb1 = vi.fn(() => false); const cb2 = vi.fn(() => false); const cb3 = vi.fn(() => false); const suite = vest.create(() => { vest.mode(vest.Modes.ALL); vest.group(() => { vest.test(FieldNames.F1, cb1); vest.test(FieldNames.F2, cb2); vest.test(FieldNames.F3, cb3); }); }); const res = suite.run(); expect(cb1).toHaveBeenCalledTimes(1); expect(cb2).toHaveBeenCalledTimes(1); expect(cb3).toHaveBeenCalledTimes(1); expect(res.tests[FieldNames.F1].testCount).toBe(1); expect(res.tests[FieldNames.F2].testCount).toBe(1); expect(res.tests[FieldNames.F3].testCount).toBe(1); expect(res.isValid()).toBe(false); expect(res.hasErrors(FieldNames.F1)).toBe(true); expect(res.hasErrors(FieldNames.F2)).toBe(true); expect(res.hasErrors(FieldNames.F3)).toBe(true); expect(suite.get()).toMatchSnapshot(); }); it('should not add the unnamed group to the results object', () => { const suite = vest.create(() => { vest.group(() => { vest.test(FieldNames.F1, () => false); vest.test(FieldNames.F2, () => false); vest.test(FieldNames.F3, () => false); }); }); const res = suite.run(); expect(res.groups).toEqual({}); expect(res.isValid()).toBe(false); expect(suite.get()).toMatchSnapshot(); }); describe('with only', () => { it('should run only tests for the focused field inside the unnamed group', () => { const cb1 = vi.fn(() => false); const cb2 = vi.fn(() => false); const cb3 = vi.fn(() => false); const suite = vest.create(() => { vest.mode(vest.Modes.ALL); vest.group(() => { vest.only(FieldNames.F1); vest.test(FieldNames.F1, cb1); vest.test(FieldNames.F2, cb2); vest.test(FieldNames.F3, cb3); }); }); const res = suite.run(); expect(cb1).toHaveBeenCalledTimes(1); expect(cb2).toHaveBeenCalledTimes(0); expect(cb3).toHaveBeenCalledTimes(0); expect(res.tests[FieldNames.F1].testCount).toBe(1); expect(res.tests[FieldNames.F2].testCount).toBe(0); expect(res.tests[FieldNames.F3].testCount).toBe(0); expect(res.isValid()).toBe(false); expect(res.hasErrors(FieldNames.F1)).toBe(true); expect(res.hasErrors(FieldNames.F2)).toBe(false); expect(res.hasErrors(FieldNames.F3)).toBe(false); expect(suite.get()).toMatchSnapshot(); }); }); describe('with skip', () => { it('should skip tests for the specified field only', () => { const cb1 = vi.fn(() => false); const cb2 = vi.fn(() => false); const cb3 = vi.fn(() => false); const suite = vest.create(() => { vest.mode(vest.Modes.ALL); vest.group(() => { vest.skip(FieldNames.F1); vest.test(FieldNames.F1, cb1); vest.test(FieldNames.F2, cb2); vest.test(FieldNames.F3, cb3); }); }); const res = suite.run(); expect(cb1).toHaveBeenCalledTimes(0); expect(cb2).toHaveBeenCalledTimes(1); expect(cb3).toHaveBeenCalledTimes(1); expect(res.tests[FieldNames.F1].testCount).toBe(0); expect(res.tests[FieldNames.F2].testCount).toBe(1); expect(res.tests[FieldNames.F3].testCount).toBe(1); expect(res.isValid()).toBe(false); expect(res.hasErrors(FieldNames.F1)).toBe(false); expect(res.hasErrors(FieldNames.F2)).toBe(true); expect(res.hasErrors(FieldNames.F3)).toBe(true); expect(suite.get()).toMatchSnapshot(); }); }); describe('with skip(true)', () => { it('should skip all tests inside the unnamed group', () => { const cb1 = vi.fn(() => false); const cb2 = vi.fn(() => false); const cb3 = vi.fn(() => false); const suite = vest.create(() => { vest.mode(vest.Modes.ALL); vest.group(() => { vest.skip(true); vest.test(FieldNames.F1, cb1); vest.test(FieldNames.F2, cb2); vest.test(FieldNames.F3, cb3); }); }); const res = suite.run(); expect(cb1).toHaveBeenCalledTimes(0); expect(cb2).toHaveBeenCalledTimes(0); expect(cb3).toHaveBeenCalledTimes(0); expect(res.tests[FieldNames.F1].testCount).toBe(0); expect(res.tests[FieldNames.F2].testCount).toBe(0); expect(res.tests[FieldNames.F3].testCount).toBe(0); expect(res.isValid()).toBe(false); expect(res.hasErrors(FieldNames.F1)).toBe(false); expect(res.hasErrors(FieldNames.F2)).toBe(false); expect(res.hasErrors(FieldNames.F3)).toBe(false); expect(suite.get()).toMatchSnapshot(); }); }); }); describe('pending count within group', () => { it('should count pending tests within the group', () => { const suite = vest.create(() => { vest.test(FieldNames.F1, () => {}); vest.group(GroupNames.G1, () => { vest.test(FieldNames.F1, async () => {}); vest.test(FieldNames.F2, async () => {}); vest.test(FieldNames.F2, async () => {}); vest.test(FieldNames.F3, () => {}); }); }); const res = suite.run(); expect(res.tests[FieldNames.F1].pendingCount).toBe(1); expect(res.tests[FieldNames.F2].pendingCount).toBe(2); expect(res.tests[FieldNames.F3].pendingCount).toBe(0); expect(res.groups[GroupNames.G1][FieldNames.F1].pendingCount).toBe(1); expect(res.groups[GroupNames.G1][FieldNames.F2].pendingCount).toBe(2); expect(res.groups[GroupNames.G1][FieldNames.F3].pendingCount).toBe(0); }); });