diff --git a/src/editors/containers/TextEditor/TextEditor.test.jsx b/src/editors/containers/TextEditor/TextEditor.test.jsx index c6fe51b8d..5b3e1fade 100644 --- a/src/editors/containers/TextEditor/TextEditor.test.jsx +++ b/src/editors/containers/TextEditor/TextEditor.test.jsx @@ -1,51 +1,91 @@ import React from 'react'; -import { render, screen } from '@testing-library/react'; -import TextEditor from './TextEditor'; -import EditorPageContext from '../EditorPageContext'; -import { ActionStates } from '../data/constants'; +import { shallow } from 'enzyme'; +import { TextEditor, mapStateToProps, mapDispatchToProps } from './TextEditor'; +import { actions, selectors } from '../../data/redux'; +import { RequestKeys } from '../../data/constants/requests'; +import { modalToggle } from './hooks'; // Per https://github.com/tinymce/tinymce-react/issues/91 React unit testing in JSDOM is not supported by tinymce. // Consequently, mock the Editor out. -const mockRole = 'Tiny-MCE-Mock'; jest.mock('@tinymce/tinymce-react', () => { const originalModule = jest.requireActual('@tinymce/tinymce-react'); return { __esModule: true, ...originalModule, - Editor: () =>
+ Editor: () => 'TiNYmCE EDitOR' , }; }); -test('Loading State:', () => { - const context = { - blockValue: null, - blockError: null, - blockLoading: ActionStates.IN_PROGRESS, - editorRef: null, +jest.mock('./hooks', () => ({ + editorConfig: jest.fn(args => ({ editorConfig: args })), + modalToggle: jest.fn(args => ({ modalToggle: args })), + nullMethod: jest.fn().mockName('nullMethod'), +})); + +jest.mock('../../data/redux', () => ({ + actions: { + app: { + initializeEditor: jest.fn().mockName('actions.app.initializeEditor'), + }, + }, + selectors: { + app: { + blockValue: jest.fn(state => ({ blockValue: state })), + }, + requests: { + isFailed: jest.fn((state, params) => ({ isFailed: { state, params } })), + isFinished: jest.fn((state, params) => ({ isFailed: { state, params } })), + }, + }, +})); + +describe('TextEditor', () => { + const props = { + setEditorRef: jest.fn().mockName('args.setEditorRef'), + // redux + blockValue: { data: 'eDiTablE Text' }, + blockFailed: false, + blockFinished: true, + initializeEditor: jest.fn().mockName('args.intializeEditor'), }; - render( - - - , - ); - expect(screen.queryByRole(mockRole)).not.toBeTruthy(); -}); -test('Loaded State-- No Error', () => { - const htmltext = 'Im baby palo santo ugh celiac fashion axe. La croix lo-fi venmo whatever. Beard man braid migas single-origin coffee forage ramps.'; - const context = { - blockValue: - { - data: - { data: { htmltext } }, - }, - blockError: null, - blockLoading: ActionStates.FINISHED, - }; - render( - - - , - ); - expect(screen.findByRole(mockRole)).toBeTruthy(); + describe('snapshots', () => { + modalToggle.mockReturnValue({ + isOpen: false, + openModal: jest.fn().mockName('modal.openModal'), + closeModal: jest.fn().mockName('modal.closeModal'), + }); + test('renders as expected with default behavior', () => { + expect(shallow()).toMatchSnapshot(); + }); + test('not yet loaded, Spinner appears', () => { + expect(shallow()).toMatchSnapshot(); + }); + test('block failed to load, Toast is shown', () => { + expect(shallow()).toMatchSnapshot(); + }); + }); + describe('mapStateToProps', () => { + const testState = { A: 'pple', B: 'anana', C: 'ucumber' }; + test('blockValue from app.blockValue', () => { + expect( + mapStateToProps(testState).blockValue, + ).toEqual(selectors.app.blockValue(testState)); + }); + test('blockFailed from requests.isFailed', () => { + expect( + mapStateToProps(testState).blockFailed, + ).toEqual(selectors.requests.isFailed(testState, { requestKey: RequestKeys.fetchBlock })); + }); + test('blockFinished from requests.isFinished', () => { + expect( + mapStateToProps(testState).blockFinished, + ).toEqual(selectors.requests.isFinished(testState, { requestKey: RequestKeys.fetchBlock })); + }); + }); + describe('mapDispatchToProps', () => { + test('initializeEditor from actions.app.initializeEditor', () => { + expect(mapDispatchToProps.initializeEditor).toEqual(actions.app.initializeEditor); + }); + }); }); diff --git a/src/editors/containers/TextEditor/__snapshots__/TextEditor.test.jsx.snap b/src/editors/containers/TextEditor/__snapshots__/TextEditor.test.jsx.snap new file mode 100644 index 000000000..f5fe54334 --- /dev/null +++ b/src/editors/containers/TextEditor/__snapshots__/TextEditor.test.jsx.snap @@ -0,0 +1,97 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`TextEditor snapshots block failed to load, Toast is shown 1`] = ` +
+ + + + + +
+`; + +exports[`TextEditor snapshots not yet loaded, Spinner appears 1`] = ` +
+ + + + +
+ +
+
+`; + +exports[`TextEditor snapshots renders as expected with default behavior 1`] = ` +
+ + + + + +
+`; diff --git a/src/editors/containers/TextEditor/hooks.test.jsx b/src/editors/containers/TextEditor/hooks.test.jsx new file mode 100644 index 000000000..762af3e2d --- /dev/null +++ b/src/editors/containers/TextEditor/hooks.test.jsx @@ -0,0 +1,110 @@ +import React from 'react'; +import * as module from './hooks'; + +jest.mock('react', () => { + const updateState = jest.fn(); + return { + updateState, + useState: jest.fn(val => ([{ state: val }, (newVal) => updateState({ val, newVal })])), + createRef: jest.fn(val => ({ ref: val })), + }; +}); + +describe('TextEditor hooks', () => { + describe('Editor Init hooks', () => { + describe('addImageUploadButton', () => { + const mockOpenModal = jest.fn(); + const mockAddbutton = jest.fn(val => ({ onAction: val })); + const editor = { + ui: { + registry: { + addButton: mockAddbutton, + }, + }, + }; + let output; + beforeEach(() => { + output = module.addImageUploadButton(mockOpenModal); + }); + test('It calls addButton in the editor, but openModal is not called', () => { + output(editor); + expect(mockAddbutton).toHaveBeenCalledWith('imageuploadbutton', { icon: 'image', onAction: mockOpenModal }); + expect(mockOpenModal).not.toHaveBeenCalled(); + }); + }); + describe('initializeEditorRef', () => { + const mockSetRef = jest.fn(val => ({ editor: val })); + const editor = { + editme: 'MakE sOMe Text', + }; + const evt = { + garbage: 'fOr TInYmCE', + }; + let output; + beforeEach(() => { + output = module.initializeEditorRef(mockSetRef); + }); + test('It calls setref with editor as params', () => { + output(evt, editor); + expect(mockSetRef).toHaveBeenCalledWith(editor); + }); + }); + describe('editorConfig', () => { + const blockvalue = null; + const props = { + setEditorRef: jest.fn(), + blockValue: blockvalue, + openModal: jest.fn(), + initializeEditor: jest.fn(), + }; + let output; + test('It creates an onInit which calls initializeEditor, but not setEditorRef', () => { + output = module.editorConfig(props); + output.onInit(); + expect(props.initializeEditor).toHaveBeenCalled(); + expect(props.setEditorRef).not.toHaveBeenCalled(); + }); + test('It sets the blockvalue to be empty string by default', () => { + output = module.editorConfig(props); + expect(output.initialValue).toBe(''); + }); + test('It sets the blockvalue to be the blockvalue if nonempty', () => { + const htmltext = 'SomE hTML content'; + const newprops = { + setEditorRef: jest.fn(), + blockValue: { + data: { + data: htmltext, + }, + }, + openModal: jest.fn(), + initializeEditor: jest.fn(), + }; + output = module.editorConfig(newprops); + expect(output.initialValue).toBe(htmltext); + }); + }); + }); + describe('modalToggle hook', () => { + let output; + beforeEach(() => { + output = module.modalToggle(); + }); + test('returns isOpen field, defaulted to false', () => { + expect(output.isOpen).toEqual({ state: false }); + }); + test('returns openModal field, which sets modal to true and calls updateState', () => { + output.openModal(); + expect(React.updateState).toHaveBeenCalledWith({ val: false, newVal: true }); + }); + test('returns closeModal field, which sets modal to true and calls updateState', () => { + output.closeModal(); + expect(React.updateState).toHaveBeenCalledWith({ val: false, newVal: false }); + }); + }); + describe('nullMethod hook', () => { + test('it outputs null', () => { + expect(module.nullMethod()).toBe(undefined); + }); + }); +});