2015-02-10 19:41:24 +00:00
|
|
|
/*global describe it before beforeEach after bar =*/
|
|
|
|
|
|
|
|
"use client";
|
2015-08-25 10:51:36 +00:00
|
|
|
|
2015-02-10 19:41:24 +00:00
|
|
|
|
|
|
|
require(["lib/architect/architect", "lib/chai/chai", "/vfs-root", "ace/test/assertions"], function (architect, chai, baseProc) {
|
|
|
|
var expect = chai.expect;
|
|
|
|
|
|
|
|
expect.setupArchitectTest([
|
|
|
|
{
|
|
|
|
packagePath: "plugins/c9.core/c9",
|
|
|
|
workspaceId: "johndoe/dev",
|
|
|
|
startdate: new Date(),
|
|
|
|
debug: true,
|
|
|
|
hosted: true,
|
|
|
|
local: false,
|
|
|
|
davPrefix: "/"
|
|
|
|
},
|
|
|
|
|
|
|
|
"plugins/c9.core/ext",
|
|
|
|
"plugins/c9.core/http-xhr",
|
|
|
|
"plugins/c9.core/util",
|
|
|
|
"plugins/c9.ide.ui/lib_apf",
|
|
|
|
{
|
|
|
|
packagePath: "plugins/c9.core/settings",
|
|
|
|
testing: true
|
|
|
|
},
|
|
|
|
"plugins/c9.core/api.js",
|
|
|
|
{
|
|
|
|
packagePath: "plugins/c9.ide.ui/ui",
|
|
|
|
staticPrefix: "plugins/c9.ide.ui"
|
|
|
|
},
|
|
|
|
"plugins/c9.ide.editors/document",
|
|
|
|
"plugins/c9.ide.editors/undomanager",
|
|
|
|
"plugins/c9.ide.editors/editors",
|
|
|
|
"plugins/c9.ide.editors/editor",
|
|
|
|
"plugins/c9.ide.editors/tabmanager",
|
|
|
|
"plugins/c9.ide.ui/focus",
|
|
|
|
"plugins/c9.ide.editors/pane",
|
|
|
|
"plugins/c9.ide.editors/tab",
|
|
|
|
"plugins/c9.ide.terminal/terminal",
|
|
|
|
"plugins/c9.ide.terminal/predict_echo",
|
|
|
|
"plugins/c9.vfs.client/vfs.ping",
|
|
|
|
"plugins/c9.ide.preferences/preferences",
|
|
|
|
"plugins/c9.ide.ui/forms",
|
|
|
|
{
|
|
|
|
packagePath: "plugins/c9.fs/proc",
|
|
|
|
tmuxName: "cloud9test"
|
|
|
|
},
|
|
|
|
"plugins/c9.vfs.client/vfs_client",
|
|
|
|
"plugins/c9.vfs.client/endpoint",
|
|
|
|
"plugins/c9.ide.auth/auth",
|
|
|
|
{
|
|
|
|
packagePath: "plugins/c9.fs/fs",
|
|
|
|
baseProc: baseProc
|
|
|
|
},
|
|
|
|
|
|
|
|
// Mock plugins
|
|
|
|
{
|
|
|
|
consumes: ["apf", "ui", "Plugin"],
|
|
|
|
provides: [
|
|
|
|
"commands", "menus", "commands", "layout", "watcher",
|
|
|
|
"save", "anims", "clipboard", "dialog.alert", "auth.bootstrap",
|
|
|
|
"info", "dialog.error"
|
|
|
|
],
|
|
|
|
setup: expect.html.mocked
|
|
|
|
},
|
|
|
|
{
|
|
|
|
consumes: ["tabManager", "proc", "terminal", "terminal.predict_echo", "c9"],
|
|
|
|
provides: [],
|
|
|
|
setup: main
|
|
|
|
}
|
|
|
|
], architect);
|
|
|
|
|
|
|
|
function main(options, imports, register) {
|
|
|
|
var tabs = imports.tabManager;
|
|
|
|
var proc = imports.proc;
|
|
|
|
var predictor = imports["terminal.predict_echo"];
|
|
|
|
var assert = require("ace/test/assertions");
|
|
|
|
|
|
|
|
var ESC = "\u001B";
|
|
|
|
var OUTPUT_CURSOR_START = ESC + "[H";
|
|
|
|
var INPUT_LEFT = ESC + "[D";
|
|
|
|
var INPUT_LEFT_ONCE = ESC + "[1D";
|
|
|
|
var INPUT_LEFT_TWICE = ESC + "[2D";
|
|
|
|
var INPUT_HOME = ESC + "[1~";
|
|
|
|
var INPUT_END = "\u0005";
|
|
|
|
var INPUT_RIGHT = ESC + "[C";
|
|
|
|
var INPUT_BACKSPACE = "\u007F";
|
|
|
|
var INPUT_CONTROL_C = "\u0003";
|
|
|
|
var INPUT_DELETE = ESC + "[3~";
|
|
|
|
var OUTPUT_BACKSPACE = "\b" + ESC + "[K";
|
|
|
|
var OUTPUT_DELETE_CHAR = ESC + "[P";
|
|
|
|
var STATE_WAIT_FOR_ECHO_OR_PROMPT = 1;
|
|
|
|
var STATE_WAIT_FOR_ECHO = 2;
|
|
|
|
var STATE_WAIT_FOR_PROMPT = 3;
|
|
|
|
|
|
|
|
expect.html.setConstructor(function(tab) {
|
|
|
|
if (typeof tab == "object")
|
|
|
|
return tab.pane.aml.getPage("editor::" + tab.editorType).$ext;
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('terminal.predict_echo', function() {
|
|
|
|
this.timeout(30000);
|
|
|
|
|
|
|
|
before(function(done) {
|
|
|
|
this.timeout(45000);
|
|
|
|
apf.config.setProperty("allow-select", false);
|
|
|
|
apf.config.setProperty("allow-blur", false);
|
|
|
|
|
|
|
|
bar.$ext.style.background = "rgba(220, 220, 220, 0.93)";
|
|
|
|
bar.$ext.style.position = "fixed";
|
|
|
|
bar.$ext.style.left = "20px";
|
|
|
|
bar.$ext.style.right = "20px";
|
|
|
|
bar.$ext.style.bottom = "20px";
|
|
|
|
bar.$ext.style.height = "33%";
|
|
|
|
|
|
|
|
document.body.style.marginBottom = "33%";
|
|
|
|
|
|
|
|
predictor.$setTestTimeouts();
|
|
|
|
predictor.DEBUG = true;
|
|
|
|
|
|
|
|
proc.execFile("~/.c9/bin/tmux", { args: ["-L", "cloud9test", "kill-server"] }, function(err) {
|
|
|
|
tabs.once("ready", function(){
|
|
|
|
tabs.getPanes()[0].focus();
|
|
|
|
openTerminal(done);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
function openTerminal(done) {
|
|
|
|
tabs.openEditor("terminal", function(err, tab) {
|
|
|
|
editor = tab.editor;
|
|
|
|
session = editor.ace.getSession().c9session;
|
|
|
|
send = session.send;
|
|
|
|
|
2015-11-03 20:24:47 +00:00
|
|
|
setTimeout(init);
|
2015-02-10 19:41:24 +00:00
|
|
|
|
|
|
|
function init() {
|
2015-11-03 15:02:03 +00:00
|
|
|
afterPrompt(function() { setTimeout(start); });
|
2015-02-10 19:41:24 +00:00
|
|
|
// Make sure we have a prompt with a dollar for tests
|
2015-11-03 15:02:03 +00:00
|
|
|
// And terminal won't send rename commands in the middle of the test
|
|
|
|
// TODO: do we need to handle rename sequence in predict_echo instead?
|
|
|
|
editor.ace.onTextInput("PS1='. $ ';"
|
|
|
|
+ "tmux setw automatic-rename off;"
|
|
|
|
+ "printf '\\x1b]0;predict echo\\x07'\n");
|
|
|
|
// editor.ace.onTextInput("ssh lennart\n");
|
|
|
|
// editor.ace.onTextInput("ssh ubuntu@ci.c9.io\n");
|
2015-02-10 19:41:24 +00:00
|
|
|
}
|
|
|
|
});
|
2015-11-03 15:02:03 +00:00
|
|
|
function start() {
|
|
|
|
predictor.on("mispredict", function(e) {
|
|
|
|
console.error("MISPREDICTED", e)
|
|
|
|
delete e.session;
|
|
|
|
throw new Error("MISPREDICTED: " + JSON.stringify(e));
|
|
|
|
});
|
|
|
|
setTimeout(done)
|
|
|
|
}
|
2015-02-10 19:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function peek(offset) {
|
|
|
|
offset = offset || 0;
|
|
|
|
var char = session.terminal.getCharAt(
|
|
|
|
session.terminal.y, session.terminal.x + offset);
|
|
|
|
return char && char[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
function afterPrompt(callback) {
|
|
|
|
// Expect a prompt to appear
|
|
|
|
editor.on("beforeWrite", function wait(e) {
|
|
|
|
if (!e.data.match(/\$ ([\s\S]*\u001B\[\d+;\d+H)?$/))
|
|
|
|
return;
|
|
|
|
if (session.$predictor.predictions.length
|
|
|
|
&& !session.$predictor.predictions[session.$predictor.predictions.length - 1].optional)
|
|
|
|
return; // probably a false positive
|
|
|
|
editor.off("beforeWrite", wait);
|
|
|
|
|
|
|
|
console.log(" ^ prompt; proceeding with test");
|
|
|
|
editor.once("afterWrite", function() {
|
|
|
|
// Make sure we're after predict_echo's afterWrite
|
|
|
|
callback();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function afterPredict(text, callback) {
|
|
|
|
predictor.on("predict", function wait(e) {
|
|
|
|
if (e.data.indexOf(text) === -1
|
|
|
|
&& e.predictions.filter(function(p) {
|
|
|
|
return (p.$outputText || "").indexOf(text) !== -1
|
|
|
|
}).length === 0)
|
|
|
|
return;
|
|
|
|
predictor.off("predict", wait);
|
|
|
|
callback(e);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
var editor;
|
|
|
|
var session;
|
|
|
|
var send;
|
|
|
|
|
|
|
|
function sendAll(keys, callback) {
|
|
|
|
var key = keys.shift();
|
|
|
|
if (!key)
|
|
|
|
return callback && callback();
|
|
|
|
setTimeout(function() {
|
|
|
|
send(key);
|
|
|
|
sendAll(keys, callback);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
describe("predict_echo", function(){
|
|
|
|
beforeEach(function(done) {
|
|
|
|
afterPredict("*", function() {
|
|
|
|
afterPrompt(function() {
|
|
|
|
session.$predictor.state = 0;
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
send("\r");
|
|
|
|
});
|
|
|
|
session.$predictor.state = 0;
|
|
|
|
sendAll(" # next*".split(""));
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should predict a single character", function(done) {
|
|
|
|
predictor.on("predict", function wait(e) {
|
|
|
|
if (!e.data.match(/:/))
|
|
|
|
return;
|
|
|
|
predictor.off("predict", wait);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
sendAll([":"]);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should predict multiple characters sent at the same time", function(done) {
|
|
|
|
afterPredict("!", function() {
|
|
|
|
afterPrompt(function() {
|
|
|
|
done();
|
|
|
|
})
|
|
|
|
send("\r");
|
|
|
|
});
|
|
|
|
sendAll([": test!"]);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should predict a single character straight from keyboard input", function(done) {
|
|
|
|
predictor.on("predict", function wait(e) {
|
|
|
|
if (!e.data.match(/:/))
|
|
|
|
return;
|
|
|
|
predictor.off("predict", wait);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
editor.ace.onTextInput(":");
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it("should predict multiple character", function(done) {
|
|
|
|
predictor.on("predict", function wait(e) {
|
|
|
|
if (!e.data.match(/t/))
|
|
|
|
return;
|
|
|
|
predictor.off("predict", wait);
|
|
|
|
assert.equal(peek(-1), "t");
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
|
|
|
|
sendAll("ls -lt".split(""));
|
|
|
|
});
|
|
|
|
|
|
|
|
it("gracefully copes with a newline", function(done) {
|
|
|
|
// Expect \r
|
|
|
|
predictor.on("nopredict", function wait(e) {
|
|
|
|
if (e.data.indexOf("\r") === -1)
|
|
|
|
return;
|
|
|
|
predictor.off("nopredict", wait);
|
|
|
|
seenNewLine = true;
|
|
|
|
});
|
|
|
|
afterPrompt(function() {
|
|
|
|
assert(seenNewLine);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
|
|
|
|
var seenNewLine;
|
|
|
|
|
|
|
|
sendAll(["\r"]);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("supports cursor key left/right", function(done) {
|
|
|
|
afterPredict("h", function() {
|
|
|
|
sendAll([INPUT_LEFT, "c"]);
|
|
|
|
});
|
|
|
|
afterPredict("c", function() {
|
|
|
|
sendAll([INPUT_RIGHT, "o"]);
|
|
|
|
});
|
|
|
|
afterPredict("o", function() {
|
|
|
|
assert.equal(peek(-4), "e");
|
|
|
|
assert.equal(peek(-3), "c");
|
|
|
|
assert.equal(peek(-2), "h");
|
|
|
|
assert.equal(peek(-1), "o");
|
|
|
|
|
|
|
|
afterPrompt(done);
|
|
|
|
send("\r");
|
|
|
|
});
|
|
|
|
|
|
|
|
sendAll(["e", "h"]);
|
|
|
|
});
|
|
|
|
|
2015-09-28 07:11:17 +00:00
|
|
|
// Fails on CI server (https://github.com/c9/newclient/issues/9550)
|
|
|
|
it.skip("supports delete with repeated characters; stress test", function loop(done, attempt) {
|
2015-02-10 19:41:24 +00:00
|
|
|
this.timeout && this.timeout(60000);
|
|
|
|
session.$predictor.state = 0;
|
|
|
|
if (attempt === 5)
|
|
|
|
return done();
|
|
|
|
|
|
|
|
afterPredict("[", function() {
|
|
|
|
afterPredict("[", function() {
|
|
|
|
assert.equal(peek(-1), " ");
|
|
|
|
assert.equal(peek(), "e");
|
|
|
|
assert.equal(peek(1), "c");
|
|
|
|
|
|
|
|
afterPrompt(loop.bind(null, done, (attempt || 0) + 1));
|
|
|
|
send("\r");
|
|
|
|
});
|
|
|
|
sendAll([INPUT_DELETE]);
|
|
|
|
})
|
|
|
|
|
|
|
|
sendAll(["eecho blaaat", INPUT_HOME]);
|
|
|
|
});
|
|
|
|
|
|
|
|
// slow, useless; skip
|
|
|
|
it.skip("supports long sequence of chars; stress test", function loop(done, attempt) {
|
|
|
|
this.timeout && this.timeout(60000);
|
|
|
|
session.$predictor.state = 0;
|
|
|
|
if (attempt === 4)
|
|
|
|
return done();
|
|
|
|
|
|
|
|
afterPredict("?", function() {
|
|
|
|
send("\r");
|
|
|
|
afterPrompt(loop.bind(null, done, (attempt || 0) + 1));
|
|
|
|
});
|
|
|
|
|
|
|
|
sendAll("echo this is a pretty long sequence of characters, right?".split(""));
|
|
|
|
});
|
|
|
|
|
|
|
|
it("supports short sequence of chars; stress test", function loop(done, attempt) {
|
|
|
|
this.timeout && this.timeout(90000);
|
|
|
|
session.$predictor.state = 0;
|
|
|
|
if (attempt === 5)
|
|
|
|
return done();
|
|
|
|
|
|
|
|
afterPredict("?", function() {
|
|
|
|
send("\r");
|
|
|
|
afterPrompt(loop.bind(null, done, (attempt || 0) + 1));
|
|
|
|
});
|
|
|
|
|
|
|
|
sendAll("echo ?".split(""));
|
|
|
|
});
|
|
|
|
|
|
|
|
it("supports short sequence of chars with a newline; stress test", function loop(done, attempt) {
|
|
|
|
this.timeout && this.timeout(90000);
|
|
|
|
session.$predictor.state = 0;
|
|
|
|
if (attempt === 5)
|
|
|
|
return done();
|
|
|
|
|
|
|
|
afterPredict("?", function() {
|
|
|
|
afterPrompt(loop.bind(null, done, (attempt || 0) + 1));
|
|
|
|
});
|
|
|
|
|
|
|
|
session.$predictor.state = 0;
|
|
|
|
sendAll("echo 2?\r".split(""));
|
|
|
|
});
|
|
|
|
|
|
|
|
it("supports backspace with repeated characters", function(done) {
|
|
|
|
afterPredict("[", function() {
|
|
|
|
afterPredict("[", function() {
|
|
|
|
afterPredict("[", function() {
|
|
|
|
assert.equal(peek(-1), " ");
|
|
|
|
assert.equal(peek(), "e");
|
|
|
|
assert.equal(peek(1), "c");
|
|
|
|
|
|
|
|
afterPrompt(done);
|
|
|
|
send("\r");
|
|
|
|
});
|
|
|
|
sendAll([INPUT_BACKSPACE]);
|
|
|
|
});
|
|
|
|
sendAll([INPUT_RIGHT]);
|
|
|
|
})
|
|
|
|
|
|
|
|
sendAll(["eecho bleep", INPUT_HOME]);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("supports insert with repeated characters; stress test", function loop(done, attempt) {
|
|
|
|
this.timeout && this.timeout(60000);
|
|
|
|
session.$predictor.state = 0;
|
|
|
|
if (attempt === 5)
|
|
|
|
return done();
|
|
|
|
|
|
|
|
sendAll("echo blaat".split(""), function() {
|
|
|
|
var sawX;
|
|
|
|
|
|
|
|
afterPredict("t", function() {
|
|
|
|
assert.equal(peek(-3), "a");
|
|
|
|
sendAll([INPUT_LEFT, INPUT_LEFT, INPUT_LEFT, "x", "a"]);
|
|
|
|
});
|
|
|
|
predictor.on("predict", function wait(e) {
|
|
|
|
sawX = sawX || e.data.match(/x/);
|
|
|
|
if (!sawX || e.data.match(/xaat/) || !e.data.match(/a/))
|
|
|
|
return; // console.log(" -", e.data, sawX)*
|
|
|
|
predictor.off("predict", wait);
|
|
|
|
|
|
|
|
assert.equal(peek(), "a");
|
|
|
|
assert.equal(peek(1), "a");
|
|
|
|
assert.equal(peek(-1), "a");
|
|
|
|
|
|
|
|
afterPrompt(loop.bind(null, done, (attempt || 0) + 1));
|
|
|
|
send("\r");
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it("supports insert with home and repeated characters", function(done) {
|
|
|
|
afterPredict("t", function() {
|
|
|
|
assert.equal(peek(-3), "a");
|
|
|
|
sendAll(["x", INPUT_HOME, "e"])
|
|
|
|
});
|
|
|
|
predictor.on("predict", function wait(e) {
|
|
|
|
sawX = sawX || e.data.match(/x/);
|
|
|
|
if (!sawX || !e.data.match(/a/))
|
|
|
|
return;
|
|
|
|
predictor.off("predict", wait);
|
|
|
|
|
|
|
|
assert.equal(peek(), "e");
|
|
|
|
assert.equal(peek(-1), "e");
|
|
|
|
|
|
|
|
afterPrompt(done);
|
|
|
|
sendAll([INPUT_HOME, "#", "\r"]);
|
|
|
|
});
|
|
|
|
|
|
|
|
var sawX;
|
|
|
|
|
|
|
|
sendAll("echo blaat".split(""));
|
|
|
|
});
|
|
|
|
|
|
|
|
it("supports at least one spurious left cursor; stress test", function loop(done, attempt) {
|
|
|
|
this.timeout && this.timeout(60000);
|
|
|
|
session.$predictor.state = 0;
|
|
|
|
if (attempt === 10)
|
|
|
|
return done();
|
|
|
|
|
|
|
|
afterPredict("c", function() {
|
|
|
|
assert.equal(peek(-1), "c");
|
|
|
|
assert.equal(peek(-2), "e");
|
|
|
|
assert.equal(peek(-3), " ");
|
|
|
|
|
|
|
|
afterPrompt(function() {
|
|
|
|
loop(done, (attempt || 0) + 1)
|
|
|
|
});
|
|
|
|
send("\r");
|
|
|
|
});
|
|
|
|
|
|
|
|
sendAll(["e", "h", "o", INPUT_LEFT, INPUT_LEFT, INPUT_LEFT, INPUT_RIGHT, "c"]);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("supports home", function(done) {
|
|
|
|
predictor.on("predict", function wait(e) {
|
|
|
|
if (e.data.match(/^[a-z]*$/))
|
|
|
|
return;
|
|
|
|
predictor.off("predict", wait);
|
|
|
|
assert.equal(peek(), "e");
|
|
|
|
afterPrompt(done);
|
|
|
|
sendAll(["\r"]);
|
|
|
|
});
|
|
|
|
|
|
|
|
sendAll(["e", "c", "h", "o", INPUT_HOME]);
|
|
|
|
});
|
|
|
|
|
|
|
|
// TODO: rewrite this to support delayed enabling?
|
|
|
|
it.skip("enables and disables itself automatically; stress test", function loop(done, attempt) {
|
|
|
|
this.timeout && this.timeout(60000);
|
|
|
|
if (attempt === 5)
|
|
|
|
return done();
|
|
|
|
|
|
|
|
predictor.once("nopredict", function() {
|
|
|
|
predictor.once("nopredict", function(e) {
|
|
|
|
assert.equal(e.data, ":");
|
|
|
|
|
|
|
|
afterPredict("i", function() {
|
|
|
|
afterPrompt(function() {
|
|
|
|
loop(done, (attempt || 0) + 1);
|
|
|
|
});
|
|
|
|
|
|
|
|
send("\r");
|
|
|
|
});
|
|
|
|
|
|
|
|
sendAll(" hoi".split(""));
|
|
|
|
});
|
|
|
|
|
|
|
|
// sometimes backspace will re-enable state 0; we reset it here
|
|
|
|
session.$predictor.state = STATE_WAIT_FOR_ECHO_OR_PROMPT;
|
|
|
|
send(":");
|
|
|
|
});
|
|
|
|
|
|
|
|
session.$predictor.state = STATE_WAIT_FOR_ECHO_OR_PROMPT;
|
|
|
|
send(INPUT_BACKSPACE);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("correctly handles duplicate states", function(done) {
|
|
|
|
afterPredict("y", function() {
|
|
|
|
afterPrompt(done);
|
|
|
|
predictor.off("nopredict", fail);
|
|
|
|
send("\r");
|
|
|
|
});
|
|
|
|
predictor.on("nopredict", fail);
|
|
|
|
function fail(e) {
|
|
|
|
assert(false, "Prediction got disabled");
|
|
|
|
}
|
|
|
|
|
|
|
|
var repeat = ["x", INPUT_BACKSPACE, "x", INPUT_BACKSPACE, "x", INPUT_BACKSPACE];
|
|
|
|
repeat = repeat.concat(repeat).concat(repeat);
|
|
|
|
sendAll(repeat, function() {
|
|
|
|
setTimeout(function() {
|
|
|
|
sendAll(repeat, function() {
|
|
|
|
setTimeout(function() {
|
|
|
|
sendAll(repeat, function() {
|
|
|
|
send("y");
|
|
|
|
});
|
|
|
|
}, 300);
|
|
|
|
});
|
|
|
|
}, 200);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it("correctly handles repeated keys without pauses", function(done) {
|
|
|
|
afterPredict(":", function() {
|
|
|
|
afterPrompt(done);
|
|
|
|
send("\r");
|
2015-11-03 15:02:03 +00:00
|
|
|
});
|
2015-02-10 19:41:24 +00:00
|
|
|
sendAll("echo".split(""), function() {
|
|
|
|
send(INPUT_BACKSPACE);
|
|
|
|
send(INPUT_BACKSPACE);
|
|
|
|
send(INPUT_BACKSPACE);
|
|
|
|
send(INPUT_BACKSPACE);
|
|
|
|
send(":");
|
|
|
|
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!onload.remain) {
|
|
|
|
after(function(done) {
|
|
|
|
tabs.unload();
|
|
|
|
bar.destroy(true, true);
|
|
|
|
|
|
|
|
document.body.style.marginBottom = "";
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
onload && onload();
|
|
|
|
}
|
|
|
|
});
|