From 3b91d44e18f91230310314dc91ffc28a67fcd0a4 Mon Sep 17 00:00:00 2001 From: Evyatar Date: Wed, 4 Sep 2024 20:53:00 +0300 Subject: [PATCH] minor(vest): Add subscribe to specific events (#1154) --- packages/vest/src/core/VestBus/BusEvents.ts | 21 ++++++----- packages/vest/src/core/VestBus/VestBus.ts | 36 +++++++++++-------- packages/vest/src/core/test/test.ts | 3 +- .../src/hooks/optional/omitOptionalFields.ts | 3 +- packages/vest/src/suite/SuiteTypes.ts | 3 +- .../src/suite/__tests__/subscribe.test.ts | 28 ++++++++++++++- packages/vest/src/suite/createSuite.ts | 11 +++--- 7 files changed, 68 insertions(+), 37 deletions(-) diff --git a/packages/vest/src/core/VestBus/BusEvents.ts b/packages/vest/src/core/VestBus/BusEvents.ts index 8ef0083ab..e708043fe 100644 --- a/packages/vest/src/core/VestBus/BusEvents.ts +++ b/packages/vest/src/core/VestBus/BusEvents.ts @@ -1,11 +1,10 @@ -export enum Events { - TEST_RUN_STARTED = 'test_run_started', - TEST_COMPLETED = 'test_completed', - ALL_RUNNING_TESTS_FINISHED = 'all_running_tests_finished', - REMOVE_FIELD = 'remove_field', - RESET_FIELD = 'reset_field', - RESET_SUITE = 'reset_suite', - SUITE_RUN_STARTED = 'suite_run_started', - SUITE_CALLBACK_RUN_FINISHED = 'SUITE_CALLBACK_RUN_FINISHED', - DONE_TEST_OMISSION_PASS = 'DONE_TEST_OMISSION_PASS', -} +export type Events = + | 'TEST_RUN_STARTED' + | 'TEST_COMPLETED' + | 'ALL_RUNNING_TESTS_FINISHED' + | 'REMOVE_FIELD' + | 'RESET_FIELD' + | 'RESET_SUITE' + | 'SUITE_RUN_STARTED' + | 'SUITE_CALLBACK_RUN_FINISHED' + | 'DONE_TEST_OMISSION_PASS'; diff --git a/packages/vest/src/core/VestBus/VestBus.ts b/packages/vest/src/core/VestBus/VestBus.ts index ae106fb97..0714264b9 100644 --- a/packages/vest/src/core/VestBus/VestBus.ts +++ b/packages/vest/src/core/VestBus/VestBus.ts @@ -20,8 +20,8 @@ import { useRunDoneCallbacks, useRunFieldCallbacks } from 'runCallbacks'; export function useInitVestBus() { const VestBus = Bus.useBus(); - on(Events.TEST_COMPLETED, () => {}); - // on(Events.TEST_RUN_STARTED, () => {}); + on('TEST_COMPLETED', () => {}); + // on("TEST_RUN_STARTED", () => {}); VestBus.on(RuntimeEvents.ISOLATE_PENDING, (isolate: TIsolate) => { if (VestTest.is(isolate)) { @@ -33,7 +33,7 @@ export function useInitVestBus() { VestBus.on(RuntimeEvents.ISOLATE_DONE, (isolate: TIsolate) => { if (VestTest.is(isolate)) { - VestBus.emit(Events.TEST_COMPLETED, isolate); + VestBus.emit('TEST_COMPLETED', isolate); } VestIsolate.setDone(isolate); @@ -50,16 +50,16 @@ export function useInitVestBus() { if (!SuiteWalker.useHasPending()) { // When no more async tests are running, emit the done event - VestBus.emit(Events.ALL_RUNNING_TESTS_FINISHED); + VestBus.emit('ALL_RUNNING_TESTS_FINISHED'); } }); - on(Events.DONE_TEST_OMISSION_PASS, () => { + on('DONE_TEST_OMISSION_PASS', () => { /* We NEED to refresh the cache here. Don't ask */ }); // Called when all the tests, including async, are done running - VestBus.on(Events.ALL_RUNNING_TESTS_FINISHED, () => { + VestBus.on('ALL_RUNNING_TESTS_FINISHED', () => { // Small optimization. We don't need to run this if there are no async tests // The reason is that we run this function immediately after the suite callback // is run, so if the suite is only comprised of sync tests, we don't need to @@ -70,28 +70,28 @@ export function useInitVestBus() { useRunDoneCallbacks(); }); - on(Events.RESET_FIELD, (fieldName: TFieldName) => { + on('RESET_FIELD', (fieldName: TFieldName) => { TestWalker.resetField(fieldName); }); - on(Events.SUITE_RUN_STARTED, () => { + on('SUITE_RUN_STARTED', () => { useResetCallbacks(); }); - on(Events.SUITE_CALLBACK_RUN_FINISHED, () => { + on('SUITE_CALLBACK_RUN_FINISHED', () => { if (!SuiteWalker.useHasPending()) { // When no more async tests are running, emit the done event - VestBus.emit(Events.ALL_RUNNING_TESTS_FINISHED); + VestBus.emit('ALL_RUNNING_TESTS_FINISHED'); } useOmitOptionalFields(); }); - on(Events.REMOVE_FIELD, (fieldName: TFieldName) => { + on('REMOVE_FIELD', (fieldName: TFieldName) => { TestWalker.removeTestByFieldName(fieldName); }); - on(Events.RESET_SUITE, () => { + on('RESET_SUITE', () => { useResetSuite(); }); @@ -99,8 +99,11 @@ export function useInitVestBus() { subscribe, }; - function subscribe(cb: CB) { - return VestBus.on('*', () => { + function subscribe(event: Events, cb: CB): CB; + function subscribe(cb: CB): CB; + function subscribe(...args: [event: Events, cb: CB] | [cb: CB]): CB { + const [cb, event] = args.reverse() as [CB, Events]; + return VestBus.on(event ?? '*', () => { cb(); }).off; } @@ -116,3 +119,8 @@ export function useInitVestBus() { } type VestEvents = Events | ValueOf | '*'; + +export type Subscribe = { + (event: Events, cb: CB): CB; + (cb: CB): CB; +}; diff --git a/packages/vest/src/core/test/test.ts b/packages/vest/src/core/test/test.ts index ec3e61a34..e8a242cfe 100644 --- a/packages/vest/src/core/test/test.ts +++ b/packages/vest/src/core/test/test.ts @@ -1,7 +1,6 @@ import { assign, invariant, isFunction, isStringValue, text } from 'vest-utils'; import { Bus, IsolateKey } from 'vestjs-runtime'; -import { Events } from 'BusEvents'; import { ErrorStrings } from 'ErrorStrings'; import { IsolateTest, TIsolateTest } from 'IsolateTest'; import { useGroupName } from 'SuiteContext'; @@ -47,7 +46,7 @@ function vestTest( const testObjectInput = { fieldName, groupName, message, testFn }; // This invalidates the suite cache. - Bus.useEmit(Events.TEST_RUN_STARTED); + Bus.useEmit('TEST_RUN_STARTED'); return IsolateTest(useAttemptRunTest, testObjectInput, key); } diff --git a/packages/vest/src/hooks/optional/omitOptionalFields.ts b/packages/vest/src/hooks/optional/omitOptionalFields.ts index 88df38474..2d832a8ab 100644 --- a/packages/vest/src/hooks/optional/omitOptionalFields.ts +++ b/packages/vest/src/hooks/optional/omitOptionalFields.ts @@ -1,7 +1,6 @@ import { isEmpty, optionalFunctionValue } from 'vest-utils'; import { Bus, VestRuntime } from 'vestjs-runtime'; -import { Events } from 'BusEvents'; import { SuiteOptionalFields, TIsolateSuite } from 'IsolateSuite'; import { TIsolateTest } from 'IsolateTest'; import { TestWalker } from 'TestWalker'; @@ -44,7 +43,7 @@ export function useOmitOptionalFields(): void { } }); - Bus.useEmit(Events.DONE_TEST_OMISSION_PASS); + Bus.useEmit('DONE_TEST_OMISSION_PASS'); function verifyAndOmit(testObject: TIsolateTest) { const { fieldName } = VestTest.getData(testObject); diff --git a/packages/vest/src/suite/SuiteTypes.ts b/packages/vest/src/suite/SuiteTypes.ts index b9ae2eddc..efd362cf4 100644 --- a/packages/vest/src/suite/SuiteTypes.ts +++ b/packages/vest/src/suite/SuiteTypes.ts @@ -7,6 +7,7 @@ import { TFieldName, TGroupName, } from 'SuiteResultTypes'; +import { Subscribe } from 'VestBus'; import { StaticSuiteRunResult } from 'createSuite'; import { TTypedMethods } from 'getTypedMethods'; import { SuiteSelectors } from 'suiteSelectors'; @@ -29,6 +30,6 @@ export type SuiteMethods< remove: CB; resetField: CB; runStatic: CB, Parameters>; - subscribe: (cb: CB) => CB; + subscribe: Subscribe; } & TTypedMethods & SuiteSelectors; diff --git a/packages/vest/src/suite/__tests__/subscribe.test.ts b/packages/vest/src/suite/__tests__/subscribe.test.ts index 6bcd52e50..78a707ce4 100644 --- a/packages/vest/src/suite/__tests__/subscribe.test.ts +++ b/packages/vest/src/suite/__tests__/subscribe.test.ts @@ -1,8 +1,8 @@ -import { SuiteSerializer } from 'SuiteSerializer'; import { enforce } from 'n4s'; import { describe, it, expect, vi } from 'vitest'; import wait from 'wait'; +import { SuiteSerializer } from 'SuiteSerializer'; import * as vest from 'vest'; describe('suite.subscribe', () => { @@ -52,6 +52,32 @@ describe('suite.subscribe', () => { expect(cb.mock.calls.length).toBeGreaterThan(callCount); }); + describe('Subscribe with event name', () => { + it('Should only call the callback on the specified event', () => { + const cbAllDone = vi.fn(); + const testDone = vi.fn(); + const testStarted = vi.fn(); + const suiteStart = vi.fn(); + + const suite = vest.create('suite', () => { + vest.test('field1', () => false); + vest.test('field2', () => true); + vest.test('field3', () => false); + }); + + suite.subscribe('ALL_RUNNING_TESTS_FINISHED', cbAllDone); + suite.subscribe('TEST_COMPLETED', testDone); + suite.subscribe('TEST_RUN_STARTED', testStarted); + suite.subscribe('SUITE_RUN_STARTED', suiteStart); + + suite(); + expect(cbAllDone).toHaveBeenCalledTimes(1); + expect(testDone).toHaveBeenCalledTimes(3); + expect(testStarted).toHaveBeenCalledTimes(3); + expect(suiteStart).toHaveBeenCalledTimes(1); + }); + }); + describe('unsubscribe', () => { it('Should unsubscribe future events', () => { const cb = vi.fn(); diff --git a/packages/vest/src/suite/createSuite.ts b/packages/vest/src/suite/createSuite.ts index 06412167e..06b381b1f 100644 --- a/packages/vest/src/suite/createSuite.ts +++ b/packages/vest/src/suite/createSuite.ts @@ -3,7 +3,6 @@ import { Bus, VestRuntime } from 'vestjs-runtime'; import { TTypedMethods, getTypedMethods } from './getTypedMethods'; -import { Events } from 'BusEvents'; import { IsolateSuite, TIsolateSuite } from 'IsolateSuite'; import { useCreateVestState, useLoadSuite } from 'Runtime'; import { SuiteContext } from 'SuiteContext'; @@ -55,7 +54,7 @@ function createSuite< suiteParams: args, }, () => { - Bus.useEmit(Events.SUITE_RUN_STARTED); + Bus.useEmit('SUITE_RUN_STARTED'); return IsolateSuite( useRunSuiteCallback(suiteCallback, ...args), @@ -82,9 +81,9 @@ function createSuite< () => VestRuntime.useAvailableRoot() as TIsolateSuite, ), get: VestRuntime.persist(useCreateSuiteResult), - remove: Bus.usePrepareEmitter(Events.REMOVE_FIELD), - reset: Bus.usePrepareEmitter(Events.RESET_SUITE), - resetField: Bus.usePrepareEmitter(Events.RESET_FIELD), + remove: Bus.usePrepareEmitter('REMOVE_FIELD'), + reset: Bus.usePrepareEmitter('RESET_SUITE'), + resetField: Bus.usePrepareEmitter('RESET_FIELD'), resume: VestRuntime.persist(useLoadSuite), runStatic: (...args: Parameters): StaticSuiteRunResult => mountedStatic(...args) as StaticSuiteRunResult, @@ -105,7 +104,7 @@ function useRunSuiteCallback< return () => { suiteCallback(...args); - emit(Events.SUITE_CALLBACK_RUN_FINISHED); + emit('SUITE_CALLBACK_RUN_FINISHED'); return useSuiteRunResult(); }; }