test/textcomplete.codemirror_spec.js
require('./test_helper');
import CodeMirror from '../src/textcomplete.codemirror';
import isNumber from 'lodash.isnumber';
const assert = require('power-assert');
describe('CodeMirror', function () {
var cm, editor;
beforeEach(function () {
var cursorDiv = document.createElement('div');
cursorDiv.appendChild(document.createElement('div'));
cm = {
display: {cursorDiv},
doc: {
getCursor: function () { return { line: 0, ch: 0 }; },
getValue: function () { return ''; },
lineSeparator: function () { return '\n'; },
setCursor: function () {},
setValue: function () {},
},
focus: function () {},
on: function () {},
off: function () {},
};
editor = new CodeMirror(cm);
});
context('when keydown event occurs', function () {
var event;
beforeEach(function () {
event = document.createEvent('UIEvents');
event.initEvent('keydown', true, true);
});
function subject() {
return editor.onKeydown(cm, event);
}
[
[38, 'UP', false, 'up'],
[40, 'DOWN', false, 'down'],
[78, 'DOWN', true, 'ctrl-n'],
[80, 'UP', true, 'ctrl-p'],
].forEach(([keyCode, code, ctrlKey, name]) => {
context(`and it is a ${name} key`, function () {
beforeEach(function () {
event.keyCode = keyCode;
event.ctrlKey = ctrlKey;
});
it(`should emit a ${code} move event`, function () {
var spy = this.sinon.spy();
editor.on('move', spy);
subject();
assert(spy.calledOnce);
assert(spy.args[0][0].detail.code === code);
});
it('should prevent the keydown event when move event is prevented', function () {
editor.on('move', e => { e.preventDefault(); });
subject();
assert(event.defaultPrevented);
});
});
});
[[9, 'tab'], [13, 'enter']].forEach(([keyCode, name]) => {
context(`and it is a ${name} key`, function () {
beforeEach(function () {
event.keyCode = keyCode;
});
it('should emit a enter event', function () {
var spy = this.sinon.spy();
editor.on('enter', spy);
subject();
assert(spy.calledOnce);
});
});
});
context('and it is a normal key', function () {
beforeEach(function () {
event.keyCode = 65;
});
it('should not emit a move event', function () {
var spy = this.sinon.spy();
editor.on('move', spy);
subject();
assert(!spy.called);
});
});
});
context('when keyup event occurs', function () {
var event;
function subject() {
return editor.onKeyup(cm, event);
}
beforeEach(function () {
event = document.createEvent('UIEvents');
event.initEvent('keyup', true, true);
});
context('and it is a move key', function () {
beforeEach(function () {
event.keyCode = 40; // down
});
it('should not emit a change event', function () {
var spy = this.sinon.spy();
editor.on('change', spy);
subject();
assert(!spy.called);
});
});
context('and it is not a move key', function () {
beforeEach(function () {
event.keyCode = 65;
});
it('should emit a change event', function () {
cm.doc.getValue = function () {
return 'hello world';
};
cm.doc.getCursor = function () {
return { line: 0, ch: 3 };
};
var spy = this.sinon.spy();
editor.on('change', spy);
subject();
assert(spy.calledOnce);
assert(spy.args[0][0].detail.beforeCursor === 'hel');
});
});
});
describe('#destroy', function () {
function subject() {
return editor.destroy();
}
it('should return itself', function () {
assert.strictEqual(subject(), editor);
});
});
describe('#applySearchResult', function () {
var searchResult;
function subject() {
return editor.applySearchResult(searchResult);
}
context('when searchResult.replace returns an array', function () {
beforeEach(function () {
searchResult = { replace: function () { return ['hello', 'world']; } };
});
it('should not throw error', function () {
subject();
});
});
context('when searchResult.replace returns null', function () {
beforeEach(function () {
searchResult = { replace: function () { return null; } };
});
it('should not throw error', function () {
subject();
});
});
});
describe('#getCursorOffset', function () {
function subject() {
return editor.getCursorOffset();
}
it('should return an object with top and left number properties', function () {
var result = subject();
assert(isNumber(result.top));
assert(isNumber(result.left));
});
});
describe('#getBeforeCursor', function () {
beforeEach(function () {
cm.doc.getCursor = function () {
return { line: 1, ch: 2 };
};
cm.doc.getValue = function () {
return 'hello\ntextcomplete\ncodemirror!';
};
});
function subject() {
return editor.getBeforeCursor();
}
it('should return string between head to cursor', function () {
assert.equal(subject(), 'hello\nte');
});
});
describe('#getAfterCursor', function () {
beforeEach(function () {
cm.doc.getCursor = function () {
return { line: 1, ch: 2 };
};
cm.doc.getValue = function () {
return 'hello\ntextcomplete\ncodemirror!';
};
});
function subject() {
return editor.getAfterCursor();
}
it('should return string between cursor to tail', function () {
assert.equal(subject(), 'xtcomplete\ncodemirror!');
});
});
});