From 6ca93a729778662ccb8f478e3eb35744a4ba14cd Mon Sep 17 00:00:00 2001
From: connorhaugh <49422820+connorhaugh@users.noreply.github.com>
Date: Tue, 22 Feb 2022 13:24:15 -0500
Subject: [PATCH] test: add EditorFooter tests (#16)
* test: add EditorFooter tests
---
.../__snapshots__/index.test.jsx.snap | 142 +++++++++++++
src/editors/components/EditorFooter/index.jsx | 5 +-
.../components/EditorFooter/index.test.jsx | 187 +++++++++---------
src/editors/hooks.js | 7 +-
4 files changed, 239 insertions(+), 102 deletions(-)
create mode 100644 src/editors/components/EditorFooter/__snapshots__/index.test.jsx.snap
diff --git a/src/editors/components/EditorFooter/__snapshots__/index.test.jsx.snap b/src/editors/components/EditorFooter/__snapshots__/index.test.jsx.snap
new file mode 100644
index 000000000..6c506e04e
--- /dev/null
+++ b/src/editors/components/EditorFooter/__snapshots__/index.test.jsx.snap
@@ -0,0 +1,142 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`EditorFooter snapshots Save Failed, error message raised 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`EditorFooter snapshots not intialized, Spinner appears and button is disabled 1`] = `
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`EditorFooter snapshots renders as expected with default behavior 1`] = `
+
+
+
+
+
+
+
+
+
+`;
diff --git a/src/editors/components/EditorFooter/index.jsx b/src/editors/components/EditorFooter/index.jsx
index 728245a4e..c2b3de3ca 100644
--- a/src/editors/components/EditorFooter/index.jsx
+++ b/src/editors/components/EditorFooter/index.jsx
@@ -10,10 +10,11 @@ import {
Toast,
} from '@edx/paragon';
import { FormattedMessage } from '@edx/frontend-platform/i18n';
+import { nullMethod, saveTextBlock, navigateCallback } from '../../hooks';
import { RequestKeys } from '../../data/constants/requests';
import { selectors, thunkActions } from '../../data/redux';
-import { saveTextBlock, navigateCallback } from '../../hooks';
+
import messages from '../messages';
import * as module from '.';
@@ -30,7 +31,7 @@ export const EditorFooter = ({
}) => (
{saveFailed && (
-
+
)}
diff --git a/src/editors/components/EditorFooter/index.test.jsx b/src/editors/components/EditorFooter/index.test.jsx
index 6f2ce95c4..3711cc87d 100644
--- a/src/editors/components/EditorFooter/index.test.jsx
+++ b/src/editors/components/EditorFooter/index.test.jsx
@@ -1,104 +1,93 @@
import React from 'react';
-import { render, screen } from '@testing-library/react';
-import userEvent from '@testing-library/user-event';
-import { mount } from 'enzyme';
-import EditorFooter from './EditorFooter';
-import EditorPageContext from './EditorPageContext';
-import { ActionStates } from './data/constants';
-import EditorPageProvider from './EditorPageProvider';
-import { saveBlock } from './data/api';
+import { shallow } from 'enzyme';
+import * as module from './index';
+import { selectors, thunkActions } from '../../data/redux';
+import { RequestKeys } from '../../data/constants/requests';
+import { saveTextBlock, navigateCallback } from '../../hooks';
-const locationTemp = window.location;
-beforeAll(() => {
- delete window.location;
- window.location = {
- assign: jest.fn(),
- };
-});
-afterAll(() => {
- window.location = locationTemp;
-});
-
-jest.mock('./data/api', () => {
- const originalModule = jest.requireActual('./data/api');
- // Mock the default export and named export saveBlock
- return {
- __esModule: true,
- ...originalModule,
- saveBlock: jest.fn(() => {}),
- };
-});
-
-jest.spyOn(React, 'useRef').mockReturnValue({
- current: {
- getContent: () => '',
- },
-});
-
-test('Rendering: loaded', () => {
- const context = {
- unitUrlLoading: ActionStates.FINISHED,
- };
- render(
-
-
- ,
- );
- expect(screen.getByText('Cancel')).toBeTruthy();
- expect(screen.getByText('Add To Course')).toBeTruthy();
-});
-
-test('Rendering: loading url', () => {
- const context = {
- unitUrlLoading: ActionStates.NOT_BEGUN,
- };
- render(
-
-
- ,
- );
- expect(screen.getByText('Cancel')).toBeTruthy();
- expect(screen.getAllByRole('button', { 'aria-label': 'Save' })).toBeTruthy();
- expect(screen.queryByText('Add To Course')).toBeNull();
-});
-
-test('Navigation: Cancel', () => {
- const context = {
- unitUrlLoading: ActionStates.FINISHED,
- unitUrl: {
- data: {
- ancestors:
- [
- { id: 'fakeblockid' },
- ],
- },
+jest.mock('../../data/redux', () => ({
+ thunkActions: {
+ app: {
+ saveBlock: jest.fn().mockName('thunkActions.app.saveBlock'),
},
- studioEndpointUrl: 'Testurl',
- };
- render(
-
-
- ,
- );
- expect(screen.getByText('Cancel')).toBeTruthy();
- userEvent.click(screen.getByText('Cancel'));
- expect(window.location.assign).toHaveBeenCalled();
-});
+ },
+ selectors: {
+ app: {
+ isInitialized: jest.fn(state => ({ isInitialized: state })),
+ studioEndpointUrl: jest.fn(state => ({ studioEndpointUrl: state })),
+ },
+ requests: {
+ isFailed: jest.fn((state, params) => ({ isFailed: { state, params } })),
+ },
+ },
+}));
-test('Navigation: Save', () => {
- const wrapper = mount(
-
-
- ,
- );
- const button = wrapper.find({ children: 'Add To Course' });
- expect(button).toBeTruthy();
- button.simulate('click');
- expect(saveBlock).toHaveBeenCalled();
- expect(window.location.assign).toHaveBeenCalled();
+jest.mock('.', () => ({
+ __esModule: true, // Use it when dealing with esModules
+ ...jest.requireActual('./index'),
+ handleCancelClicked: jest.fn(args => ({ handleCancelClicked: args })),
+ handleSaveClicked: jest.fn(args => ({ handleSaveClicked: args })),
+ }
+));
+
+jest.mock('../../hooks', () => ({
+ saveTextBlock: jest.fn(),
+ navigateCallback: jest.fn(),
+ nullMethod: jest.fn().mockName('nullMethod'),
+}));
+
+describe('EditorFooter', () => {
+ const props = {
+ editorRef: jest.fn().mockName('args.editorRef'),
+ isInitialized: true,
+ returnUrl: 'hocuspocus.ca',
+ saveFailed: false,
+ saveBlock: jest.fn().mockName('args.saveBlock'),
+ };
+ describe('behavior', () => {
+ const realmodule = jest.requireActual('./index');
+ test('handleSaveClicked calls saveTextBlock', () => {
+ const createdCallback = realmodule.handleSaveClicked(props);
+ createdCallback();
+ expect(saveTextBlock).toHaveBeenCalled();
+ });
+ test('handleCancelClicked calls navigateCallback', () => {
+ realmodule.handleCancelClicked({ returnUrl: props.returnUrl });
+ expect(navigateCallback).toHaveBeenCalledWith(props.returnUrl);
+ });
+ });
+ describe('snapshots', () => {
+ test('renders as expected with default behavior', () => {
+ expect(shallow()).toMatchSnapshot();
+ });
+ test('not intialized, Spinner appears and button is disabled', () => {
+ expect(shallow()).toMatchSnapshot();
+ });
+ test('Save Failed, error message raised', () => {
+ expect(shallow()).toMatchSnapshot();
+ });
+ });
+ describe('mapStateToProps', () => {
+ const testState = { A: 'pple', B: 'anana', C: 'ucumber' };
+ test('isInitialized from app.isInitialized', () => {
+ expect(
+ module.mapStateToProps(testState).isInitialized,
+ ).toEqual(selectors.app.isInitialized(testState));
+ });
+ test('studioEndpointUrl from app.studioEndpointUrl', () => {
+ expect(
+ module.mapStateToProps(testState).studioEndpointUrl,
+ ).toEqual(selectors.app.studioEndpointUrl(testState));
+ });
+ test('saveFailed from requests.isFailed', () => {
+ expect(
+ module.mapStateToProps(testState).saveFailed,
+ ).toEqual(selectors.requests.isFailed(testState, { requestKey: RequestKeys.saveBlock }));
+ });
+ });
+ describe('mapDispatchToProps', () => {
+ test('saveBlock from thunkActions.app.saveBlock', () => {
+ expect(module.mapDispatchToProps.saveBlock).toEqual(thunkActions.app.saveBlock);
+ });
+ });
});
diff --git a/src/editors/hooks.js b/src/editors/hooks.js
index a86147665..e9f6fcea9 100644
--- a/src/editors/hooks.js
+++ b/src/editors/hooks.js
@@ -1,4 +1,6 @@
-import { useRef, useEffect, useCallback, useState } from 'react';
+import {
+ useRef, useEffect, useCallback, useState,
+} from 'react';
export const initializeApp = ({ initialize, data }) => useEffect(() => initialize(data), []);
@@ -28,3 +30,6 @@ export const saveTextBlock = ({
content: editorRef.current.getContent(),
});
};
+
+// for toast onClose to avoid console warnings
+export const nullMethod = () => {};