diff --git a/package.json b/package.json index 58e6eb3a..91b2fcd1 100644 --- a/package.json +++ b/package.json @@ -98,6 +98,7 @@ "karma-mocha": "^1.3.0", "karma-sinon": "^1.0.5", "karma-sinon-chai": "^2.0.2", + "karma-spec-reporter": "^0.0.32", "karma-tfs-reporter": "^1.0.2", "mocha": "^7.0.1", "nw-builder": "^3.5.7", diff --git a/src/js/CliAutoComplete.js b/src/js/CliAutoComplete.js index 48cd7264..0b824f21 100644 --- a/src/js/CliAutoComplete.js +++ b/src/js/CliAutoComplete.js @@ -6,17 +6,17 @@ * Uses: https://github.com/yuku/jquery-textcomplete * Check out the docs at https://github.com/yuku/jquery-textcomplete/tree/v1/doc */ -var CliAutoComplete = { +const CliAutoComplete = { configEnabled: false, builder: { state: 'reset', numFails: 0 }, }; CliAutoComplete.isEnabled = function() { - return this.isBuilding() || (this.configEnabled && FC.CONFIG.flightControllerIdentifier == "BTFL" && this.builder.state != 'fail'); + return this.isBuilding() || (this.configEnabled && FC.CONFIG.flightControllerIdentifier === "BTFL" && this.builder.state !== 'fail'); }; CliAutoComplete.isBuilding = function() { - return this.builder.state != 'reset' && this.builder.state != 'done' && this.builder.state != 'fail'; + return this.builder.state !== 'reset' && this.builder.state !== 'done' && this.builder.state !== 'fail'; }; CliAutoComplete.isOpen = function() { @@ -27,7 +27,7 @@ CliAutoComplete.isOpen = function() { * @param {boolean} force - Forces AutoComplete to be shown even if the matching strategy has less that minChars input */ CliAutoComplete.openLater = function(force) { - var self = this; + const self = this; setTimeout(function() { self.forceOpen = !!force; self.$textarea.textcomplete('trigger'); @@ -36,7 +36,7 @@ CliAutoComplete.openLater = function(force) { }; CliAutoComplete.setEnabled = function(enable) { - if (this.configEnabled != enable) { + if (this.configEnabled !== enable) { this.configEnabled = enable; if (CONFIGURATOR.cliActive && CONFIGURATOR.cliValid) { @@ -67,12 +67,13 @@ CliAutoComplete.cleanup = function() { }; CliAutoComplete._builderWatchdogTouch = function() { - var self = this; + const self = this; this._builderWatchdogStop(); GUI.timeout_add('autocomplete_builder_watchdog', function() { - if (self.builder.numFails++) { + if (self.builder.numFails) { + self.builder.numFails++; self.builder.state = 'fail'; self.writeToOutput('Failed!
# '); $(self).trigger('build:stop'); @@ -89,7 +90,7 @@ CliAutoComplete._builderWatchdogStop = function() { }; CliAutoComplete.builderStart = function() { - if (this.builder.state == 'reset') { + if (this.builder.state === 'reset') { this.cache = { commands: [], resources: [], @@ -98,7 +99,7 @@ CliAutoComplete.builderStart = function() { settingsAcceptedValues: {}, feature: [], beeper: ['ALL'], - mixers: [] + mixers: [], }; this.builder.commandSequence = ['help', 'dump', 'get', 'mixer list']; this.builder.currentSetting = null; @@ -111,15 +112,14 @@ CliAutoComplete.builderStart = function() { }; CliAutoComplete.builderParseLine = function(line) { - var cache = this.cache; - var builder = this.builder; - var m; + const cache = this.cache; + const builder = this.builder; this._builderWatchdogTouch(); if (line.indexOf(builder.sentinel) !== -1) { // got sentinel - var command = builder.commandSequence.shift(); + const command = builder.commandSequence.shift(); if (command && this.configEnabled) { // next state @@ -150,39 +150,49 @@ CliAutoComplete.builderParseLine = function(line) { } else { switch (builder.state) { case 'parse-help': - if (m = line.match(/^(\w+)/)) { - cache.commands.push(m[1]); + const matchHelp = line.match(/^(\w+)/); + if (matchHelp) { + cache.commands.push(matchHelp[1]); } break; case 'parse-dump': - if (m = line.match(/^resource\s+(\w+)/i)) { - var r = m[1].toUpperCase(); // should alread be upper, but to be sure, since we depend on that later + const matchDump = line.match(/^resource\s+(\w+)/i); + if (matchDump) { + const r = matchDump[1].toUpperCase(); // should alread be upper, but to be sure, since we depend on that later cache.resourcesCount[r] = (cache.resourcesCount[r] || 0) + 1; - } else if (m = line.match(/^(feature|beeper)\s+-?(\w+)/i)) { - cache[m[1].toLowerCase()].push(m[2]); + } else { + const matchFeatBeep = line.match(/^(feature|beeper)\s+-?(\w+)/i); + if (matchFeatBeep) { + cache[matchFeatBeep[1].toLowerCase()].push(matchFeatBeep[2]); + } } break; case 'parse-get': - if (m = line.match(/^(\w+)\s*=/)) { + const matchGet = line.match(/^(\w+)\s*=/); + if (matchGet) { // setting name - cache.settings.push(m[1]); - builder.currentSetting = m[1].toLowerCase(); - } else if (builder.currentSetting && (m = line.match(/^(.*): (.*)/))) { - if (m[1].match(/values/i)) { - // Allowed Values - cache.settingsAcceptedValues[builder.currentSetting] = m[2].split(/\s*,\s*/).sort(); - } else if (m[1].match(/range|length/i)){ - // "Allowed range" or "Array length", store as string hint - cache.settingsAcceptedValues[builder.currentSetting] = m[0]; + cache.settings.push(matchGet[1]); + builder.currentSetting = matchGet[1].toLowerCase(); + } else { + const matchGetSettings = line.match(/^(.*): (.*)/); + if (matchGetSettings !== null && builder.currentSetting) { + if (matchGetSettings[1].match(/values/i)) { + // Allowed Values + cache.settingsAcceptedValues[builder.currentSetting] = matchGetSettings[2].split(/\s*,\s*/).sort(); + } else if (matchGetSettings[1].match(/range|length/i)){ + // "Allowed range" or "Array length", store as string hint + cache.settingsAcceptedValues[builder.currentSetting] = matchGetSettings[0]; + } } } break; case 'parse-mixer list': - if (m = line.match(/:(.+)/)) { - cache.mixers = ['list'].concat(m[1].trim().split(/\s+/)); + const matchMixer = line.match(/:(.+)/); + if (matchMixer) { + cache.mixers = ['list'].concat(matchMixer[1].trim().split(/\s+/)); } break; } @@ -193,29 +203,31 @@ CliAutoComplete.builderParseLine = function(line) { * Initializes textcomplete with all the autocomplete strategies */ CliAutoComplete._initTextcomplete = function() { - var sendOnEnter = false; - var self = this; - var $textarea = this.$textarea; - var cache = self.cache; + let sendOnEnter = false; + const self = this; + const $textarea = this.$textarea; + const cache = self.cache; - var savedMouseoverItemHandler = null; + let savedMouseoverItemHandler = null; // helper functions - var highlighter = function(anywhere) { + const highlighter = function(anywhere) { return function(value, term) { - return term ? value.replace(new RegExp((anywhere?'':'^') + '('+term+')', 'gi'), '$1') : value; + const anywherePrefix = anywhere ? '': '^'; + const termValue = value.replace(new RegExp(`${anywherePrefix}(${term})`, 'gi'), '$1'); + return term ? termValue : value; }; }; - var highlighterAnywhere = highlighter(true); - var highlighterPrefix = highlighter(false); + const highlighterAnywhere = highlighter(true); + const highlighterPrefix = highlighter(false); - var searcher = function(term, callback, array, minChars, matchPrefix) { - var res = []; + const searcher = function(term, callback, array, minChars, matchPrefix) { + const res = []; if ((minChars !== false && term.length >= minChars) || self.forceOpen || self.isOpen()) { term = term.toLowerCase(); - for (var i = 0; i < array.length; i++) { - var v = array[i].toLowerCase(); + for (let i = 0; i < array.length; i++) { + const v = array[i].toLowerCase(); if (matchPrefix && v.startsWith(term) || !matchPrefix && v.indexOf(term) !== -1) { res.push(array[i]); } @@ -224,24 +236,24 @@ CliAutoComplete._initTextcomplete = function() { callback(res); - if (self.forceOpen && res.length == 1) { + if (self.forceOpen && res.length === 1) { // hacky: if we came here because of Tab and there's only one match // trigger Tab again, so that textcomplete should immediately select the only result // instead of showing the menu - $textarea.trigger($.Event('keydown', {keyCode:9})) + $textarea.trigger($.Event('keydown', {keyCode:9})); } }; - var contexter = function(text) { - var val = $textarea.val(); - if (val.length == text.length || val[text.length].match(/\s/)) { + const contexter = function(text) { + const val = $textarea.val(); + if (val.length === text.length || val[text.length].match(/\s/)) { return true; } return false; // do not show autocomplete if in the middle of a word }; - var basicReplacer = function(value) { - return '$1' + value + ' '; + const basicReplacer = function(value) { + return `$1${value} `; }; // end helper functions @@ -255,18 +267,18 @@ CliAutoComplete._initTextcomplete = function() { onKeydown: function(e) { // some strategies may set sendOnEnter only at the replace stage, thus we call with timeout // since this handler [onKeydown] is triggered before replace() - if (e.which == 13) { + if (e.which === 13) { setTimeout(function() { if (sendOnEnter) { // fake "enter" to run the textarea's handler - $textarea.trigger($.Event('keypress', {which:13})) + $textarea.trigger($.Event('keypress', {which:13})); } }, 0); } - } + }, } ) - .on('textComplete:show', function(e) { + .on('textComplete:show', function() { /** * The purpose of this code is to disable initially the `mouseover` menu item handler. * Normally, when the menu pops up, if the mouse cursor is in the same area, @@ -299,12 +311,12 @@ CliAutoComplete._initTextcomplete = function() { // textcomplete autocomplete strategies // strategy builder helper - var strategy = function(s) { + const strategy = function(s) { return $.extend({ template: highlighterAnywhere, replace: basicReplacer, context: contexter, - index: 2 + index: 2, }, s); }; @@ -329,7 +341,7 @@ CliAutoComplete._initTextcomplete = function() { } callback(arr); }, cache.settings, 3); - } + }, }), strategy({ // "set" @@ -337,7 +349,7 @@ CliAutoComplete._initTextcomplete = function() { search: function(term, callback) { sendOnEnter = false; searcher(term, callback, cache.settings, 3); - } + }, }), strategy({ // "set =" @@ -349,24 +361,24 @@ CliAutoComplete._initTextcomplete = function() { replace: function(value) { self.openLater(); return basicReplacer(value); - } + }, }), strategy({ // "set with value" match: /^(\s*set\s+(\w+))\s*=\s*(.*)$/i, search: function(term, callback, match) { - var arr = []; - var settingName = match[2].toLowerCase(); + const arr = []; + const settingName = match[2].toLowerCase(); this.isSettingValueArray = false; this.value = match[3]; sendOnEnter = !!term; if (settingName in cache.settingsAcceptedValues) { - var val = cache.settingsAcceptedValues[settingName]; + const val = cache.settingsAcceptedValues[settingName]; if (Array.isArray(val)) { // setting uses lookup strings - this.isSettingValueArray = true + this.isSettingValueArray = true; sendOnEnter = true; searcher(term, callback, val, 0); return; @@ -389,14 +401,14 @@ CliAutoComplete._initTextcomplete = function() { return '$1 = ' + value; // cosmetic - make sure we have spaces around the `=` }, index: 3, - isSettingValueArray: false + isSettingValueArray: false, }), strategy({ // "resource" match: /^(\s*resource\s+)(\w*)$/i, - search: function(term, callback, match) { + search: function(term, callback) { sendOnEnter = false; - var arr = cache.resources; + let arr = cache.resources; if (semver.gte(FC.CONFIG.flightControllerVersion, "4.0.0")) { arr = ['show'].concat(arr); } else { @@ -407,11 +419,11 @@ CliAutoComplete._initTextcomplete = function() { replace: function(value) { if (value in cache.resourcesCount) { self.openLater(); - } else if (value == 'list' || value == 'show') { + } else if (value === 'list' || value === 'show') { sendOnEnter = true; } return basicReplacer(value); - } + }, }), strategy({ // "resource index" @@ -419,29 +431,30 @@ CliAutoComplete._initTextcomplete = function() { search: function(term, callback, match) { sendOnEnter = false; this.savedTerm = term; - callback(['<1-' + cache.resourcesCount[match[2].toUpperCase()] + '>']); + callback([`<1-${cache.resourcesCount[match[2].toUpperCase()]}>`]); }, - replace: function(value) { + replace: function() { if (this.savedTerm) { self.openLater(); return '$1$3 '; } + return null; }, context: function(text) { - var m; + const matchResource = text.match(/^\s*resource\s+(\w+)\s/i); // use this strategy only for resources with more than one index - if ((m = text.match(/^\s*resource\s+(\w+)\s/i)) && (cache.resourcesCount[m[1].toUpperCase()] || 0) > 1 ) { + if (matchResource && (cache.resourcesCount[matchResource[1].toUpperCase()] || 0) > 1 ) { return contexter(text); } return false; }, index: 3, - savedTerm: null + savedTerm: null, }), strategy({ // "resource pin" match: /^(\s*resource\s+\w+\s+(\d*\s+)?)(\w*)$/i, - search: function(term, callback, match) { + search: function(term, callback) { sendOnEnter = !!term; if (term) { if ('none'.startsWith(term)) { @@ -454,78 +467,79 @@ CliAutoComplete._initTextcomplete = function() { } }, template: function(value, term) { - if (value == 'none') { + if (value === 'none') { return highlighterPrefix(value, term); } return value; }, replace: function(value) { - if (value == 'none') { + if (value === 'none') { sendOnEnter = true; return '$1none '; } + return null; }, context: function(text) { - var m = text.match(/^\s*resource\s+(\w+)\s+(\d+\s)?/i); + const m = text.match(/^\s*resource\s+(\w+)\s+(\d+\s)?/i); if (m) { // show pin/none for resources having only one index (it's not needed at the commend line) // OR having more than one index and the index is supplied at the command line - var count = cache.resourcesCount[m[1].toUpperCase()] || 0; + const count = cache.resourcesCount[m[1].toUpperCase()] || 0; if (count && (m[2] || count === 1)) { return contexter(text); } } return false; }, - index: 3 + index: 3, }), strategy({ // "feature" and "beeper" match: /^(\s*(feature|beeper)\s+(-?))(\w*)$/i, search: function(term, callback, match) { sendOnEnter = !!term; - var arr = cache[match[2].toLowerCase()]; + let arr = cache[match[2].toLowerCase()]; if (!match[3]) { arr = ['-', 'list'].concat(arr); } searcher(term, callback, arr, 1); }, replace: function(value) { - if (value == '-') { + if (value === '-') { self.openLater(true); return '$1-'; } return basicReplacer(value); }, - index: 4 + index: 4, }), strategy({ // "mixer" match: /^(\s*mixer\s+)(\w*)$/i, - search: function(term, callback, match) { + search: function(term, callback) { sendOnEnter = true; searcher(term, callback, cache.mixers, 1); - } - }) + }, + }), ]); if (semver.gte(FC.CONFIG.flightControllerVersion, "4.0.0")) { $textarea.textcomplete('register', [ strategy({ // "resource show all", from BF 4.0.0 onwards match: /^(\s*resource\s+show\s+)(\w*)$/i, - search: function(term, callback, matches) { + search: function(term, callback) { sendOnEnter = true; searcher(term, callback, ['all'], 1, true); }, - template: highlighterPrefix + template: highlighterPrefix, }), ]); } // diff command - var diffArgs1 = ["master", "profile", "rates", "all"]; - var diffArgs2 = []; + const diffArgs1 = ["master", "profile", "rates", "all"]; + const diffArgs2 = []; if (semver.lt(FC.CONFIG.flightControllerVersion, "3.4.0")) { diffArgs2.push("showdefaults"); @@ -544,20 +558,20 @@ CliAutoComplete._initTextcomplete = function() { $textarea.textcomplete('register', [ strategy({ // "diff arg1" match: /^(\s*diff\s+)(\w*)$/i, - search: function(term, callback, match) { + search: function(term, callback) { sendOnEnter = true; searcher(term, callback, diffArgs1, 1, true); }, - template: highlighterPrefix + template: highlighterPrefix, }), strategy({ // "diff arg1 arg2" match: /^(\s*diff\s+\w+\s+)(\w*)$/i, - search: function(term, callback, match) { + search: function(term, callback) { sendOnEnter = true; searcher(term, callback, diffArgs2, 1, true); }, - template: highlighterPrefix - }) + template: highlighterPrefix, + }), ]); }; diff --git a/src/js/tabs/cli.js b/src/js/tabs/cli.js index 50b39280..dae3ff1f 100644 --- a/src/js/tabs/cli.js +++ b/src/js/tabs/cli.js @@ -7,6 +7,8 @@ TABS.cli = { cliBuffer: "", GUI: { snippetPreviewWindow: null, + copyButton: null, + windowWrapper: null, }, }; @@ -15,8 +17,8 @@ function removePromptHash(promptText) { } function cliBufferCharsToDelete(command, buffer) { - var commonChars = 0; - for (var i = 0;i < buffer.length;i++) { + let commonChars = 0; + for (let i = 0; i < buffer.length; i++) { if (command[i] === buffer[i]) { commonChars++; } else { @@ -46,8 +48,9 @@ function getCliCommand(command, cliBuffer) { function copyToClipboard(text) { function onCopySuccessful() { + analytics.sendEvent(analytics.EVENT_CATEGORIES.FLIGHT_CONTROLLER, 'CliCopyToClipboard', text.length); - const button = $('.tab-cli .copy'); + const button = self.GUI.copyButton; const origText = button.text(); const origWidth = button.css("width"); button.text(i18n.getMessage("cliCopySuccessful")); @@ -72,25 +75,25 @@ function copyToClipboard(text) { } TABS.cli.initialize = function (callback) { - var self = this; + const self = this; - if (GUI.active_tab != 'cli') { + if (GUI.active_tab !== 'cli') { GUI.active_tab = 'cli'; } - + self.outputHistory = ""; self.cliBuffer = ""; const enterKeyCode = 13; - function executeCommands(out_string) { - self.history.add(out_string.trim()); + function executeCommands(outString) { + self.history.add(outString.trim()); - var outputArray = out_string.split("\n"); + const outputArray = outString.split("\n"); Promise.reduce(outputArray, function(delay, line, index) { return new Promise(function (resolve) { GUI.timeout_add('CLI_send_slowly', function () { - var processingDelay = self.lineDelayMs; + let processingDelay = self.lineDelayMs; line = line.trim(); if (line.toLowerCase().startsWith('profile')) { processingDelay = self.profileSwitchDelayMs; @@ -102,8 +105,8 @@ TABS.cli.initialize = function (callback) { self.sendLine(line, function () { resolve(processingDelay); }); - }, delay) - }) + }, delay); + }); }, 0); } @@ -115,7 +118,10 @@ TABS.cli.initialize = function (callback) { CONFIGURATOR.cliActive = true; - var textarea = $('.tab-cli textarea[name="commands"]'); + self.GUI.copyButton = $('.tab-cli .copy'); + self.GUI.windowWrapper = $('.tab-cli .window .wrapper'); + + const textarea = $('.tab-cli textarea[name="commands"]'); CliAutoComplete.initialize(textarea, self.sendLine.bind(self), writeToOutput); $(CliAutoComplete).on('build:start', function() { @@ -132,12 +138,12 @@ TABS.cli.initialize = function (callback) { }); $('.tab-cli .save').click(function() { - var prefix = 'cli'; - var suffix = 'txt'; + const prefix = 'cli'; + const suffix = 'txt'; - var filename = generateFilename(prefix, suffix); + const filename = generateFilename(prefix, suffix); - var accepts = [{ + const accepts = [{ description: suffix.toUpperCase() + ' files', extensions: [suffix], }]; @@ -176,19 +182,19 @@ TABS.cli.initialize = function (callback) { $('.tab-cli .clear').click(function() { self.outputHistory = ""; - $('.tab-cli .window .wrapper').empty(); + self.GUI.windowWrapper.empty(); }); if (Clipboard.available) { - $('.tab-cli .copy').click(function() { + self.GUI.copyButton.click(function() { copyToClipboard(self.outputHistory); }); } else { - $('.tab-cli .copy').hide(); + self.GUI.copyButton.hide(); } $('.tab-cli .load').click(function() { - var accepts = [ + const accepts = [ { description: 'Config files', extensions: ["txt", "config"], }, @@ -207,8 +213,8 @@ TABS.cli.initialize = function (callback) { console.log('No file selected'); return; } - - let previewArea = $("#snippetpreviewcontent textarea#preview"); + + const previewArea = $("#snippetpreviewcontent textarea#preview"); function executeSnippet(fileName) { const commands = previewArea.val(); @@ -230,7 +236,7 @@ TABS.cli.initialize = function (callback) { isolateScroll: false, title: i18n.getMessage("cliConfirmSnippetDialogTitle", { fileName: fileName }), content: $('#snippetpreviewcontent'), - onCreated: () => + onCreated: () => $("#snippetpreviewcontent a.confirm").click(() => executeSnippet(fileName)) , }); @@ -240,8 +246,8 @@ TABS.cli.initialize = function (callback) { } entry.file((file) => { - let reader = new FileReader(); - reader.onload = + const reader = new FileReader(); + reader.onload = () => previewCommands(reader.result, file.name); reader.onerror = () => console.error(reader.error); reader.readAsText(file); @@ -253,7 +259,7 @@ TABS.cli.initialize = function (callback) { // `keypress`/`keyup` happens too late, as `textarea` will have already lost focus. textarea.keydown(function (event) { const tabKeyCode = 9; - if (event.which == tabKeyCode) { + if (event.which === tabKeyCode) { // prevent default tabbing behaviour event.preventDefault(); @@ -275,22 +281,22 @@ TABS.cli.initialize = function (callback) { }); textarea.keypress(function (event) { - if (event.which == enterKeyCode) { + if (event.which === enterKeyCode) { event.preventDefault(); // prevent the adding of new line if (CliAutoComplete.isBuilding()) { return; // silently ignore commands if autocomplete is still building } - var out_string = textarea.val(); - executeCommands(out_string); + const outString = textarea.val(); + executeCommands(outString); textarea.val(''); } }); textarea.keyup(function (event) { - var keyUp = {38: true}, - keyDown = {40: true}; + const keyUp = {38: true}; + const keyDown = {40: true}; if (CliAutoComplete.isOpen()) { return; // disable history keys if autocomplete is open @@ -310,8 +316,8 @@ TABS.cli.initialize = function (callback) { GUI.timeout_add('enter_cli', function enter_cli() { // Enter CLI mode - var bufferOut = new ArrayBuffer(1); - var bufView = new Uint8Array(bufferOut); + const bufferOut = new ArrayBuffer(1); + const bufView = new Uint8Array(bufferOut); bufView[0] = 0x23; // # @@ -335,7 +341,7 @@ TABS.cli.adaptPhones = function() { TABS.cli.history = { history: [], - index: 0 + index: 0, }; TABS.cli.history.add = function (str) { @@ -344,12 +350,16 @@ TABS.cli.history.add = function (str) { }; TABS.cli.history.prev = function () { - if (this.index > 0) this.index -= 1; + if (this.index > 0) { + this.index -= 1; + } return this.history[this.index]; }; TABS.cli.history.next = function () { - if (this.index < this.history.length) this.index += 1; + if (this.index < this.history.length) { + this.index += 1; + } return this.history[this.index - 1]; }; @@ -358,8 +368,9 @@ const lineFeedCode = 10; const carriageReturnCode = 13; function writeToOutput(text) { - $('.tab-cli .window .wrapper').append(text); - $('.tab-cli .window').scrollTop($('.tab-cli .window .wrapper').height()); + const windowWrapper = TABS.cli.GUI.windowWrapper; + windowWrapper.append(text); + $('.tab-cli .window').scrollTop(windowWrapper.height()); } function writeLineToOutput(text) { @@ -369,7 +380,7 @@ function writeLineToOutput(text) { } if (text.startsWith("###ERROR")) { - writeToOutput('' + text + '
'); + writeToOutput(`${text}
`); } else { writeToOutput(text + "
"); } @@ -390,11 +401,11 @@ TABS.cli.read = function (readInfo) { Windows understands (both) CRLF Chrome OS currently unknown */ - var data = new Uint8Array(readInfo.data), - validateText = "", - sequenceCharsToSkip = 0; + const data = new Uint8Array(readInfo.data); + let validateText = ""; + let sequenceCharsToSkip = 0; - for (var i = 0; i < data.length; i++) { + for (let i = 0; i < data.length; i++) { const currentChar = String.fromCharCode(data[i]); if (!CONFIGURATOR.cliValid) { @@ -406,7 +417,7 @@ TABS.cli.read = function (readInfo) { const escapeSequenceCode = 27; const escapeSequenceCharLength = 3; - if (data[i] == escapeSequenceCode && !sequenceCharsToSkip) { // ESC + other + if (data[i] === escapeSequenceCode && !sequenceCharsToSkip) { // ESC + other sequenceCharsToSkip = escapeSequenceCharLength; } @@ -448,7 +459,7 @@ TABS.cli.read = function (readInfo) { this.outputHistory += currentChar; } - if (this.cliBuffer == 'Rebooting') { + if (this.cliBuffer === 'Rebooting') { CONFIGURATOR.cliActive = false; CONFIGURATOR.cliValid = false; GUI.log(i18n.getMessage('cliReboot')); @@ -464,7 +475,6 @@ TABS.cli.read = function (readInfo) { // this is to match the content of the history with what the user sees on this tab const lastLine = validateText.split("\n").pop(); this.outputHistory = lastLine; - validateText = ""; if (CliAutoComplete.isEnabled() && !CliAutoComplete.isBuilding()) { // start building autoComplete @@ -472,9 +482,10 @@ TABS.cli.read = function (readInfo) { } } - if (!CliAutoComplete.isEnabled()) - // fallback to native autocomplete + // fallback to native autocomplete + if (!CliAutoComplete.isEnabled()) { setPrompt(removePromptHash(this.cliBuffer)); + } }; TABS.cli.sendLine = function (line, callback) { @@ -486,11 +497,11 @@ TABS.cli.sendNativeAutoComplete = function (line, callback) { }; TABS.cli.send = function (line, callback) { - var bufferOut = new ArrayBuffer(line.length); - var bufView = new Uint8Array(bufferOut); + const bufferOut = new ArrayBuffer(line.length); + const bufView = new Uint8Array(bufferOut); - for (var c_key = 0; c_key < line.length; c_key++) { - bufView[c_key] = line.charCodeAt(c_key); + for (let cKey = 0; cKey < line.length; cKey++) { + bufView[cKey] = line.charCodeAt(cKey); } serial.send(bufferOut, callback); @@ -508,7 +519,7 @@ TABS.cli.cleanup = function (callback) { return; } - this.send(getCliCommand('exit\r', this.cliBuffer), function (writeInfo) { + this.send(getCliCommand('exit\r', this.cliBuffer), function () { // we could handle this "nicely", but this will do for now // (another approach is however much more complicated): // we can setup an interval asking for data lets say every 200ms, when data arrives, callback will be triggered and tab switched diff --git a/test/karma.conf.js b/test/karma.conf.js index 9a2be454..3736894c 100644 --- a/test/karma.conf.js +++ b/test/karma.conf.js @@ -1,6 +1,6 @@ module.exports = function(config) { config.set({ - reporters: ['tfs'], + reporters: ['tfs', 'spec'], basePath: '../', frameworks: ['mocha', 'chai', 'sinon-chai'], files: [ @@ -15,14 +15,14 @@ module.exports = function(config) { './src/js/CliAutoComplete.js', './src/js/tabs/cli.js', './src/js/phones_ui.js', - './test/**/*.js' + './test/**/*.js', ], browsers: ['ChromeHeadlessNoSandbox'], customLaunchers: { ChromeHeadlessNoSandbox: { base: 'ChromeHeadless', - flags: ['--no-sandbox'] - } + flags: ['--no-sandbox'], + }, }, tfsReporter: { outputDir: 'testresults', diff --git a/test/tabs/cli.js b/test/tabs/cli.js index 3b0be1a2..95da0a2d 100644 --- a/test/tabs/cli.js +++ b/test/tabs/cli.js @@ -1,17 +1,21 @@ class MockAnalytics { EVENT_CATEGORIES = {}; - sendEvent() {} + sendEvent() { + // Empty + } } -var analytics; +let analytics; + describe('TABS.cli', () => { - function toArrayBuffer(string) { - var bufferOut = new ArrayBuffer(string.length); - var bufView = new Uint8Array(bufferOut); - for (var i = 0; i < string.length; i++) { + function toArrayBuffer(string) { + const bufferOut = new ArrayBuffer(string.length); + const bufView = new Uint8Array(bufferOut); + + for (let i = 0; i < string.length; i++) { bufView[i] = string.charCodeAt(i); } @@ -20,7 +24,7 @@ describe('TABS.cli', () => { describe('output', () => { const cliTab = $('
').addClass('tab-cli'); - const cliOutput = $('
').addClass('wrapper') + const cliOutput = $('
').addClass('wrapper'); const cliPrompt = $('