From 62341ffe569e9ab8ce8b731dcd72ad6f7342db33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Wed, 30 Jan 2019 10:31:38 +0100 Subject: [PATCH] Added actionCreatorFactory and tests --- .../core/redux/actionCreatorFactory.test.ts | 53 +++++++++++++++++++ public/app/core/redux/actionCreatorFactory.ts | 33 ++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 public/app/core/redux/actionCreatorFactory.test.ts create mode 100644 public/app/core/redux/actionCreatorFactory.ts diff --git a/public/app/core/redux/actionCreatorFactory.test.ts b/public/app/core/redux/actionCreatorFactory.test.ts new file mode 100644 index 00000000000..f79c1ebe0dc --- /dev/null +++ b/public/app/core/redux/actionCreatorFactory.test.ts @@ -0,0 +1,53 @@ +import { actionCreatorFactory, resetAllActionCreatorTypes } from './actionCreatorFactory'; + +interface Dummy { + n: number; + s: string; + o: { + n: number; + s: string; + b: boolean; + }; + b: boolean; +} + +const setup = payload => { + resetAllActionCreatorTypes(); + const actionCreator = actionCreatorFactory('dummy').create(); + const result = actionCreator(payload); + + return { + actionCreator, + result, + }; +}; + +describe('actionCreatorFactory', () => { + describe('when calling create', () => { + it('then it should create correct type string', () => { + const payload = { n: 1, b: true, s: 'dummy', o: { n: 1, b: true, s: 'dummy' } }; + const { actionCreator, result } = setup(payload); + + expect(actionCreator.type).toEqual('dummy'); + expect(result.type).toEqual('dummy'); + }); + + it('then it should create correct payload', () => { + const payload = { n: 1, b: true, s: 'dummy', o: { n: 1, b: true, s: 'dummy' } }; + const { result } = setup(payload); + + expect(result.payload).toEqual(payload); + }); + }); + + describe('when calling create with existing type', () => { + it('then it should throw error', () => { + const payload = { n: 1, b: true, s: 'dummy', o: { n: 1, b: true, s: 'dummy' } }; + setup(payload); + + expect(() => { + actionCreatorFactory('dummy').create(); + }).toThrow(); + }); + }); +}); diff --git a/public/app/core/redux/actionCreatorFactory.ts b/public/app/core/redux/actionCreatorFactory.ts new file mode 100644 index 00000000000..936440f735a --- /dev/null +++ b/public/app/core/redux/actionCreatorFactory.ts @@ -0,0 +1,33 @@ +import { Action } from 'redux'; + +const allActionCreators: string[] = []; + +export interface GrafanaAction extends Action { + readonly type: string; + readonly payload: Payload; +} + +export interface GrafanaActionCreator { + readonly type: string; + (payload: Payload): GrafanaAction; +} + +export interface ActionCreatorFactory { + create: () => GrafanaActionCreator; +} + +export const actionCreatorFactory = (type: string): ActionCreatorFactory => { + const create = (): GrafanaActionCreator => { + return Object.assign((payload: Payload): GrafanaAction => ({ type, payload }), { type }); + }; + + if (allActionCreators.some(t => type === type)) { + throw new Error(`There is already an actionCreator defined with the type ${type}`); + } + + allActionCreators.push(type); + + return { create }; +}; + +export const resetAllActionCreatorTypes = () => (allActionCreators.length = 0);