TNL-716: Add possibility for notes creation via keyboard.
This commit is contained in:
@@ -43,7 +43,7 @@ define([
|
||||
describe('destroy', function () {
|
||||
it('should unbind all events', function () {
|
||||
spyOn($.fn, 'off');
|
||||
spyOn(this.annotator, 'unsubscribe');
|
||||
spyOn(this.annotator, 'unsubscribe').andCallThrough();
|
||||
this.plugin.destroy();
|
||||
expect(this.annotator.unsubscribe).toHaveBeenCalledWith(
|
||||
'annotationViewerTextField', this.plugin.addAriaAttributes
|
||||
@@ -54,6 +54,9 @@ define([
|
||||
expect(this.annotator.unsubscribe).toHaveBeenCalledWith(
|
||||
'annotationCreated', this.plugin.addDescriptions
|
||||
);
|
||||
expect(this.annotator.unsubscribe).toHaveBeenCalledWith(
|
||||
'annotationCreated', this.plugin.focusOnHighlightedText
|
||||
);
|
||||
expect(this.annotator.unsubscribe).toHaveBeenCalledWith(
|
||||
'annotationDeleted', this.plugin.removeDescription
|
||||
);
|
||||
@@ -136,11 +139,9 @@ define([
|
||||
it('should focus highlighted text after closing', function () {
|
||||
var note;
|
||||
highlight.trigger(keyDownEvent(this.KEY.ENTER));
|
||||
expect(this.plugin.savedHighlights).toBeDefined();
|
||||
note = this.annotator.element.find('.annotator-edit');
|
||||
note.trigger(keyDownEvent(this.KEY.ESCAPE));
|
||||
expect(highlight).toBeFocused();
|
||||
expect(this.plugin.savedHighlights).toBeNull();
|
||||
});
|
||||
|
||||
it('should focus on grabber after being deleted', function () {
|
||||
|
||||
200
lms/static/js/spec/edxnotes/plugins/caret_navigation_spec.js
Normal file
200
lms/static/js/spec/edxnotes/plugins/caret_navigation_spec.js
Normal file
@@ -0,0 +1,200 @@
|
||||
define([
|
||||
'jquery', 'underscore', 'annotator_1.2.9', 'logger', 'js/edxnotes/views/notes_factory'
|
||||
], function($, _, Annotator, Logger, NotesFactory) {
|
||||
'use strict';
|
||||
describe('EdxNotes CaretNavigation Plugin', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
loadFixtures('js/fixtures/edxnotes/edxnotes_wrapper.html');
|
||||
this.annotator = NotesFactory.factory(
|
||||
$('div#edx-notes-wrapper-123').get(0), {
|
||||
endpoint: 'http://example.com/'
|
||||
}
|
||||
);
|
||||
this.plugin = this.annotator.plugins.CaretNavigation;
|
||||
spyOn(Logger, 'log');
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
_.invoke(Annotator._instances, 'destroy');
|
||||
});
|
||||
|
||||
describe('destroy', function () {
|
||||
it('should unbind all events', function () {
|
||||
spyOn($.fn, 'off');
|
||||
this.plugin.destroy();
|
||||
expect($.fn.off).toHaveBeenCalledWith('keyup', this.plugin.onKeyUp);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isShortcut', function () {
|
||||
it('should return `true` if it is a shortcut', function () {
|
||||
expect(this.plugin.isShortcut($.Event('keyup', {
|
||||
ctrlKey: true,
|
||||
shiftKey: true,
|
||||
keyCode: 221
|
||||
}))).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return `false` if it is not a shortcut', function () {
|
||||
expect(this.plugin.isShortcut($.Event('keyup', {
|
||||
ctrlKey: false,
|
||||
shiftKey: true,
|
||||
keyCode: 221
|
||||
}))).toBeFalsy();
|
||||
|
||||
expect(this.plugin.isShortcut($.Event('keyup', {
|
||||
ctrlKey: true,
|
||||
shiftKey: true,
|
||||
keyCode: $.ui.keyCode.TAB
|
||||
}))).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasSelection', function () {
|
||||
it('should return `true` if has selection', function () {
|
||||
expect(this.plugin.hasSelection([{}, {}])).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return `false` if does not have selection', function () {
|
||||
expect(this.plugin.hasSelection([])).toBeFalsy();
|
||||
expect(this.plugin.hasSelection()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('onKeyUp', function () {
|
||||
var triggerEvent = function (element, props) {
|
||||
var eventProps = $.extend({
|
||||
ctrlKey: true,
|
||||
shiftKey: true,
|
||||
keyCode: 221
|
||||
}, props);
|
||||
element.trigger($.Event('keyup', eventProps));
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
this.element = $('<span />', {'class': 'annotator-hl'}).appendTo(this.annotator.element);
|
||||
|
||||
this.annotation = {
|
||||
text: "test",
|
||||
highlights: [this.element.get(0)]
|
||||
};
|
||||
|
||||
this.mockOffset = {top: 0, left:0};
|
||||
|
||||
this.mockSubscriber = jasmine.createSpy();
|
||||
this.annotator.subscribe('annotationCreated', this.mockSubscriber);
|
||||
|
||||
spyOn($.fn, 'position').andReturn(this.mockOffset);
|
||||
spyOn(this.annotator, 'createAnnotation').andReturn(this.annotation);
|
||||
spyOn(this.annotator, 'setupAnnotation').andReturn(this.annotation);
|
||||
spyOn(this.annotator, 'getSelectedRanges').andReturn([{}]);
|
||||
spyOn(this.annotator, 'deleteAnnotation');
|
||||
spyOn(this.annotator, 'showEditor');
|
||||
spyOn(Annotator.Util, 'readRangeViaSelection');
|
||||
spyOn(this.plugin, 'saveSelection');
|
||||
spyOn(this.plugin, 'restoreSelection');
|
||||
});
|
||||
|
||||
it('should create a new annotation', function () {
|
||||
triggerEvent(this.element);
|
||||
expect(this.annotator.createAnnotation.callCount).toBe(1);
|
||||
});
|
||||
|
||||
it('should set up the annotation', function () {
|
||||
triggerEvent(this.element);
|
||||
expect(this.annotator.setupAnnotation).toHaveBeenCalledWith(
|
||||
this.annotation
|
||||
);
|
||||
});
|
||||
|
||||
it('should display the Annotation#editor correctly if the Annotation#adder is hidden', function () {
|
||||
spyOn($.fn, 'is').andReturn(false);
|
||||
triggerEvent(this.element);
|
||||
expect($('annotator-hl-temporary').position.callCount).toBe(1);
|
||||
expect(this.annotator.showEditor).toHaveBeenCalledWith(
|
||||
this.annotation, this.mockOffset
|
||||
);
|
||||
});
|
||||
|
||||
it('should display the Annotation#editor in the same place as the Annotation#adder', function () {
|
||||
spyOn($.fn, 'is').andReturn(true);
|
||||
triggerEvent(this.element);
|
||||
expect(this.annotator.adder.position.callCount).toBe(1);
|
||||
expect(this.annotator.showEditor).toHaveBeenCalledWith(
|
||||
this.annotation, this.mockOffset
|
||||
);
|
||||
});
|
||||
|
||||
it('should hide the Annotation#adder', function () {
|
||||
spyOn($.fn, 'is').andReturn(true);
|
||||
spyOn($.fn, 'hide');
|
||||
triggerEvent(this.element);
|
||||
expect(this.annotator.adder.hide).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should add temporary highlights to the document to show the user what they selected', function () {
|
||||
triggerEvent(this.element);
|
||||
expect(this.element).toHaveClass('annotator-hl');
|
||||
expect(this.element).toHaveClass('annotator-hl-temporary');
|
||||
});
|
||||
|
||||
it('should persist the temporary highlights if the annotation is saved', function () {
|
||||
triggerEvent(this.element);
|
||||
this.annotator.publish('annotationEditorSubmit');
|
||||
expect(this.element).toHaveClass('annotator-hl');
|
||||
expect(this.element).not.toHaveClass('annotator-hl-temporary');
|
||||
});
|
||||
|
||||
it('should trigger the `annotationCreated` event if the edit\'s saved', function () {
|
||||
triggerEvent(this.element);
|
||||
this.annotator.onEditorSubmit(this.annotation);
|
||||
expect(this.mockSubscriber).toHaveBeenCalledWith(this.annotation);
|
||||
});
|
||||
|
||||
it('should call Annotator#deleteAnnotation if editing is cancelled', function () {
|
||||
triggerEvent(this.element);
|
||||
this.annotator.onEditorHide();
|
||||
expect(this.mockSubscriber).not.toHaveBeenCalledWith('annotationCreated');
|
||||
expect(this.annotator.deleteAnnotation).toHaveBeenCalledWith(
|
||||
this.annotation
|
||||
);
|
||||
});
|
||||
|
||||
it('should restore selection if editing is cancelled', function () {
|
||||
triggerEvent(this.element);
|
||||
this.plugin.savedRange = 'range';
|
||||
expect(this.plugin.saveSelection).toHaveBeenCalled();
|
||||
this.annotator.onEditorHide();
|
||||
expect(this.plugin.restoreSelection).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should do nothing if the edit\'s saved', function () {
|
||||
triggerEvent(this.element);
|
||||
expect(this.plugin.saveSelection).toHaveBeenCalled();
|
||||
this.plugin.savedRange = 'range';
|
||||
this.annotator.onEditorSubmit();
|
||||
expect(Annotator.Util.readRangeViaSelection).not.toHaveBeenCalled();
|
||||
expect(this.plugin.savedRange).toBeNull();
|
||||
expect(this.plugin.restoreSelection).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should do nothing if it is not a shortcut', function () {
|
||||
triggerEvent(this.element, {ctrlKey: false});
|
||||
expect(this.annotator.showEditor).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should do nothing if empty selection', function () {
|
||||
this.annotator.getSelectedRanges.andReturn([]);
|
||||
triggerEvent(this.element);
|
||||
expect(this.annotator.showEditor).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should do nothing if selection is in Annotator', function () {
|
||||
spyOn(this.annotator, 'isAnnotator').andReturn(true);
|
||||
triggerEvent(this.element);
|
||||
expect(this.annotator.showEditor).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user