From c3e468bc73bfb566a078200ab455e66ca5985056 Mon Sep 17 00:00:00 2001 From: Daniel Capeletti Date: Fri, 22 Feb 2019 15:36:16 +0100 Subject: [PATCH] Add rendering utils --- app/utils/__tests__/rendering.spec.js | 164 ++++++++++++++++++++++++++ app/utils/rendering.js | 32 +++++ app/utils/testUtils.js | 3 + 3 files changed, 199 insertions(+) create mode 100644 app/utils/__tests__/rendering.spec.js create mode 100644 app/utils/rendering.js create mode 100644 app/utils/testUtils.js diff --git a/app/utils/__tests__/rendering.spec.js b/app/utils/__tests__/rendering.spec.js new file mode 100644 index 0000000..26fcbce --- /dev/null +++ b/app/utils/__tests__/rendering.spec.js @@ -0,0 +1,164 @@ +import { spy } from 'sinon'; +import { expect } from 'chai'; +import { List } from 'immutable'; +import { always } from 'ramda'; + +import { intlMock } from '../testUtils'; +import { + renderWhen, + renderWhenNotNil, + renderWhenTrue, + getFormFieldHelperText, + renderWhenTrueOtherwise, +} from '../rendering'; + +describe('renderWhenNotNil: Function', () => { + it('should call function argument, if condition argument is not null', () => { + const condition = {}; + const fn = spy(); + renderWhenNotNil(fn)(condition); + expect(fn).to.have.been.calledOnce; + }); + + it('should not return null, if condition argument is not null', () => { + const condition = {}; + const fn = spy(); + expect(renderWhenNotNil(fn)(condition)).to.not.be.null; + }); + + it('should not call function argument, if condition argument is null', () => { + const condition = null; + const fn = spy(); + renderWhenNotNil(fn)(condition); + expect(fn).to.have.not.been.called; + }); + + it('should return null if condition argument is null', () => { + const condition = null; + const fn = spy(); + expect(renderWhenNotNil(fn)(condition)).to.be.null; + }); +}); + + +describe('renderWhenTrue: Function', () => { + it('should call function argument, if condition argument is true', () => { + const condition = true; + const fn = spy(); + renderWhenTrue(fn)(condition); + expect(fn).to.have.been.calledOnce; + }); + + it('should not return null, if condition argument is true', () => { + const condition = true; + const fn = spy(); + expect(renderWhenTrue(fn)(condition)).to.not.be.null; + }); + + it('should not call function argument, if condition argument is false', () => { + const condition = false; + const fn = spy(); + renderWhenTrue(fn)(condition); + expect(fn).to.have.not.been.called; + }); + + it('should return null if condition argument is false', () => { + const condition = false; + const fn = spy(); + expect(renderWhenTrue(fn)(condition)).to.be.null; + }); +}); + +describe('renderWhen: Function', () => { + it('should call function argument, if condition argument is true', () => { + const condition = always(true); + const fn = spy(); + renderWhen(condition, fn)(); + expect(fn).to.have.been.calledOnce; + }); + + it('should not return null, if condition argument is true', () => { + const condition = always(true); + const fn = spy(); + expect(renderWhen(condition, fn)()).to.not.be.null; + }); + + it('should not call function argument, if condition argument is false', () => { + const condition = always(false); + const fn = spy(); + renderWhen(condition, fn)(); + expect(fn).to.have.not.been.called; + }); + + it('should return null if condition argument is false', () => { + const condition = always(false); + const fn = spy(); + expect(renderWhen(condition, fn)()).to.be.null; + }); +}); + +describe('renderWhenTrueOtherwise: Function', () => { + it('should call first function argument, if condition argument is true', () => { + const condition = true; + const fn1 = spy(); + const fn2 = spy(); + renderWhenTrueOtherwise(fn1, fn2)(condition); + expect(fn1).to.have.been.calledOnce; + expect(fn2).to.not.have.been.called; + }); + + it('should call second function argument, if condition argument is false', () => { + const condition = false; + const fn1 = spy(); + const fn2 = spy(); + renderWhenTrueOtherwise(fn1, fn2)(condition); + expect(fn1).to.not.have.been.called; + expect(fn2).to.have.been.calledOnce; + }); +}); + +describe('getFormFieldHelperText', () => { + const messages = { + message1: { id: 'test.message1', defaultMessage: 'Test error 1' }, + message2: { id: 'test.message2', defaultMessage: 'Test error 2' }, + }; + + it('should return proper error message when error is a string', () => { + const meta = { + error: 'message1', + invalid: true, + touched: true, + }; + + expect(getFormFieldHelperText(intlMock(), messages, meta)).to.equal('test.message1 / Test error 1 / {}'); + }); + + it('should return first error message when error is a List', () => { + const meta = { + error: List(['message2', 'message1']), + invalid: true, + touched: true, + }; + + expect(getFormFieldHelperText(intlMock(), messages, meta)).to.equal('test.message2 / Test error 2 / {}'); + }); + + it('should return empty string when field hasn\'t been touched', () => { + const meta = { + error: 'message1', + invalid: true, + touched: false, + }; + + expect(getFormFieldHelperText(intlMock(), messages, meta)).to.equal(''); + }); + + it('should return empty string when field isn\'t invalid', () => { + const meta = { + invalid: false, + touched: true, + }; + + expect(getFormFieldHelperText(intlMock(), messages, meta)).to.equal(''); + }); +}); diff --git a/app/utils/rendering.js b/app/utils/rendering.js new file mode 100644 index 0000000..128908a --- /dev/null +++ b/app/utils/rendering.js @@ -0,0 +1,32 @@ +import reportError from 'report-error'; +import { ifElse, isNil, always, when, is, complement, equals, pipe } from 'ramda'; +import { List } from 'immutable'; + + +export const renderWhen = (pred, fn) => ifElse(pred, fn, always(null)); + +export const renderWhenNotNil = (fn) => renderWhen(complement(isNil), fn); + +export const renderWhenTrue = (fn) => renderWhen(equals(true), fn); + +export const renderWhenTrueOtherwise = (fn, otherwise) => ifElse(equals(true), fn, otherwise); + +export const getFormFieldHelperText = (intl, messages, { error, invalid, touched }) => { + if (invalid && touched) { + try { + return intl.formatMessage(messages[pipe( + when( + is(List), + (errors) => errors.first() + ), + when( + is(Array), + ([firstError]) => firstError + ), + )(error)]); + } catch (e) { + reportError(e); + } + } + return ''; +}; diff --git a/app/utils/testUtils.js b/app/utils/testUtils.js new file mode 100644 index 0000000..d79c66a --- /dev/null +++ b/app/utils/testUtils.js @@ -0,0 +1,3 @@ +export const intlMock = () => ({ + formatMessage: ({ id, defaultMessage, values = {} }) => `${id} / ${defaultMessage} / ${JSON.stringify(values)}`, +});