Commit 60246db2 authored by Lyza Danger Gardner's avatar Lyza Danger Gardner Committed by Lyza Gardner

Refactor and update tests

Update tests for the changes to props and callbacks in `AnnotationEditor`
and `AnnotationPublishControl`

There were some mis-nested tests for `AnnotationEditor`; fix.
parent 1cfb11c3
...@@ -12,6 +12,8 @@ import AnnotationEditor, { $imports } from '../AnnotationEditor'; ...@@ -12,6 +12,8 @@ import AnnotationEditor, { $imports } from '../AnnotationEditor';
describe('AnnotationEditor', () => { describe('AnnotationEditor', () => {
let fakeApplyTheme; let fakeApplyTheme;
let fakeAnnotationsService; let fakeAnnotationsService;
let fakeGroup;
let fakeMetadata;
let fakeTagsService; let fakeTagsService;
let fakeSettings; let fakeSettings;
let fakeToastMessenger; let fakeToastMessenger;
...@@ -22,6 +24,7 @@ describe('AnnotationEditor', () => { ...@@ -22,6 +24,7 @@ describe('AnnotationEditor', () => {
return mount( return mount(
<AnnotationEditor <AnnotationEditor
annotation={fixtures.defaultAnnotation()} annotation={fixtures.defaultAnnotation()}
draft={fixtures.defaultDraft()}
annotationsService={fakeAnnotationsService} annotationsService={fakeAnnotationsService}
settings={fakeSettings} settings={fakeSettings}
tags={fakeTagsService} tags={fakeTagsService}
...@@ -36,6 +39,17 @@ describe('AnnotationEditor', () => { ...@@ -36,6 +39,17 @@ describe('AnnotationEditor', () => {
fakeAnnotationsService = { fakeAnnotationsService = {
save: sinon.stub(), save: sinon.stub(),
}; };
fakeGroup = {
name: 'Fake Group',
type: 'private',
};
fakeMetadata = {
isReply: sinon.stub().returns(false),
isSaved: sinon.stub().returns(true),
};
fakeSettings = {}; fakeSettings = {};
fakeTagsService = { fakeTagsService = {
store: sinon.stub(), store: sinon.stub(),
...@@ -46,30 +60,31 @@ describe('AnnotationEditor', () => { ...@@ -46,30 +60,31 @@ describe('AnnotationEditor', () => {
fakeStore = { fakeStore = {
createDraft: sinon.stub(), createDraft: sinon.stub(),
getDraft: sinon.stub().returns(fixtures.defaultDraft()), getGroup: sinon.stub().returns(fakeGroup),
getGroup: sinon.stub(), setDefault: sinon.stub(),
removeDraft: sinon.stub(),
removeAnnotations: sinon.stub(),
}; };
$imports.$mock(mockImportedComponents()); $imports.$mock(mockImportedComponents());
$imports.$mock({ $imports.$mock({
'../../store/use-store': { useStoreProxy: () => fakeStore }, '../../store/use-store': { useStoreProxy: () => fakeStore },
'../../helpers/annotation-metadata': fakeMetadata,
'../../helpers/theme': { applyTheme: fakeApplyTheme }, '../../helpers/theme': { applyTheme: fakeApplyTheme },
}); });
// `AnnotationLicense` is a presentation-only component and is only used
// within `AnnotationEditor`. Not mocking it allows it to be exercised and
// meet code coverage.
$imports.$restore({
'./AnnotationLicense': true,
});
}); });
afterEach(() => { afterEach(() => {
$imports.$restore(); $imports.$restore();
}); });
it('is an empty component if there is no draft', () => { describe('editing text content', () => {
fakeStore.getDraft.returns(null);
const wrapper = createComponent();
assert.equal(wrapper.html(), '');
});
describe('markdown content editor', () => {
it('applies theme', () => { it('applies theme', () => {
const textStyle = { fontFamily: 'serif' }; const textStyle = { fontFamily: 'serif' };
fakeApplyTheme fakeApplyTheme
...@@ -95,8 +110,9 @@ describe('AnnotationEditor', () => { ...@@ -95,8 +110,9 @@ describe('AnnotationEditor', () => {
assert.calledOnce(fakeStore.createDraft); assert.calledOnce(fakeStore.createDraft);
assert.equal(call.args[1].text, 'updated text'); assert.equal(call.args[1].text, 'updated text');
}); });
});
describe('tag editing', () => { describe('editing tags', () => {
it('adds tag when add callback invoked', () => { it('adds tag when add callback invoked', () => {
const wrapper = createComponent(); const wrapper = createComponent();
wrapper.find('TagEditor').props().onAddTag('newTag'); wrapper.find('TagEditor').props().onAddTag('newTag');
...@@ -111,9 +127,8 @@ describe('AnnotationEditor', () => { ...@@ -111,9 +127,8 @@ describe('AnnotationEditor', () => {
it('does not add duplicate tags', () => { it('does not add duplicate tags', () => {
const draft = fixtures.defaultDraft(); const draft = fixtures.defaultDraft();
draft.tags = ['newTag']; draft.tags = ['newTag'];
fakeStore.getDraft.returns(draft);
const wrapper = createComponent(); const wrapper = createComponent({ draft });
wrapper.find('TagEditor').props().onAddTag('newTag'); wrapper.find('TagEditor').props().onAddTag('newTag');
assert.equal(fakeTagsService.store.callCount, 0); assert.equal(fakeTagsService.store.callCount, 0);
...@@ -123,9 +138,8 @@ describe('AnnotationEditor', () => { ...@@ -123,9 +138,8 @@ describe('AnnotationEditor', () => {
it('removes tag when remove callback invoked', () => { it('removes tag when remove callback invoked', () => {
const draft = fixtures.defaultDraft(); const draft = fixtures.defaultDraft();
draft.tags = ['newTag']; draft.tags = ['newTag'];
fakeStore.getDraft.returns(draft);
const wrapper = createComponent(); const wrapper = createComponent({ draft });
wrapper.find('TagEditor').props().onRemoveTag('newTag'); wrapper.find('TagEditor').props().onRemoveTag('newTag');
const draftCall = fakeStore.createDraft.getCall(0); const draftCall = fakeStore.createDraft.getCall(0);
...@@ -136,9 +150,8 @@ describe('AnnotationEditor', () => { ...@@ -136,9 +150,8 @@ describe('AnnotationEditor', () => {
it('does not remove non-existent tags', () => { it('does not remove non-existent tags', () => {
const draft = fixtures.defaultDraft(); const draft = fixtures.defaultDraft();
fakeStore.getDraft.returns(draft);
const wrapper = createComponent(); const wrapper = createComponent({ draft });
wrapper.find('TagEditor').props().onRemoveTag('newTag'); wrapper.find('TagEditor').props().onRemoveTag('newTag');
assert.equal(fakeTagsService.store.callCount, 0); assert.equal(fakeTagsService.store.callCount, 0);
...@@ -190,8 +203,7 @@ describe('AnnotationEditor', () => { ...@@ -190,8 +203,7 @@ describe('AnnotationEditor', () => {
const draft = fixtures.defaultDraft(); const draft = fixtures.defaultDraft();
// Need some content so that it won't evaluate as "empty" and not save // Need some content so that it won't evaluate as "empty" and not save
draft.text = 'something is here'; draft.text = 'something is here';
fakeStore.getDraft.returns(draft); const wrapper = createComponent({ draft });
const wrapper = createComponent();
wrapper wrapper
.find('.AnnotationEditor') .find('.AnnotationEditor')
...@@ -208,8 +220,7 @@ describe('AnnotationEditor', () => { ...@@ -208,8 +220,7 @@ describe('AnnotationEditor', () => {
const draft = fixtures.defaultDraft(); const draft = fixtures.defaultDraft();
// Need some content so that it won't evaluate as "empty" and not save // Need some content so that it won't evaluate as "empty" and not save
draft.text = 'something is here'; draft.text = 'something is here';
fakeStore.getDraft.returns(draft); const wrapper = createComponent({ draft });
const wrapper = createComponent();
wrapper wrapper
.find('.AnnotationEditor') .find('.AnnotationEditor')
...@@ -231,8 +242,8 @@ describe('AnnotationEditor', () => { ...@@ -231,8 +242,8 @@ describe('AnnotationEditor', () => {
assert.notCalled(fakeAnnotationsService.save); assert.notCalled(fakeAnnotationsService.save);
}); });
});
describe('handling publish options', () => {
it('sets the publish control to disabled if the annotation is empty', () => { it('sets the publish control to disabled if the annotation is empty', () => {
// default draft has no tags or text // default draft has no tags or text
const wrapper = createComponent(); const wrapper = createComponent();
...@@ -245,14 +256,85 @@ describe('AnnotationEditor', () => { ...@@ -245,14 +256,85 @@ describe('AnnotationEditor', () => {
it('enables the publish control when annotation has content', () => { it('enables the publish control when annotation has content', () => {
const draft = fixtures.defaultDraft(); const draft = fixtures.defaultDraft();
draft.text = 'something is here'; draft.text = 'something is here';
fakeStore.getDraft.returns(draft); const wrapper = createComponent({ draft });
const wrapper = createComponent();
assert.isFalse( assert.isFalse(
wrapper.find('AnnotationPublishControl').props().isDisabled wrapper.find('AnnotationPublishControl').props().isDisabled
); );
}); });
context('privacy changed in publish control', () => {
it("updates the draft's privacy when set to private", () => {
const draft = fixtures.defaultDraft();
draft.isPrivate = false;
const wrapper = createComponent({ draft });
wrapper.find('AnnotationPublishControl').props().onSetPrivacy(true);
const call = fakeStore.createDraft.getCall(0);
assert.calledOnce(fakeStore.createDraft);
assert.isTrue(call.args[1].isPrivate);
});
it("updates the draft's privacy when set to shared", () => {
const wrapper = createComponent();
wrapper.find('AnnotationPublishControl').props().onSetPrivacy(false);
const call = fakeStore.createDraft.getCall(0);
assert.calledOnce(fakeStore.createDraft);
assert.isFalse(call.args[1].isPrivate);
});
it('updates privacy default setting', () => {
const wrapper = createComponent();
wrapper.find('AnnotationPublishControl').props().onSetPrivacy(false);
assert.calledOnce(fakeStore.setDefault);
assert.calledWith(
fakeStore.setDefault,
'annotationPrivacy',
'shared'
);
});
it('does not update privacy default if annotation is a reply', () => {
fakeMetadata.isReply.returns(true);
const wrapper = createComponent();
wrapper.find('AnnotationPublishControl').props().onSetPrivacy(false);
assert.notCalled(fakeStore.setDefault);
});
});
});
});
context('exiting edit mode', () => {
it('removes the current draft when canceled', () => {
const wrapper = createComponent();
wrapper.find('AnnotationPublishControl').props().onCancel();
assert.calledOnce(fakeStore.removeDraft);
assert.calledWith(fakeStore.removeDraft, wrapper.props().annotation);
assert.equal(fakeStore.removeAnnotations.callCount, 0);
});
it('removes annotation from store if it is an unsaved annotation', () => {
fakeMetadata.isSaved.returns(false);
const wrapper = createComponent();
wrapper.find('AnnotationPublishControl').props().onCancel();
assert.calledOnce(fakeStore.removeDraft);
assert.calledOnce(fakeStore.removeAnnotations);
});
});
it('shows license info if annotation is shared and in a public group', () => { it('shows license info if annotation is shared and in a public group', () => {
fakeStore.getGroup.returns({ type: 'open' }); fakeStore.getGroup.returns({ type: 'open' });
...@@ -265,9 +347,8 @@ describe('AnnotationEditor', () => { ...@@ -265,9 +347,8 @@ describe('AnnotationEditor', () => {
const draft = fixtures.defaultDraft(); const draft = fixtures.defaultDraft();
draft.isPrivate = true; draft.isPrivate = true;
fakeStore.getGroup.returns({ type: 'open' }); fakeStore.getGroup.returns({ type: 'open' });
fakeStore.getDraft.returns(draft);
const wrapper = createComponent(); const wrapper = createComponent({ draft });
assert.isFalse(wrapper.find('AnnotationLicense').exists()); assert.isFalse(wrapper.find('AnnotationLicense').exists());
}); });
...@@ -279,7 +360,6 @@ describe('AnnotationEditor', () => { ...@@ -279,7 +360,6 @@ describe('AnnotationEditor', () => {
assert.isFalse(wrapper.find('AnnotationLicense').exists()); assert.isFalse(wrapper.find('AnnotationLicense').exists());
}); });
});
it( it(
'should pass a11y checks', 'should pass a11y checks',
......
import { mount } from 'enzyme'; import { mount } from 'enzyme';
import * as fixtures from '../../../test/annotation-fixtures';
import { checkAccessibility } from '../../../../test-util/accessibility'; import { checkAccessibility } from '../../../../test-util/accessibility';
import { mockImportedComponents } from '../../../../test-util/mock-imported-components'; import { mockImportedComponents } from '../../../../test-util/mock-imported-components';
...@@ -11,17 +9,22 @@ import AnnotationPublishControl, { ...@@ -11,17 +9,22 @@ import AnnotationPublishControl, {
describe('AnnotationPublishControl', () => { describe('AnnotationPublishControl', () => {
let fakeGroup; let fakeGroup;
let fakeMetadata;
let fakeSettings; let fakeSettings;
let fakeStore;
let fakeApplyTheme; let fakeApplyTheme;
let fakeOnSave;
let fakeOnCancel;
let fakeOnSetPrivacy;
const createAnnotationPublishControl = (props = {}) => { const createAnnotationPublishControl = (props = {}) => {
return mount( return mount(
<AnnotationPublishControl <AnnotationPublishControl
annotation={fixtures.defaultAnnotation()} group={fakeGroup}
isDisabled={false} isDisabled={false}
onSave={sinon.stub()} isPrivate={false}
onCancel={fakeOnCancel}
onSave={fakeOnSave}
onSetPrivacy={fakeOnSetPrivacy}
settings={fakeSettings} settings={fakeSettings}
{...props} {...props}
/> />
...@@ -29,16 +32,14 @@ describe('AnnotationPublishControl', () => { ...@@ -29,16 +32,14 @@ describe('AnnotationPublishControl', () => {
}; };
beforeEach(() => { beforeEach(() => {
fakeOnCancel = sinon.stub();
fakeOnSave = sinon.stub();
fakeOnSetPrivacy = sinon.stub();
fakeGroup = { fakeGroup = {
name: 'Fake Group', name: 'Fake Group',
type: 'private', type: 'private',
}; };
fakeMetadata = {
isNew: sinon.stub(),
isReply: sinon.stub().returns(false),
};
fakeSettings = { fakeSettings = {
branding: { branding: {
ctaTextColor: '#0f0', ctaTextColor: '#0f0',
...@@ -46,21 +47,10 @@ describe('AnnotationPublishControl', () => { ...@@ -46,21 +47,10 @@ describe('AnnotationPublishControl', () => {
}, },
}; };
fakeStore = {
createDraft: sinon.stub(),
getDraft: sinon.stub().returns(fixtures.defaultDraft()),
getGroup: sinon.stub().returns(fakeGroup),
setDefault: sinon.stub(),
removeAnnotations: sinon.stub(),
removeDraft: sinon.stub(),
};
fakeApplyTheme = sinon.stub(); fakeApplyTheme = sinon.stub();
$imports.$mock(mockImportedComponents()); $imports.$mock(mockImportedComponents());
$imports.$mock({ $imports.$mock({
'../../store/use-store': { useStoreProxy: () => fakeStore },
'../../helpers/annotation-metadata': fakeMetadata,
'../../helpers/theme': { '../../helpers/theme': {
applyTheme: fakeApplyTheme, applyTheme: fakeApplyTheme,
}, },
...@@ -71,12 +61,6 @@ describe('AnnotationPublishControl', () => { ...@@ -71,12 +61,6 @@ describe('AnnotationPublishControl', () => {
$imports.$restore(); $imports.$restore();
}); });
it('should not render if group is missing', () => {
fakeStore.getGroup.returns(undefined);
const wrapper = createAnnotationPublishControl();
assert.isFalse(wrapper.find('.AnnotationPublishControl').exists());
});
const getPublishButton = wrapper => const getPublishButton = wrapper =>
wrapper.find('LabeledButton[data-testid="publish-control-button"]'); wrapper.find('LabeledButton[data-testid="publish-control-button"]');
...@@ -108,10 +92,7 @@ describe('AnnotationPublishControl', () => { ...@@ -108,10 +92,7 @@ describe('AnnotationPublishControl', () => {
context('private annotation', () => { context('private annotation', () => {
it('should label the button with "Only Me"', () => { it('should label the button with "Only Me"', () => {
const draft = fixtures.defaultDraft(); const wrapper = createAnnotationPublishControl({ isPrivate: true });
draft.isPrivate = true;
fakeStore.getDraft.returns(draft);
const wrapper = createAnnotationPublishControl();
const btn = getPublishButton(wrapper); const btn = getPublishButton(wrapper);
assert.equal(btn.text(), 'Post to Only Me'); assert.equal(btn.text(), 'Post to Only Me');
...@@ -144,43 +125,14 @@ describe('AnnotationPublishControl', () => { ...@@ -144,43 +125,14 @@ describe('AnnotationPublishControl', () => {
describe('menu', () => { describe('menu', () => {
describe('share (to group) menu item', () => { describe('share (to group) menu item', () => {
it('should invoke privacy callback with shared privacy', () => { it('should set privacy to shared when group name clicked', () => {
const wrapper = createAnnotationPublishControl(); const wrapper = createAnnotationPublishControl();
const shareMenuItem = wrapper.find('MenuItem').first(); const shareMenuItem = wrapper.find('MenuItem[label="Fake Group"]');
shareMenuItem.prop('onClick')(); shareMenuItem.prop('onClick')();
const call = fakeStore.createDraft.getCall(0); assert.calledOnce(fakeOnSetPrivacy);
assert.calledWith(fakeOnSetPrivacy, false);
assert.calledOnce(fakeStore.createDraft);
assert.isFalse(call.args[1].isPrivate);
});
it('should update default privacy level to shared', () => {
const wrapper = createAnnotationPublishControl();
const privateMenuItem = wrapper.find('MenuItem').first();
privateMenuItem.prop('onClick')();
assert.calledOnce(fakeStore.setDefault);
assert.calledWith(fakeStore.setDefault, 'annotationPrivacy', 'shared');
});
it('should not update default privacy level if annotation is reply', () => {
fakeMetadata.isReply.returns(true);
const wrapper = createAnnotationPublishControl();
const privateMenuItem = wrapper.find('MenuItem').first();
privateMenuItem.prop('onClick')();
assert.equal(fakeStore.setDefault.callCount, 0);
});
it('should have a label that is the name of the group', () => {
const wrapper = createAnnotationPublishControl();
const shareMenuItem = wrapper.find('MenuItem').first();
assert.equal(shareMenuItem.prop('label'), fakeGroup.name);
}); });
context('private group', () => { context('private group', () => {
...@@ -191,6 +143,7 @@ describe('AnnotationPublishControl', () => { ...@@ -191,6 +143,7 @@ describe('AnnotationPublishControl', () => {
assert.equal(shareMenuItem.prop('icon'), 'groups'); assert.equal(shareMenuItem.prop('icon'), 'groups');
}); });
}); });
context('open group', () => { context('open group', () => {
beforeEach(() => { beforeEach(() => {
fakeGroup.type = 'open'; fakeGroup.type = 'open';
...@@ -206,36 +159,14 @@ describe('AnnotationPublishControl', () => { ...@@ -206,36 +159,14 @@ describe('AnnotationPublishControl', () => {
}); });
describe('private (only me) menu item', () => { describe('private (only me) menu item', () => {
it('should invoke callback with private privacy', () => { it('should set privacy to private when "Only Me" option clicked', () => {
const wrapper = createAnnotationPublishControl();
const privateMenuItem = wrapper.find('MenuItem').at(1);
privateMenuItem.prop('onClick')();
const call = fakeStore.createDraft.getCall(0);
assert.calledOnce(fakeStore.createDraft);
assert.isTrue(call.args[1].isPrivate);
});
it('should update default privacy level to private', () => {
const wrapper = createAnnotationPublishControl();
const privateMenuItem = wrapper.find('MenuItem').at(1);
privateMenuItem.prop('onClick')();
assert.calledOnce(fakeStore.setDefault);
assert.calledWith(fakeStore.setDefault, 'annotationPrivacy', 'private');
});
it('should not update default privacy level if annotation is reply', () => {
fakeMetadata.isReply.returns(true);
const wrapper = createAnnotationPublishControl(); const wrapper = createAnnotationPublishControl();
const privateMenuItem = wrapper.find('MenuItem').at(1); const shareMenuItem = wrapper.find('MenuItem[label="Only Me"]');
privateMenuItem.prop('onClick')(); shareMenuItem.prop('onClick')();
assert.equal(fakeStore.setDefault.callCount, 0); assert.calledOnce(fakeOnSetPrivacy);
assert.calledWith(fakeOnSetPrivacy, true);
}); });
it('should use a private/lock icon', () => { it('should use a private/lock icon', () => {
...@@ -244,6 +175,7 @@ describe('AnnotationPublishControl', () => { ...@@ -244,6 +175,7 @@ describe('AnnotationPublishControl', () => {
assert.equal(privateMenuItem.prop('icon'), 'lock'); assert.equal(privateMenuItem.prop('icon'), 'lock');
}); });
it('should have an "Only me" label', () => { it('should have an "Only me" label', () => {
const wrapper = createAnnotationPublishControl(); const wrapper = createAnnotationPublishControl();
const privateMenuItem = wrapper.find('MenuItem').at(1); const privateMenuItem = wrapper.find('MenuItem').at(1);
...@@ -254,29 +186,15 @@ describe('AnnotationPublishControl', () => { ...@@ -254,29 +186,15 @@ describe('AnnotationPublishControl', () => {
}); });
describe('cancel button', () => { describe('cancel button', () => {
it('should remove the current draft on cancel button click', () => { it('should invoke the `onCancel` callback when cancel button clicked', () => {
const wrapper = createAnnotationPublishControl({}); const wrapper = createAnnotationPublishControl();
const cancelBtn = wrapper
.find('LabeledButton')
.filter({ icon: 'cancel' });
cancelBtn.props().onClick();
assert.calledOnce(fakeStore.removeDraft);
assert.calledWith(fakeStore.removeDraft, wrapper.props().annotation);
assert.equal(fakeStore.removeAnnotations.callCount, 0);
});
it('should remove the annotation from the store if it is new/unsaved', () => {
fakeMetadata.isNew.returns(true);
const wrapper = createAnnotationPublishControl({});
const cancelBtn = wrapper const cancelBtn = wrapper
.find('LabeledButton') .find('LabeledButton')
.filter({ icon: 'cancel' }); .filter({ icon: 'cancel' });
cancelBtn.props().onClick(); cancelBtn.props().onClick();
assert.calledOnce(fakeStore.removeAnnotations); assert.calledOnce(fakeOnCancel);
}); });
}); });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment