diff --git a/packages/vest/src/core/state/__tests__/state.test.js b/packages/vest/src/core/state/__tests__/state.test.js index 28c5e7aea..ce512009a 100644 --- a/packages/vest/src/core/state/__tests__/state.test.js +++ b/packages/vest/src/core/state/__tests__/state.test.js @@ -88,6 +88,27 @@ describe('state', () => { }); }); }); + + describe('onStateChange', () => { + const onStateChange = jest.fn(); + beforeEach(() => { + + stateRef = state.createRef({ + keyWithObject: state.registerHandler(() => ({ a: true })), + }, onStateChange); + }); + + it('should run callback on state change', () => { + expect(onStateChange).toHaveBeenCalledTimes(1); + stateRef.set('key', 'value'); + expect(onStateChange).toHaveBeenCalledTimes(2); + }); + + it('should run callback with updated state value', () => { + stateRef.set('key', 'value'); + expect(onStateChange).toHaveBeenCalledWith(stateRef.current(),'key', 'value'); + }); + }) }); const initialState = { diff --git a/packages/vest/src/core/state/state.js b/packages/vest/src/core/state/state.js index a0b98c610..6bd62596f 100644 --- a/packages/vest/src/core/state/state.js +++ b/packages/vest/src/core/state/state.js @@ -38,7 +38,7 @@ export default (function createState() { return use; } - function createRef(handlers) { + function createRef(handlers, onStateChange) { let state = {}; const registeredHandlers = []; @@ -48,6 +48,9 @@ export default (function createState() { function set(key, value) { state[key] = value; + if (isFunction(onStateChange)) { + onStateChange(state, key, value); + } } function reset() { diff --git a/packages/vest/src/core/suite/__tests__/__snapshots__/subscribe.test.js.snap b/packages/vest/src/core/suite/__tests__/__snapshots__/subscribe.test.js.snap new file mode 100644 index 000000000..49006ad6b --- /dev/null +++ b/packages/vest/src/core/suite/__tests__/__snapshots__/subscribe.test.js.snap @@ -0,0 +1,24 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`suite.subscribe Should call handler on suite subscription initialization 1`] = ` +Array [ + Object { + "suiteState": Object { + "usePending": Object { + "lagging": Array [], + "pending": Array [], + }, + "useSuiteId": Object { + "id": "1", + "name": undefined, + }, + "useTestCallbacks": Object { + "doneCallbacks": Array [], + "fieldCallbacks": Array [], + }, + "useTestObjects": Array [], + }, + "type": "suiteSubscribeInit", + }, +] +`; diff --git a/packages/vest/src/core/suite/__tests__/subscribe.test.js b/packages/vest/src/core/suite/__tests__/subscribe.test.js new file mode 100644 index 000000000..d10455888 --- /dev/null +++ b/packages/vest/src/core/suite/__tests__/subscribe.test.js @@ -0,0 +1,31 @@ +import vest from 'vest'; + +describe('suite.subscribe', () => { + let suite; + let handler; + beforeEach(() => { + handler = jest.fn(); + suite = vest.create(() => { + + }); + + }); + + it('Should call handler on suite subscription initialization', () => { + + suite(); + + expect(handler).toHaveBeenCalledTimes(0); + suite.subscribe(handler); + expect(handler).toHaveBeenCalledTimes(1); + }); + + it('Should call handler on suite subscription initialization', () => { + + suite(); + + suite.subscribe(handler); + expect(handler.mock.calls[0]).toMatchSnapshot(); + }); + +}); diff --git a/packages/vest/src/core/suite/createSuite.js b/packages/vest/src/core/suite/createSuite.js index c130ee6aa..028040d98 100644 --- a/packages/vest/src/core/suite/createSuite.js +++ b/packages/vest/src/core/suite/createSuite.js @@ -26,11 +26,19 @@ const createSuite = withArgs(args => { ); } + const handlers = []; const stateRef = state.createRef({ usePending, useSuiteId: [useSuiteId, [genId(), name]], useTestCallbacks, useTestObjects, + }, (state, key, value) => { + handlers.forEach(fn => fn({ + key, + suiteState: state, + type: 'suiteStateUpdate', + value + })) }); /* @@ -67,6 +75,18 @@ const createSuite = withArgs(args => { } }); }); + + suite.subscribe = function(handler){ + if (!isFunction(handler)) return; + + handlers.push(handler); + + handler({ + type: 'suiteSubscribeInit', + suiteState: stateRef.current() + }); + } + return suite; }); diff --git a/packages/vest/src/typings/vest.d.ts b/packages/vest/src/typings/vest.d.ts index e3620c03c..043ceec4e 100644 --- a/packages/vest/src/typings/vest.d.ts +++ b/packages/vest/src/typings/vest.d.ts @@ -162,11 +162,21 @@ interface IOnly { */ group(groupName?: ExclusionArg): void; } + +interface ISubscribePayload { + type: string; + suiteState: Record; + key?: string; + value?: any; +} + interface ICreateResult { (...args: any[]): IVestResult; get: () => DraftResult; reset: () => void; remove: (fieldName: string) => void; + + subscribe: (payload: ISubscribePayload) => void; } declare namespace vest {