From 70cd0eef8c98dfb286bc49e82ced9f6395135e7d Mon Sep 17 00:00:00 2001 From: Pearce <32177944+Pearce-Ropion@users.noreply.github.com> Date: Thu, 26 Nov 2020 06:20:25 -0800 Subject: [PATCH] fix(events): allow multiple event handlers to execute (#4612) --- .../src/lib/__tests__/registry.spec.js | 78 ++++++++++++++++++- packages/netlify-cms-core/src/lib/registry.js | 9 ++- 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/packages/netlify-cms-core/src/lib/__tests__/registry.spec.js b/packages/netlify-cms-core/src/lib/__tests__/registry.spec.js index 20473e50..633025b9 100644 --- a/packages/netlify-cms-core/src/lib/__tests__/registry.spec.js +++ b/packages/netlify-cms-core/src/lib/__tests__/registry.spec.js @@ -1,3 +1,5 @@ +import { fromJS } from 'immutable'; + jest.spyOn(console, 'error').mockImplementation(() => {}); describe('registry', () => { @@ -145,12 +147,86 @@ describe('registry', () => { registerEventListener({ name, handler }, options); - const data = { entry: {} }; + const data = { entry: fromJS({ data: {} }) }; await invokeEvent({ name, data }); expect(handler).toHaveBeenCalledTimes(1); expect(handler).toHaveBeenCalledWith(data, options); }); + + it(`should invoke multiple handlers on '${name}`, async () => { + const { registerEventListener, invokeEvent } = require('../registry'); + + const options1 = { hello: 'test1' }; + const options2 = { hello: 'test2' }; + const handler = jest.fn(({ entry }) => entry.get('data')); + + registerEventListener({ name, handler }, options1); + registerEventListener({ name, handler }, options2); + + const data = { entry: fromJS({ data: {} }) }; + await invokeEvent({ name, data }); + + expect(handler).toHaveBeenCalledTimes(2); + expect(handler).toHaveBeenLastCalledWith(data, options2); + }); + }); + + it(`should return an updated entry's DataMap`, async () => { + const { registerEventListener, invokeEvent } = require('../registry'); + + const event = 'preSave'; + const options = { hello: 'world' }; + const handler1 = jest.fn(({ entry }) => { + const data = entry.get('data'); + return data.set('a', 'test1'); + }); + const handler2 = jest.fn(({ entry }) => { + const data = entry.get('data'); + return data.set('c', 'test2'); + }); + + registerEventListener({ name: event, handler: handler1 }, options); + registerEventListener({ name: event, handler: handler2 }, options); + + const data = { + entry: fromJS({ data: { a: 'foo', b: 'bar' } }), + }; + + const dataAfterFirstHandlerExecution = { + entry: fromJS({ data: { a: 'test1', b: 'bar' } }), + }; + const dataAfterSecondHandlerExecution = { + entry: fromJS({ data: { a: 'test1', b: 'bar', c: 'test2' } }), + }; + + const result = await invokeEvent({ name: event, data }); + + expect(handler1).toHaveBeenCalledWith(data, options); + expect(handler2).toHaveBeenCalledWith(dataAfterFirstHandlerExecution, options); + + expect(result).toEqual(dataAfterSecondHandlerExecution.entry.get('data')); + }); + + it('should allow multiple events to not return a value', async () => { + const { registerEventListener, invokeEvent } = require('../registry'); + + const event = 'prePublish'; + const options = { hello: 'world' }; + const handler1 = jest.fn(); + const handler2 = jest.fn(); + + registerEventListener({ name: event, handler: handler1 }, options); + registerEventListener({ name: event, handler: handler2 }, options); + + const data = { + entry: fromJS({ data: { a: 'foo', b: 'bar' } }), + }; + const result = await invokeEvent({ name: event, data }); + + expect(handler1).toHaveBeenCalledWith(data, options); + expect(handler2).toHaveBeenCalledWith(data, options); + expect(result).toEqual(data.entry.get('data')); }); }); }); diff --git a/packages/netlify-cms-core/src/lib/registry.js b/packages/netlify-cms-core/src/lib/registry.js index f561cf7c..b587ede1 100644 --- a/packages/netlify-cms-core/src/lib/registry.js +++ b/packages/netlify-cms-core/src/lib/registry.js @@ -226,13 +226,20 @@ export function registerEventListener({ name, handler }, options = {}) { export async function invokeEvent({ name, data }) { validateEventName(name); const handlers = registry.eventHandlers[name]; + + let _data = { ...data }; for (const { handler, options } of handlers) { try { - return await handler(data, options); + const result = await handler(_data, options); + if (result !== undefined) { + const entry = _data.entry.set('data', result); + _data = { ...data, entry }; + } } catch (e) { console.warn(`Failed running handler for event ${name} with message: ${e.message}`); } } + return _data.entry.get('data'); } export function removeEventListener({ name, handler }) {