Skip to content

Commit

Permalink
minor(vest): Add subscribe to specific events
Browse files Browse the repository at this point in the history
  • Loading branch information
ealush committed Sep 3, 2024
1 parent a48e91b commit d462791
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 37 deletions.
21 changes: 10 additions & 11 deletions packages/vest/src/core/VestBus/BusEvents.ts
Original file line number Diff line number Diff line change
@@ -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';
36 changes: 22 additions & 14 deletions packages/vest/src/core/VestBus/VestBus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand All @@ -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);
Expand All @@ -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
Expand All @@ -70,37 +70,40 @@ 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();
});

return {
subscribe,
};

function subscribe(cb: CB) {
return VestBus.on('*', () => {
function subscribe(event: Events, cb: CB): CB<void>;
function subscribe(cb: CB): CB<void>;
function subscribe(...args: [event: Events, cb: CB] | [cb: CB]): CB<void> {
const [cb, event] = args.reverse() as [CB, Events];
return VestBus.on(event ?? '*', () => {
cb();
}).off;
}
Expand All @@ -116,3 +119,8 @@ export function useInitVestBus() {
}

type VestEvents = Events | ValueOf<typeof RuntimeEvents> | '*';

export type Subscribe = {
(event: Events, cb: CB): CB<void>;
(cb: CB): CB<void>;
};
3 changes: 1 addition & 2 deletions packages/vest/src/core/test/test.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -47,7 +46,7 @@ function vestTest<F extends TFieldName>(
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);
}
Expand Down
3 changes: 1 addition & 2 deletions packages/vest/src/hooks/optional/omitOptionalFields.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion packages/vest/src/suite/SuiteTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -29,6 +30,6 @@ export type SuiteMethods<
remove: CB<void, [fieldName: F]>;
resetField: CB<void, [fieldName: F]>;
runStatic: CB<StaticSuiteRunResult<F, G>, Parameters<T>>;
subscribe: (cb: CB) => CB<void>;
subscribe: Subscribe;
} & TTypedMethods<F, G> &
SuiteSelectors<F, G>;
28 changes: 27 additions & 1 deletion packages/vest/src/suite/__tests__/subscribe.test.ts
Original file line number Diff line number Diff line change
@@ -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', () => {
Expand Down Expand Up @@ -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();
Expand Down
11 changes: 5 additions & 6 deletions packages/vest/src/suite/createSuite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -55,7 +54,7 @@ function createSuite<
suiteParams: args,
},
() => {
Bus.useEmit(Events.SUITE_RUN_STARTED);
Bus.useEmit('SUITE_RUN_STARTED');

return IsolateSuite(
useRunSuiteCallback<T, F, G>(suiteCallback, ...args),
Expand All @@ -82,9 +81,9 @@ function createSuite<
() => VestRuntime.useAvailableRoot() as TIsolateSuite,
),
get: VestRuntime.persist(useCreateSuiteResult),
remove: Bus.usePrepareEmitter<string>(Events.REMOVE_FIELD),
reset: Bus.usePrepareEmitter(Events.RESET_SUITE),
resetField: Bus.usePrepareEmitter<string>(Events.RESET_FIELD),
remove: Bus.usePrepareEmitter<string>('REMOVE_FIELD'),
reset: Bus.usePrepareEmitter('RESET_SUITE'),
resetField: Bus.usePrepareEmitter<string>('RESET_FIELD'),
resume: VestRuntime.persist(useLoadSuite),
runStatic: (...args: Parameters<T>): StaticSuiteRunResult<F, G> =>
mountedStatic(...args) as StaticSuiteRunResult<F, G>,
Expand All @@ -105,7 +104,7 @@ function useRunSuiteCallback<

return () => {
suiteCallback(...args);
emit(Events.SUITE_CALLBACK_RUN_FINISHED);
emit('SUITE_CALLBACK_RUN_FINISHED');
return useSuiteRunResult<F, G>();
};
}
Expand Down

0 comments on commit d462791

Please sign in to comment.