test: add TextEditor Tests (#21)
This commit is contained in:
@@ -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: () => <div role={mockRole} />
|
||||
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(
|
||||
<EditorPageContext.Provider value={context}>
|
||||
<TextEditor />
|
||||
</EditorPageContext.Provider>,
|
||||
);
|
||||
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(
|
||||
<EditorPageContext.Provider value={context}>
|
||||
<TextEditor />
|
||||
</EditorPageContext.Provider>,
|
||||
);
|
||||
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(<TextEditor {...props} />)).toMatchSnapshot();
|
||||
});
|
||||
test('not yet loaded, Spinner appears', () => {
|
||||
expect(shallow(<TextEditor {...props} blockFinished={false} />)).toMatchSnapshot();
|
||||
});
|
||||
test('block failed to load, Toast is shown', () => {
|
||||
expect(shallow(<TextEditor {...props} blockFailed />)).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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`TextEditor snapshots block failed to load, Toast is shown 1`] = `
|
||||
<div
|
||||
className="editor-body h-75"
|
||||
>
|
||||
<ImageUploadModal
|
||||
close={[MockFunction modal.closeModal]}
|
||||
isOpen={false}
|
||||
/>
|
||||
<Toast
|
||||
onClose={[MockFunction nullMethod]}
|
||||
show={true}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Error: Could Not Load Text Content"
|
||||
description="Error Message Dispayed When HTML content fails to Load"
|
||||
id="authoring.texteditor.load.error"
|
||||
/>
|
||||
</Toast>
|
||||
<Editor
|
||||
editorConfig={
|
||||
Object {
|
||||
"blockValue": Object {
|
||||
"data": "HYleTsEditTeaxt",
|
||||
},
|
||||
"initializeEditor": [MockFunction args.intializeEditor],
|
||||
"openModal": [MockFunction modal.openModal],
|
||||
"setEditorRef": [MockFunction args.setEditorRef],
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`TextEditor snapshots not yet loaded, Spinner appears 1`] = `
|
||||
<div
|
||||
className="editor-body h-75"
|
||||
>
|
||||
<ImageUploadModal
|
||||
close={[MockFunction modal.closeModal]}
|
||||
isOpen={false}
|
||||
/>
|
||||
<Toast
|
||||
onClose={[MockFunction nullMethod]}
|
||||
show={false}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Error: Could Not Load Text Content"
|
||||
description="Error Message Dispayed When HTML content fails to Load"
|
||||
id="authoring.texteditor.load.error"
|
||||
/>
|
||||
</Toast>
|
||||
<div
|
||||
className="text-center p-6"
|
||||
>
|
||||
<Spinner
|
||||
animation="border"
|
||||
className="m-3"
|
||||
screenreadertext="loading"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`TextEditor snapshots renders as expected with default behavior 1`] = `
|
||||
<div
|
||||
className="editor-body h-75"
|
||||
>
|
||||
<ImageUploadModal
|
||||
close={[MockFunction modal.closeModal]}
|
||||
isOpen={false}
|
||||
/>
|
||||
<Toast
|
||||
onClose={[MockFunction nullMethod]}
|
||||
show={false}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Error: Could Not Load Text Content"
|
||||
description="Error Message Dispayed When HTML content fails to Load"
|
||||
id="authoring.texteditor.load.error"
|
||||
/>
|
||||
</Toast>
|
||||
<Editor
|
||||
editorConfig={
|
||||
Object {
|
||||
"blockValue": Object {
|
||||
"data": "HYleTsEditTeaxt",
|
||||
},
|
||||
"initializeEditor": [MockFunction args.intializeEditor],
|
||||
"openModal": [MockFunction modal.openModal],
|
||||
"setEditorRef": [MockFunction args.setEditorRef],
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
110
src/editors/containers/TextEditor/hooks.test.jsx
Normal file
110
src/editors/containers/TextEditor/hooks.test.jsx
Normal file
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user