2019-09-15 11:31:23 +00:00
|
|
|
class MockAnalytics {
|
|
|
|
EVENT_CATEGORIES = {};
|
|
|
|
|
|
|
|
sendEvent() {}
|
|
|
|
}
|
|
|
|
|
|
|
|
var analytics;
|
2018-05-29 21:53:35 +00:00
|
|
|
|
2019-09-15 11:31:23 +00:00
|
|
|
describe('TABS.cli', () => {
|
2018-05-29 21:53:35 +00:00
|
|
|
function toArrayBuffer(string) {
|
|
|
|
var bufferOut = new ArrayBuffer(string.length);
|
|
|
|
var bufView = new Uint8Array(bufferOut);
|
|
|
|
|
|
|
|
for (var i = 0; i < string.length; i++) {
|
|
|
|
bufView[i] = string.charCodeAt(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
return bufferOut;
|
|
|
|
}
|
|
|
|
|
|
|
|
describe('output', () => {
|
|
|
|
const cliTab = $('<div>').addClass('tab-cli');
|
|
|
|
const cliOutput = $('<div>').addClass('wrapper')
|
2019-04-11 10:30:13 +00:00
|
|
|
const cliPrompt = $('<textarea name="commands">');
|
2018-05-29 21:53:35 +00:00
|
|
|
|
|
|
|
cliTab.append($('<div>').addClass('window').append(cliOutput));
|
|
|
|
cliTab.append(cliPrompt);
|
|
|
|
|
2019-03-23 23:21:52 +00:00
|
|
|
CliAutoComplete.setEnabled(false); // not testing the client-side autocomplete
|
|
|
|
|
2018-05-29 21:53:35 +00:00
|
|
|
before(() => {
|
2019-09-15 11:31:23 +00:00
|
|
|
analytics = new MockAnalytics();
|
|
|
|
|
2018-05-29 21:53:35 +00:00
|
|
|
$('body')
|
|
|
|
.append(cliTab);
|
|
|
|
|
|
|
|
CONFIGURATOR.cliValid = true;
|
|
|
|
});
|
|
|
|
|
|
|
|
after(() => cliTab.remove());
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
cliOutput.empty();
|
|
|
|
cliPrompt.val('');
|
|
|
|
TABS.cli.cliBuffer = "";
|
|
|
|
});
|
|
|
|
|
|
|
|
it('ambiguous auto-complete results', () => {
|
2018-06-02 12:14:56 +00:00
|
|
|
TABS.cli.cliBuffer = 'se';
|
|
|
|
|
2018-05-29 21:53:35 +00:00
|
|
|
TABS.cli.read({
|
|
|
|
data: toArrayBuffer('\r\033[Kserialpassthrough\tservo\r\n# ser')
|
|
|
|
});
|
|
|
|
|
2018-06-01 16:46:10 +00:00
|
|
|
// Ambigous auto-complete from firmware is preceded with an \r carriage return
|
2018-06-02 12:14:56 +00:00
|
|
|
// which only renders a line break on Mac
|
2018-06-03 09:37:55 +00:00
|
|
|
const expectedValue = GUI.operating_system !== "Windows" ?
|
2018-06-02 12:14:56 +00:00
|
|
|
'se<br>serialpassthrough\tservo<br>' :
|
|
|
|
'seserialpassthrough\tservo<br>';
|
2018-06-01 16:46:10 +00:00
|
|
|
expect(cliOutput.html()).to.equal(expectedValue);
|
2018-05-29 21:53:35 +00:00
|
|
|
expect(cliPrompt.val()).to.equal('ser');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('unambiguous auto-complete result', () => {
|
|
|
|
TABS.cli.read({
|
2018-06-01 15:12:17 +00:00
|
|
|
data: toArrayBuffer('serialpassthrough')
|
2018-05-29 21:53:35 +00:00
|
|
|
});
|
|
|
|
|
2018-06-01 15:12:17 +00:00
|
|
|
expect(cliOutput.html()).to.equal('');
|
|
|
|
expect(cliPrompt.val()).to.equal('serialpassthrough');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('unambiguous auto-complete result with partial buffer', () => {
|
|
|
|
TABS.cli.cliBuffer = 'serial';
|
|
|
|
|
|
|
|
TABS.cli.read({
|
|
|
|
data: toArrayBuffer('passthrough')
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(cliOutput.html()).to.equal('');
|
2018-05-29 21:53:35 +00:00
|
|
|
expect(cliPrompt.val()).to.equal('serialpassthrough');
|
|
|
|
});
|
|
|
|
|
2019-11-06 14:49:00 +00:00
|
|
|
it("escape characters are skipped", () => {
|
2018-05-29 21:53:35 +00:00
|
|
|
TABS.cli.read({
|
|
|
|
data: toArrayBuffer('\033[K')
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(cliOutput.html()).to.equal('');
|
|
|
|
expect(cliPrompt.val()).to.equal('');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
function triggerEnterKey(input) {
|
|
|
|
const enterKeycode = 13;
|
|
|
|
const event = $.Event("keypress");
|
|
|
|
event.which = enterKeycode;
|
|
|
|
input.trigger(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
function triggerTabKey(input) {
|
|
|
|
const tabKeycode = 9;
|
|
|
|
const event = $.Event("keydown");
|
|
|
|
event.which = tabKeycode;
|
|
|
|
input.trigger(event);
|
|
|
|
}
|
|
|
|
|
2018-06-02 12:14:56 +00:00
|
|
|
const backspaceCode = String.fromCharCode(127);
|
|
|
|
|
2018-05-29 21:53:35 +00:00
|
|
|
describe('input', () => {
|
|
|
|
const content = $('<div>').attr('id', 'content');
|
|
|
|
const cliTab = $('<div>').addClass('tab-cli');
|
2019-04-11 10:30:13 +00:00
|
|
|
const cliPrompt = $('<textarea name="commands">');
|
2018-05-29 21:53:35 +00:00
|
|
|
cliTab.append(cliPrompt);
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
$('body')
|
|
|
|
.append(content);
|
|
|
|
|
|
|
|
// Stub loading of template.
|
|
|
|
sinon.stub($.fn, 'load').callsFake((file, callback) => {
|
|
|
|
content.append(cliTab);
|
|
|
|
callback();
|
|
|
|
});
|
|
|
|
sinon.stub(TABS.cli, 'send');
|
|
|
|
sinon.stub(Promise, 'reduce').callsFake((items, cb, initialValue) => {
|
|
|
|
items.forEach((line, idx) => cb(0, line, idx));
|
|
|
|
});
|
|
|
|
sinon.stub(window, 'Promise').callsFake(resolve => resolve(0));
|
|
|
|
sinon.stub(GUI, 'timeout_add').withArgs('CLI_send_slowly')
|
|
|
|
.callsFake((name, cb) => {
|
|
|
|
cb();
|
|
|
|
});
|
|
|
|
|
|
|
|
TABS.cli.cliBuffer = "";
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
content.remove();
|
|
|
|
$.fn.load.restore();
|
|
|
|
TABS.cli.send.restore();
|
|
|
|
Promise.reduce.restore();
|
|
|
|
Promise.restore();
|
|
|
|
GUI.timeout_add.restore();
|
|
|
|
});
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
cliPrompt.val('');
|
|
|
|
content.empty();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('tab key triggers serial message with appended tab char', done => {
|
|
|
|
TABS.cli.initialize(() => {
|
|
|
|
cliPrompt.val('serial');
|
|
|
|
|
|
|
|
triggerTabKey(cliPrompt);
|
|
|
|
|
|
|
|
expect(TABS.cli.send).to.have.been.calledOnce;
|
|
|
|
expect(TABS.cli.send).to.have.been.calledWith('serial\t');
|
|
|
|
done()
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('second auto complete in row', done => {
|
|
|
|
TABS.cli.initialize(() => {
|
2018-06-01 15:12:17 +00:00
|
|
|
TABS.cli.cliBuffer = '# ser';
|
|
|
|
|
2018-05-29 21:53:35 +00:00
|
|
|
cliPrompt.val('seri');
|
|
|
|
|
|
|
|
triggerTabKey(cliPrompt);
|
|
|
|
|
|
|
|
expect(TABS.cli.send).to.have.been.calledOnce;
|
|
|
|
expect(TABS.cli.send).to.have.been.calledWith('i\t');
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('auto-complete command with trailing space', done => {
|
|
|
|
TABS.cli.initialize(() => {
|
2018-06-01 15:12:17 +00:00
|
|
|
TABS.cli.cliBuffer = '# get ';
|
|
|
|
|
2018-05-29 21:53:35 +00:00
|
|
|
cliPrompt.val('get r');
|
|
|
|
|
|
|
|
triggerTabKey(cliPrompt);
|
|
|
|
|
|
|
|
expect(TABS.cli.send).to.have.been.calledOnce;
|
|
|
|
expect(TABS.cli.send).to.have.been.calledWith('r\t');
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('auto-complete after delete characters', done => {
|
|
|
|
TABS.cli.initialize(() => {
|
2018-06-01 15:12:17 +00:00
|
|
|
TABS.cli.cliBuffer = '# serial';
|
|
|
|
|
2018-05-29 21:53:35 +00:00
|
|
|
cliPrompt.val('ser');
|
|
|
|
|
|
|
|
triggerTabKey(cliPrompt);
|
|
|
|
|
|
|
|
expect(TABS.cli.send).to.have.been.calledOnce;
|
2018-06-02 12:14:56 +00:00
|
|
|
expect(TABS.cli.send).to.have.been.calledWith(backspaceCode.repeat(3) + '\t');
|
2018-05-29 21:53:35 +00:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('enter after autocomplete', done => {
|
|
|
|
TABS.cli.initialize(() => {
|
2018-06-01 15:12:17 +00:00
|
|
|
TABS.cli.cliBuffer = '# servo';
|
|
|
|
|
2018-05-29 21:53:35 +00:00
|
|
|
cliPrompt.val('servo');
|
|
|
|
|
|
|
|
triggerEnterKey(cliPrompt);
|
|
|
|
|
|
|
|
expect(TABS.cli.send).to.have.been.calledOnce;
|
|
|
|
expect(TABS.cli.send).to.have.been.calledWith('\n');
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('enter after autocomplete', done => {
|
|
|
|
TABS.cli.initialize(() => {
|
2018-06-01 15:12:17 +00:00
|
|
|
TABS.cli.cliBuffer = '# ser';
|
|
|
|
|
2018-05-29 21:53:35 +00:00
|
|
|
cliPrompt.val('servo');
|
|
|
|
|
|
|
|
triggerEnterKey(cliPrompt);
|
|
|
|
|
|
|
|
expect(TABS.cli.send).to.have.been.calledOnce;
|
|
|
|
expect(TABS.cli.send).to.have.been.calledWith('vo\n');
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('enter after deleting characters', done => {
|
|
|
|
TABS.cli.initialize(() => {
|
2018-06-01 15:12:17 +00:00
|
|
|
TABS.cli.cliBuffer = '# serial';
|
|
|
|
|
2018-05-29 21:53:35 +00:00
|
|
|
cliPrompt.val('ser');
|
|
|
|
|
|
|
|
triggerEnterKey(cliPrompt);
|
|
|
|
|
|
|
|
expect(TABS.cli.send).to.have.been.calledOnce;
|
2018-06-02 12:14:56 +00:00
|
|
|
expect(TABS.cli.send).to.have.been.calledWith(backspaceCode.repeat(3) + '\n');
|
2018-05-29 21:53:35 +00:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2018-06-01 15:12:17 +00:00
|
|
|
|
2018-06-02 12:14:56 +00:00
|
|
|
it('cliBuffer is cleared on startup', done => {
|
2018-06-01 15:12:17 +00:00
|
|
|
TABS.cli.cliBuffer = '# serial';
|
|
|
|
|
|
|
|
TABS.cli.initialize(() => {
|
|
|
|
expect(TABS.cli.cliBuffer).to.equal('');
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2018-06-02 12:14:56 +00:00
|
|
|
|
|
|
|
it('exit upon cleanup clears cliBuffer first', done => {
|
|
|
|
CONFIGURATOR.connectionValid = true;
|
|
|
|
TABS.cli.cliValid = true;
|
|
|
|
|
|
|
|
|
|
|
|
TABS.cli.initialize(() => {
|
|
|
|
const commandInBuffer = 'resource';
|
|
|
|
|
|
|
|
TABS.cli.cliBuffer = `# ${commandInBuffer}`;
|
|
|
|
|
|
|
|
TABS.cli.cleanup();
|
|
|
|
|
|
|
|
expect(TABS.cli.send).to.have.been.calledOnce;
|
|
|
|
expect(TABS.cli.send).to.have.been.calledWith(backspaceCode.repeat(commandInBuffer.length) + 'exit\r');
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2018-05-29 21:53:35 +00:00
|
|
|
});
|
|
|
|
});
|