Test: editor header component (#20)
* test: header tests start * test: EditableHeader test ready for review 1 * test: editor header tests complete * test: fixing up nits * test: ben's corrections
This commit is contained in:
29
src/editors/components/EditorHeader/EditableHeader.test.jsx
Normal file
29
src/editors/components/EditorHeader/EditableHeader.test.jsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { Icon, Form } from '@edx/paragon';
|
||||
import { Edit } from '@edx/paragon/icons';
|
||||
import * as module from './EditableHeader';
|
||||
|
||||
describe('EditableHeader', () => {
|
||||
const props = {
|
||||
handleChange: jest.fn().mockName('args.handleChange'),
|
||||
updateTitle: jest.fn().mockName('args.updateTitle'),
|
||||
handleKeyDown: jest.fn().mockName('args.handleKeyDown'),
|
||||
inputRef: jest.fn().mockName('args.inputRef'),
|
||||
localTitle: 'test-title-text',
|
||||
};
|
||||
let el;
|
||||
beforeEach(() => {
|
||||
el = shallow(<module.EditableHeader {...props} />);
|
||||
});
|
||||
|
||||
describe('snapshot', () => {
|
||||
test('snapshot', () => {
|
||||
expect(el).toMatchSnapshot();
|
||||
});
|
||||
test('displays Edit Icon', () => {
|
||||
const formControl = el.find(Form.Control);
|
||||
expect(formControl.props().trailingInputElement).toMatchObject(<Icon src={Edit} />);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -7,9 +7,9 @@ import { Edit } from '@edx/paragon/icons';
|
||||
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { actions, selectors } from '../../data/redux';
|
||||
import { localTitleHooks } from './hooks';
|
||||
import messages from '../messages';
|
||||
import EditableHeader from './EditableHeader';
|
||||
import { localTitleHooks } from './hooks';
|
||||
|
||||
export const HeaderTitle = ({
|
||||
editorRef,
|
||||
@@ -19,7 +19,6 @@ export const HeaderTitle = ({
|
||||
}) => {
|
||||
if (!isInitialized) { return <FormattedMessage {...messages.loading} />; }
|
||||
|
||||
console.log('HeaderTitle');
|
||||
const {
|
||||
inputRef,
|
||||
isEditing,
|
||||
@@ -53,13 +52,13 @@ export const HeaderTitle = ({
|
||||
{localTitle}
|
||||
</div>
|
||||
<IconButton
|
||||
iconAs={Icon}
|
||||
src={Edit}
|
||||
onClick={startEditing}
|
||||
alt="Edit"
|
||||
aria-label="Edit Title"
|
||||
className="mr-2"
|
||||
iconAs={Icon}
|
||||
onClick={startEditing}
|
||||
size="sm"
|
||||
src={Edit}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
86
src/editors/components/EditorHeader/HeaderTitle.test.jsx
Normal file
86
src/editors/components/EditorHeader/HeaderTitle.test.jsx
Normal file
@@ -0,0 +1,86 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import * as module from './HeaderTitle';
|
||||
import { actions, selectors } from '../../data/redux';
|
||||
import { localTitleHooks } from './hooks';
|
||||
|
||||
jest.mock('../../data/redux', () => ({
|
||||
actions: {
|
||||
app: {
|
||||
setBlockTitle: jest.fn().mockName('actions.app.setBlockTitle'),
|
||||
},
|
||||
},
|
||||
selectors: {
|
||||
app: {
|
||||
typeHeader: jest.fn(state => ({ typeHeader: state })),
|
||||
isInitialized: jest.fn(state => ({ studioEndpointUrl: state })),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('./hooks', () => ({
|
||||
localTitleHooks: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('HeaderTitle', () => {
|
||||
const props = {
|
||||
editorRef: jest.fn().mockName('args.editorRef'),
|
||||
isInitialized: false,
|
||||
setBlockTitle: jest.fn().mockName('args.setBlockTitle'),
|
||||
typeHeader: 'html',
|
||||
};
|
||||
const localTitleHooksProps = {
|
||||
inputRef: jest.fn().mockName('localTitleHooks.inputRef'),
|
||||
isEditing: false,
|
||||
handleChange: jest.fn().mockName('localTitleHooks.handleChange'),
|
||||
handleKeyDown: jest.fn().mockName('localTitleHooks.handleKeyDown'),
|
||||
localTitle: 'TeST LocALtitLE',
|
||||
startEditing: jest.fn().mockName('localTitleHooks.startEditing'),
|
||||
updateTitle: jest.fn().mockName('localTitleHooks.updateTitle'),
|
||||
};
|
||||
|
||||
describe('behavior', () => {
|
||||
it(' calls localTitleHooks with initialization args', () => {
|
||||
localTitleHooks.mockReturnValue(localTitleHooksProps);
|
||||
shallow(<module.HeaderTitle {...props} isInitialized />);
|
||||
expect(localTitleHooks).toHaveBeenCalledWith({
|
||||
editorRef: props.editorRef,
|
||||
setBlockTitle: props.setBlockTitle,
|
||||
typeHeader: props.typeHeader,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('snapshots', () => {
|
||||
test('not initialized', () => {
|
||||
expect(shallow(<module.HeaderTitle {...props} />)).toMatchSnapshot();
|
||||
});
|
||||
test('initialized', () => {
|
||||
localTitleHooks.mockReturnValue(hookProps);
|
||||
expect(shallow(<module.HeaderTitle {...props} isInitialized />)).toMatchSnapshot();
|
||||
});
|
||||
test('editing', () => {
|
||||
localTitleHooks.mockReturnValue({ ...hookProps, isEditing: true });
|
||||
expect(shallow(<module.HeaderTitle {...props} isInitialized />)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('mapStateToProps', () => {
|
||||
const testState = { T: 'esting', S: 'tate' };
|
||||
test('typeHeader from app.typeHeader', () => {
|
||||
expect(module.mapStateToProps(testState).typeHeader)
|
||||
.toEqual(selectors.app.typeHeader(testState));
|
||||
});
|
||||
test('isInitialized from app.isInitialized', () => {
|
||||
expect(module.mapStateToProps(testState).isInitialized)
|
||||
.toEqual(selectors.app.isInitialized(testState));
|
||||
});
|
||||
});
|
||||
|
||||
describe('mapDispatchToProps', () => {
|
||||
test('setBlockTitle from actions.app.setBlockTitle', () => {
|
||||
expect(module.mapDispatchToProps.setBlockTitle).toEqual(actions.app.setBlockTitle);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`EditableHeader snapshot 1`] = `
|
||||
<Form.Group>
|
||||
<Form.Control
|
||||
autoFocus={true}
|
||||
onBlur={[MockFunction args.updateTitle]}
|
||||
onChange={[MockFunction args.handleChange]}
|
||||
onKeyDown={[MockFunction args.handleKeyDown]}
|
||||
placeholder="Title"
|
||||
trailingInputElement={
|
||||
<Icon
|
||||
src={[MockFunction icons.Edit]}
|
||||
/>
|
||||
}
|
||||
value="test-title-text"
|
||||
/>
|
||||
</Form.Group>
|
||||
`;
|
||||
|
||||
exports[`EditableHeader snapshot snapshot 1`] = `
|
||||
<Form.Group>
|
||||
<Form.Control
|
||||
autoFocus={true}
|
||||
onBlur={[MockFunction args.updateTitle]}
|
||||
onChange={[MockFunction args.handleChange]}
|
||||
onKeyDown={[MockFunction args.handleKeyDown]}
|
||||
placeholder="Title"
|
||||
trailingInputElement={
|
||||
<Icon
|
||||
src={[MockFunction icons.Edit]}
|
||||
/>
|
||||
}
|
||||
value="test-title-text"
|
||||
/>
|
||||
</Form.Group>
|
||||
`;
|
||||
@@ -0,0 +1,45 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`HeaderTitle snapshots editing 1`] = `
|
||||
<EditableHeader
|
||||
handleChange={[MockFunction titleHooks.handleChange]}
|
||||
handleKeyDown={[MockFunction titleHooks.handleKeyDown]}
|
||||
inputRef={[MockFunction titleHooks.inputRef]}
|
||||
localTitle="TeST LocALtitLE"
|
||||
updateTitle={[MockFunction titleHooks.updateTitle]}
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`HeaderTitle snapshots initialized 1`] = `
|
||||
<div
|
||||
className="d-flex"
|
||||
>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"lineHeight": "1.5",
|
||||
"paddingRight": ".25em",
|
||||
}
|
||||
}
|
||||
>
|
||||
TeST LocALtitLE
|
||||
</div>
|
||||
<IconButton
|
||||
alt="Edit"
|
||||
aria-label="Edit Title"
|
||||
className="mr-2"
|
||||
iconAs="Icon"
|
||||
onClick={[MockFunction titleHooks.startEditing]}
|
||||
size="sm"
|
||||
src={[MockFunction icons.Edit]}
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`HeaderTitle snapshots not initialized 1`] = `
|
||||
<FormattedMessage
|
||||
defaultMessage="Loading..."
|
||||
description="Message displayed while loading content"
|
||||
id="authoring.texteditor.title.loading"
|
||||
/>
|
||||
`;
|
||||
@@ -0,0 +1,24 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[` 1`] = `
|
||||
<div
|
||||
className="editor-header"
|
||||
>
|
||||
<ModalDialog.Header>
|
||||
<ActionRow>
|
||||
<ModalDialog.Title>
|
||||
<HeaderTitle />
|
||||
</ModalDialog.Title>
|
||||
<ActionRow.Spacer />
|
||||
<IconButton
|
||||
alt="Close"
|
||||
aria-label="Cancel Changes and Return to Learning Context"
|
||||
className="mr-2"
|
||||
iconAs="Icon"
|
||||
src={[MockFunction icons.Close]}
|
||||
variant="light"
|
||||
/>
|
||||
</ActionRow>
|
||||
</ModalDialog.Header>
|
||||
</div>
|
||||
`;
|
||||
@@ -2,9 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import {
|
||||
ActionRow, IconButton, Icon, ModalDialog,
|
||||
} from '@edx/paragon';
|
||||
import { ActionRow, IconButton, Icon, ModalDialog } from '@edx/paragon';
|
||||
import { Close } from '@edx/paragon/icons';
|
||||
|
||||
import { selectors } from '../../data/redux';
|
||||
@@ -12,7 +10,7 @@ import * as appHooks from '../../hooks';
|
||||
|
||||
import HeaderTitle from './HeaderTitle';
|
||||
|
||||
const EditorHeader = ({
|
||||
export const EditorHeader = ({
|
||||
returnUrl,
|
||||
}) => (
|
||||
<div className="editor-header">
|
||||
|
||||
@@ -1,58 +1,56 @@
|
||||
import React from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import EditorHeader from './EditorHeader';
|
||||
import EditorPageContext from './EditorPageContext';
|
||||
import { ActionStates } from './data/constants';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
const locationTemp = window.location;
|
||||
beforeEach(() => {
|
||||
delete window.location;
|
||||
window.location = {
|
||||
assign: jest.fn(),
|
||||
};
|
||||
});
|
||||
afterAll(() => {
|
||||
window.location = locationTemp;
|
||||
});
|
||||
import { IconButton } from '@edx/paragon';
|
||||
import * as module from './index';
|
||||
import { selectors } from '../../data/redux';
|
||||
import * as appHooks from '../../hooks';
|
||||
|
||||
test('Rendering And Click Close Button: Does not Navigate off of Page When Loading', () => {
|
||||
const title = 'An Awesome Block';
|
||||
const context = {
|
||||
unitUrlLoading: ActionStates.IN_PROGRESS,
|
||||
};
|
||||
render(
|
||||
<EditorPageContext.Provider value={context}>
|
||||
<EditorHeader title={title} />
|
||||
</EditorPageContext.Provider>,
|
||||
);
|
||||
expect(screen.getByText(title)).toBeTruthy();
|
||||
expect(screen.getByLabelText('Close')).toBeTruthy();
|
||||
userEvent.click(screen.getByLabelText('Close'));
|
||||
expect(window.location.assign).not.toHaveBeenCalled();
|
||||
});
|
||||
jest.mock('.', () => ({
|
||||
__esModule: true, // Use it when dealing with esModules
|
||||
...jest.requireActual('./index'),
|
||||
handleCloseClicked: jest.fn(args => ({ handleCloseClicked: args })),
|
||||
}));
|
||||
|
||||
test('Rendering And Click Button: Loaded Navigates Away', () => {
|
||||
const title = 'An Awesome Block';
|
||||
const context = {
|
||||
unitUrlLoading: ActionStates.FINISHED,
|
||||
unitUrl: {
|
||||
data: {
|
||||
ancestors:
|
||||
[
|
||||
{ id: 'fakeblockid' },
|
||||
],
|
||||
},
|
||||
jest.mock('../../data/redux', () => ({
|
||||
selectors: {
|
||||
app: {
|
||||
returnUrl: jest.fn().mockName('actions.app.returnUrl'),
|
||||
},
|
||||
studioEndpointUrl: 'Testurl',
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('../../hooks', () => ({
|
||||
navigateCallback: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('./HeaderTitle', () => 'HeaderTitle');
|
||||
|
||||
describe('Editor Header index', () => {
|
||||
const props = {
|
||||
returnUrl: 'TeST-ReTurNurL',
|
||||
};
|
||||
render(
|
||||
<EditorPageContext.Provider value={context}>
|
||||
<EditorHeader title={title} />
|
||||
</EditorPageContext.Provider>,
|
||||
);
|
||||
expect(screen.getByText(title)).toBeTruthy();
|
||||
expect(screen.getByLabelText('Close')).toBeTruthy();
|
||||
userEvent.click(screen.getByLabelText('Close'));
|
||||
expect(window.location.assign).toHaveBeenCalled();
|
||||
const { EditorHeader } = module;
|
||||
let el;
|
||||
el = shallow(<EditorHeader {...props} />);
|
||||
|
||||
describe('behavior', () => {
|
||||
test('IconButton onClick calls navigateCallback', () => {
|
||||
const iconButtonControl = el.find(IconButton);
|
||||
iconButtonControl.simulate('click');
|
||||
expect(appHooks.navigateCallback).toHaveBeenCalledWith(props.returnUrl);
|
||||
});
|
||||
});
|
||||
|
||||
describe('snapshot', () => {
|
||||
expect(el).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe('mapStateToProps', () => {
|
||||
const testState = { T: 'est', S: 'tate' };
|
||||
test('returnUrl from app.returnUrl', () => {
|
||||
expect(module.mapStateToProps(testState).returnUrl)
|
||||
.toEqual(selectors.app.returnUrl(testState));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -40,7 +40,6 @@ export const TextEditor = ({
|
||||
blockFinished,
|
||||
initializeEditor,
|
||||
}) => {
|
||||
console.log({ blockValue, blockFailed, blockFinished, test: 1 });
|
||||
const { isOpen, openModal, closeModal } = modalToggle();
|
||||
|
||||
return (
|
||||
@@ -61,7 +60,10 @@ export const TextEditor = ({
|
||||
</div>
|
||||
)
|
||||
: (
|
||||
<Editor {...editorConfig({ setEditorRef, blockValue, openModal, initializeEditor })} />
|
||||
<Editor {...editorConfig({
|
||||
setEditorRef, blockValue, openModal, initializeEditor,
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
@@ -87,7 +89,7 @@ export const mapStateToProps = (state) => ({
|
||||
});
|
||||
|
||||
export const mapDispatchToProps = {
|
||||
initializeEditor: actions.app.initializeEditor,
|
||||
initializeEditor: actions.app.initializeEditor,
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(TextEditor);
|
||||
|
||||
@@ -58,7 +58,9 @@ jest.mock('@edx/frontend-platform/i18n', () => {
|
||||
});
|
||||
|
||||
jest.mock('@edx/paragon', () => jest.requireActual('testUtils').mockNestedComponents({
|
||||
ActionRow: 'ActionRow',
|
||||
ActionRow: {
|
||||
Spacer: 'ActionRow.Spacer',
|
||||
},
|
||||
Button: 'Button',
|
||||
Icon: 'Icon',
|
||||
IconButton: 'IconButton',
|
||||
|
||||
Reference in New Issue
Block a user