/*global describe it before after beforeEach onload*/ "use client"; var base = require("plugins/c9.ide.language/test_base"); base.setup(function(err, imports, helpers) { if (err) throw err; var language = imports.language; var chai = require("lib/chai/chai"); var expect = chai.expect; var assert = require("assert"); var tabs = imports.tabManager; var complete = imports["language.complete"]; var afterNoCompleteOpen = helpers.afterNoCompleteOpen; var afterCompleteDocOpen = helpers.afterCompleteDocOpen; var afterCompleteOpen = helpers.afterCompleteOpen; var isCompleterOpen = helpers.isCompleterOpen; var getCompletionCalls = helpers.getCompletionCalls; describe("analysis", function() { var jsTab; var jsSession; // Setup beforeEach(function(done) { tabs.getTabs().forEach(function(tab) { tab.close(true); }); // tab.close() isn't quite synchronous, wait for it :( complete.closeCompletionBox(); setTimeout(function() { tabs.openFile("/language.js", function(err, tab) { if (err) return done(err); jsTab = tab; jsSession = jsTab.document.getSession().session; expect(jsSession).to.not.equal(null); setTimeout(function() { complete.closeCompletionBox(); done(); }); }); }, 0); }); it('shows a word completer popup on keypress', function(done) { jsSession.setValue("conny; con"); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("n"); afterCompleteOpen(function(el) { expect.html(el).text(/conny/); done(); }); }); it('shows a word completer popup for things in comments', function(done) { jsSession.setValue("// conny\nco"); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 2, column: 0 }, end: { row: 2, column: 0 }}); jsTab.editor.ace.onTextInput("n"); afterCompleteOpen(function(el) { expect.html(el).text(/conny/); done(); }); }); it('shows an inference completer popup on keypress', function(done) { jsSession.setValue("console."); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("l"); afterCompleteOpen(function(el) { expect.html(el).text(/log\(/); done(); }); }); it('always does dot completion', function(done) { language.setContinuousCompletionEnabled(false); jsSession.setValue("console"); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("."); afterCompleteOpen(function(el) { expect.html(el).text(/log\(/); language.setContinuousCompletionEnabled(true); done(); }); }); it('shows a documentation popup in completion', function(done) { jsSession.setValue("console."); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("l"); afterCompleteDocOpen(function(el) { expect.html(el).text(/Outputs a message/); done(); }); }); it('shows a word completer in an immediate tab', function(done) { tabs.open( { active: true, editorType: "immediate" }, function(err, tab) { if (err) return done(err); // We get a tab, but it's not done yet, so we wait setTimeout(function() { expect(!isCompleterOpen()); tab.editor.ace.onTextInput("conny con"); expect(!isCompleterOpen()); tab.editor.ace.onTextInput("n"); afterCompleteOpen(function(el) { expect.html(el).text(/conny/); done(); }); }); } ); }); it('shows an immediate completer in an immediate tab', function(done) { tabs.open( { active: true, editorType: "immediate" }, function(err, tab) { if (err) return done(err); // We get a tab, but it's not done yet, so we wait setTimeout(function() { tab.editor.ace.onTextInput("window.a"); tab.editor.ace.onTextInput("p"); afterCompleteOpen(function(el) { expect.html(el).text(/applicationCache/); done(); }); }); } ); }); it("doesn't show a word completer when there are contextual completions", function(done) { jsSession.setValue("// logaritm\nconsole."); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 2, column: 0 }, end: { row: 2, column: 0 }}); jsTab.editor.ace.onTextInput("l"); afterCompleteOpen(function(el) { assert(!el.textContent.match(/logarithm/)); done(); }); }); it("completes with parentheses insertion", function(done) { jsSession.setValue("// logaritm\nconsole."); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 2, column: 0 }, end: { row: 2, column: 0 }}); jsTab.editor.ace.onTextInput("l"); afterCompleteOpen(function(el) { jsTab.editor.ace.keyBinding.onCommandKey({ preventDefault: function() {} }, 0, 13); setTimeout(function() { assert(jsSession.getValue().match(/console.log\(\)/)); done(); }); }); }); it("completes local functions with parentheses insertion", function(done) { jsSession.setValue('function foobar() {}\nfoo'); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 2, column: 0 }, end: { row: 2, column: 0 }}); jsTab.editor.ace.onTextInput("b"); afterCompleteOpen(function(el) { jsTab.editor.ace.keyBinding.onCommandKey({ preventDefault: function() {} }, 0, 13); setTimeout(function() { assert(jsSession.getValue().match(/foobar\(\)/)); done(); }); }); }); it("completes without parentheses insertion in strings", function(done) { jsSession.setValue('function foobar() {}\n\"foo'); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 2, column: 0 }, end: { row: 2, column: 0 }}); jsTab.editor.ace.onTextInput("b"); afterCompleteOpen(function(el) { jsTab.editor.ace.keyBinding.onCommandKey({ preventDefault: function() {} }, 0, 13); setTimeout(function() { assert(jsSession.getValue().match(/"foobar/)); assert(!jsSession.getValue().match(/"foobar\(\)/)); done(); }); }); }); it("completes following local dependencies", function(done) { jsSession.setValue('var test2 = require\("./test2.js");\ntest2.'); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 2, column: 0 }, end: { row: 2, column: 0 }}); jsTab.editor.ace.onTextInput("h"); afterCompleteOpen(function(el) { assert(el.textContent.match(/hoi/)); done(); }); }); it("completes following local with absolute paths", function(done) { jsSession.setValue('var ext = require\("plugins/c9.dummy/dep");\next.'); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 2, column: 0 }, end: { row: 2, column: 0 }}); jsTab.editor.ace.onTextInput("e"); afterCompleteOpen(function(el) { assert(el.textContent.match(/export3/)); assert(el.textContent.match(/export4/)); done(); }); }); it("completes following local dependencies with absolute paths and common js style exports", function(done) { jsSession.setValue('var ext = require\("plugins/c9.dummy/dep-define");\next.'); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 2, column: 0 }, end: { row: 2, column: 0 }}); jsTab.editor.ace.onTextInput("e"); afterCompleteOpen(function(el) { assert(el.textContent.match(/export1/)); assert(el.textContent.match(/export2/)); done(); }); }); it("doesn't show default browser properties like onabort for global completions", function(done) { jsSession.setValue('// function onlyShowMe() {}; \no'); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 2, column: 0 }, end: { row: 2, column: 0 }}); jsTab.editor.ace.onTextInput("n"); afterCompleteOpen(function(el) { assert(!el.textContent.match(/onabort/)); done(); }); }); it("shows default browser properties like onabort when 3 characters were typed", function(done) { jsSession.setValue('// function onlyShowMeAndMore() {};\non'); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 2, column: 0 }, end: { row: 2, column: 0 }}); jsTab.editor.ace.onTextInput("a"); afterCompleteOpen(function(el) { assert(el.textContent.match(/onabort/)); done(); }); }); it("shows no self-completion for 'var bre'", function(done) { jsSession.setValue('var '); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 2, column: 0 }, end: { row: 2, column: 0 }}); jsTab.editor.ace.onTextInput("bre"); afterCompleteOpen(function(el) { assert(!el.textContent.match(/bre\b/)); assert(el.textContent.match(/break/)); done(); }); }); it("shows word completion for 'var b'", function(done) { jsSession.setValue('// blie\nvar '); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 2, column: 0 }, end: { row: 2, column: 0 }}); jsTab.editor.ace.onTextInput("b"); afterCompleteOpen(function(el) { assert(el.textContent.match(/blie/)); done(); }); }); it("shows word completion for 'var bre'", function(done) { jsSession.setValue('// breedbeeld\nvar '); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 2, column: 0 }, end: { row: 2, column: 0 }}); jsTab.editor.ace.onTextInput("bre"); afterCompleteOpen(function(el) { assert(el.textContent.match(/breedbeeld/)); done(); }); }); it("shows no self-completion for 'function blie'", function(done) { jsSession.setValue('function bli'); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 2, column: 0 }, end: { row: 2, column: 0 }}); jsTab.editor.ace.onTextInput("e"); afterNoCompleteOpen(done); }); it("shows no completion for 'function blie(param'", function(done) { jsSession.setValue('function blie(para'); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 2, column: 0 }, end: { row: 2, column: 0 }}); jsTab.editor.ace.onTextInput("m"); afterNoCompleteOpen(done); }); it.skip("shows word completion for 'function blie(param'", function(done) { jsSession.setValue('function parametric() {}\nfunction blie(para'); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 2, column: 0 }, end: { row: 2, column: 0 }}); jsTab.editor.ace.onTextInput("m"); afterCompleteOpen(function(el) { assert(!el.textContent.match(/parapara/)); assert(el.textContent.match(/parametric/)); done(); }); }); it("shows no self-completion for 'x={ prop'", function(done) { jsSession.setValue('x={ pro'); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 2, column: 0 }, end: { row: 2, column: 0 }}); jsTab.editor.ace.onTextInput("p"); afterNoCompleteOpen(done); }); it("shows no function completion for 'x={ prop: 2 }'", function(done) { jsSession.setValue('function propAccess() {}\nx={ pro: 2 }'); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 7 }, end: { row: 1, column: 7 }}); jsTab.editor.ace.onTextInput("p"); afterCompleteOpen(function(el) { assert(!el.textContent.match(/propAccess\(\)/)); assert(el.textContent.match(/propAccess/)); done(); }); }); it("shows completion for '{ prop: fo'", function(done) { jsSession.setValue('function foo() {}\n{ prop: f'); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 2, column: 0 }, end: { row: 2, column: 0 }}); jsTab.editor.ace.onTextInput("o"); afterCompleteOpen(function(el) { assert(el.textContent.match(/foo\(\)/)); done(); }); }); it("extracts types from comments", function(done) { jsSession.setValue('/**\ndocs be here\n@param {String} text\n*/\nfunction foo(text) {}\nf'); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 10, column: 0 }, end: { row: 10, column: 0 }}); jsTab.editor.ace.onTextInput("o"); afterCompleteOpen(function(el) { assert(el.textContent.match(/foo\(text\)/)); afterCompleteDocOpen(function(el) { assert(el.textContent.match(/string/i)); assert(el.textContent.match(/docs/i)); done(); }); }); }); it("caches across expression prefixes", function(done) { jsSession.setValue("_collin; _c"); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("o"); afterCompleteOpen(function(el) { assert.equal(getCompletionCalls(), 1); complete.closeCompletionBox(); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("rry _co"); afterCompleteOpen(function(el) { assert.equal(getCompletionCalls(), 1); // Normally typing "_corry _c" would show "_corry" in the completion, // but since JavaScript is supposed to have a getCacheCompletionRegex set, // a cached results should be used that doesn't have "_corry" yet assert(!el.textContent.match(/_corry/)); assert(el.textContent.match(/_collin/)); done(); }); }); }); it("caches across expression prefixes, including 'if(' and 'if ('", function(done) { jsSession.setValue("b_collin; b_c"); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("o"); afterCompleteOpen(function(el) { assert.equal(getCompletionCalls(), 1); complete.closeCompletionBox(); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("rry if(if (b_co"); afterCompleteOpen(function(el) { assert.equal(getCompletionCalls(), 1); assert(el.textContent.match(/b_corry/)); // local_completer secretly ran a second time assert(el.textContent.match(/b_collin/)); done(); }); }); }); it("doesn't cache across expression prefixes in assigments", function(done) { jsSession.setValue("_collin; _c"); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("o"); afterCompleteOpen(function(el) { assert.equal(getCompletionCalls(), 1); complete.closeCompletionBox(); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("rry=_co"); afterCompleteOpen(function(el) { assert.equal(getCompletionCalls(), 2); assert(el.textContent.match(/_corry/)); assert(el.textContent.match(/_collin/)); done(); }); }); }); it("doesn't cache with expression prefixes based on function names or params", function(done) { jsSession.setValue("ffarg; function "); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("ff"); afterCompleteOpen(function(el) { assert.equal(getCompletionCalls(), 1); assert(el.textContent.match(/ffarg/)); complete.closeCompletionBox(); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("oo(ff"); afterCompleteOpen(function(el) { assert.equal(getCompletionCalls(), 2); // cache got cleared so we have farg here now assert(el.textContent.match(/ffoo/)); assert(el.textContent.match(/ffarg/)); complete.closeCompletionBox(); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("ort) ff"); afterCompleteOpen(function(el) { assert.equal(getCompletionCalls(), 3); // cache got cleared so we have fort here now assert(el.textContent.match(/ffoo/)); assert(el.textContent.match(/ffort/)); assert(el.textContent.match(/ffarg/)); done(); }); }); }); }); it("doesn't do prefix-caching outside of a function context", function(done) { jsSession.setValue("function foo() { "); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("f"); afterCompleteOpen(function(el) { assert.equal(getCompletionCalls(), 1); complete.closeCompletionBox(); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("} f"); afterCompleteOpen(function(el) { assert.equal(getCompletionCalls(), 2); done(); }); }); }); it("doesn't do prefix-caching after property access", function(done) { jsSession.setValue("console.l"); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("o"); afterCompleteOpen(function(el) { assert.equal(getCompletionCalls(), 1); complete.closeCompletionBox(); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("g c"); afterCompleteOpen(function(el) { assert(el.textContent.match(/console/), el.textContent); assert.equal(getCompletionCalls(), 2, "Should refetch after property access: " + getCompletionCalls()); done(); }); }); }); it.skip('predicts console.log() when typing just consol', function(done) { jsSession.setValue("conso"); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("l"); imports.worker.once("complete_predict_called", function() { assert.equal(getCompletionCalls(), 1); afterCompleteOpen(function retry(el) { assert.equal(getCompletionCalls(), 1); if (!el.textContent.match(/log/)) return afterCompleteOpen(retry); done(); }); }); }); it('shows the current identifier as the top result', function(done) { jsSession.setValue("concat; conso; cons"); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("o"); afterCompleteOpen(function(el) { assert.equal(getCompletionCalls(), 1); assert(el.textContent.match(/conso(?!l).*console/)); done(); }); }); it('shows the current identifier as the top result, and removes it as you keep typing', function(done) { jsSession.setValue("2; concat; conso; cons"); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("o"); afterCompleteOpen(function(el) { assert.equal(getCompletionCalls(), 1); assert(el.textContent.match(/conso(?!l).*console/)); complete.closeCompletionBox(); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("l"); afterCompleteOpen(function(el) { assert.equal(getCompletionCalls(), 1); assert(!el.textContent.match(/conso(?!l)/)); assert(el.textContent.match(/console/)); done(); }); }); }); it("doesn't assume undeclared vars are functions", function(done) { jsSession.setValue('window[imUndefined] = function(json) {};\n\ var unassigned;\n\ '); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 10, column: 0 }, end: { row: 10, column: 0 }}); jsTab.editor.ace.onTextInput("u"); afterCompleteOpen(function(el) { assert(el.textContent.match(/unassigned/)); assert(!el.textContent.match(/unassigned\(/)); done(); }); }); it("doesn't assume arrays are optional", function(done) { jsSession.setValue('function myFun(arr){}\nvar a = []\nmyFun(a)\nmyF'); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 10, column: 0 }, end: { row: 10, column: 0 }}); jsTab.editor.ace.onTextInput("u"); afterCompleteDocOpen(function(el) { assert(el.textContent.match(/myFun\(arr.*Array/)); done(); }); }); it.skip("completes php variables in short php escapes", function(done) { tabs.openFile("/test_broken.php", function(err, _tab) { if (err) return done(err); var tab = _tab; tabs.focusTab(tab); var session = tab.document.getSession().session; session.setValue(""); tab.editor.ace.selection.setSelectionRange({ start: { row: 0, column: 16 }, end: { row: 0, column: 16 }}); tab.editor.ace.onTextInput("$"); afterCompleteOpen(function(el) { complete.closeCompletionBox(); tab.editor.ace.onTextInput("f"); afterCompleteOpen(function(el) { assert(el.textContent.match(/foo/)); done(); }); }); }); }); it.skip("completes php variables in long files", function(done) { tabs.openFile("/test_broken.php", function(err, _tab) { if (err) return done(err); var tab = _tab; tabs.focusTab(tab); var session = tab.document.getSession().session; var value = ""; session.setValue(value); tab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); tab.editor.ace.onTextInput("$"); afterCompleteOpen(function(el) { complete.closeCompletionBox(); tab.editor.ace.onTextInput("foo_99"); afterCompleteOpen(function(el) { assert(el.textContent.match(/foo_991/)); done(); }); }); }); }); it('starts predicting a completion immediately after an assignment', function(done) { // We expect this behavior as infer_completer's predictNextCompletion() // tells worker we need completion here. jsSession.setValue("foo "); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("="); imports.testHandler.once("complete_called", function() { assert.equal(getCompletionCalls(), 1); jsTab.editor.ace.onTextInput(" "); // Wait and see if this triggers anything setTimeout(function() { jsTab.editor.ace.onTextInput("f"); afterCompleteOpen(function(el) { assert.equal(getCompletionCalls(), 1); assert(el.textContent.match(/foo/)); done(); }); }, 5); }); }); it.skip('just invokes completion once for "v1 + 1 == v2 + v"', function(done) { jsSession.setValue("var v1; "); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("v"); afterCompleteOpen(function(el) { complete.closeCompletionBox(); jsTab.editor.ace.onTextInput("1"); jsTab.editor.ace.onTextInput(" "); jsTab.editor.ace.onTextInput("+"); jsTab.editor.ace.onTextInput(" "); jsTab.editor.ace.onTextInput("1"); jsTab.editor.ace.onTextInput(" "); jsTab.editor.ace.onTextInput("="); jsTab.editor.ace.onTextInput("="); jsTab.editor.ace.onTextInput(" "); jsTab.editor.ace.onTextInput("v"); afterCompleteOpen(function(el) { complete.closeCompletionBox(); jsTab.editor.ace.onTextInput("2"); jsTab.editor.ace.onTextInput(" "); jsTab.editor.ace.onTextInput("+"); jsTab.editor.ace.onTextInput(" "); jsTab.editor.ace.onTextInput("v"); afterCompleteOpen(function(el) { assert.equal(getCompletionCalls(), 1); done(); }); }); }); }); it.skip('just invokes completion once for "x1 + 1 == x2 + x", with some timeouts', function(done) { jsSession.setValue("var x1; "); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("x"); afterCompleteOpen(function(el) { jsTab.editor.ace.onTextInput("1"); jsTab.editor.ace.onTextInput(" "); // Allow prediction to be triggered setTimeout(function() { jsTab.editor.ace.onTextInput("+"); // Allow prediction to be triggered setTimeout(function() { jsTab.editor.ace.onTextInput(" "); jsTab.editor.ace.onTextInput("1"); jsTab.editor.ace.onTextInput(" "); jsTab.editor.ace.onTextInput("="); jsTab.editor.ace.onTextInput("="); // Allow prediction to be triggered setTimeout(function() { jsTab.editor.ace.onTextInput(" "); jsTab.editor.ace.onTextInput("x"); afterCompleteOpen(function(el) { complete.closeCompletionBox(); jsTab.editor.ace.onTextInput("2"); jsTab.editor.ace.onTextInput(" "); jsTab.editor.ace.onTextInput("+"); jsTab.editor.ace.onTextInput(" "); jsTab.editor.ace.onTextInput("x"); afterCompleteOpen(function(el) { assert.equal(getCompletionCalls(), 1); done(); }); }); }, 5); }, 5); }, 5); }); }); it('calls completion twice for "var y; ...", "var v; ..."', function(done) { jsSession.setValue("var y1; "); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("y"); afterCompleteOpen(function(el) { complete.closeCompletionBox(); jsSession.setValue("var v1; "); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("v"); afterCompleteOpen(function(el) { assert.equal(getCompletionCalls(), 2); done(); }); }); }); it("doesn't start predicting completion immediately after a newline", function(done) { // We expect this behavior as infer_completer's predictNextCompletion() // tells worker we need completion here. jsSession.setValue("var foo;"); jsTab.editor.ace.selection.setSelectionRange({ start: { row: 1, column: 0 }, end: { row: 1, column: 0 }}); jsTab.editor.ace.onTextInput("\n"); setTimeout(function() { jsTab.editor.ace.onTextInput("\nf"); imports.testHandler.once("complete_called", function() { assert.equal(getCompletionCalls(), 1); done(); }); }, 50); }); it("completes python", function(done) { tabs.openFile("/python/test_user.py", function(err, _tab) { if (err) return done(err); var tab = _tab; tabs.focusTab(tab); var session = tab.document.getSession().session; session.setValue("import os; os"); tab.editor.ace.selection.setSelectionRange({ start: { row: 0, column: 16 }, end: { row: 0, column: 16 }}); imports.worker.once("python_completer_ready", function() { tab.editor.ace.onTextInput("."); afterCompleteOpen(function(el) { complete.closeCompletionBox(); assert(el.textContent.match(/abort/)); done(); }); }); }); }); }); });