feature(console) update to v2.8.0

This commit is contained in:
coderaiser 2014-02-03 03:45:29 -05:00
parent dd5370074f
commit 0bea992779
25 changed files with 16121 additions and 196 deletions

View file

@ -132,13 +132,15 @@ var CloudCmd, Util, DOM, CloudFunc, $;
Util.time(Name + ' load');
var lDir = CloudCmd.LIBDIRCLIENT + 'console/',
cssPath = lDir + 'css/',
jsPath = lDir + 'lib/',
lCSS = [
lDir + 'jqconsole.css',
lDir + 'ansi.css'
cssPath + 'jqconsole.css',
cssPath + 'ansi.css'
],
lAllCSS = CloudFunc.getJoinURL(lCSS),
lFiles = [
lDir + 'jqconsole.js',
jsPath + 'jqconsole.js',
lAllCSS
];

View file

@ -9,7 +9,7 @@ task 'watch', 'Build and watch the CoffeeScript source files', ->
task 'build', 'Build minified file with uglify', ->
console.log 'building...'
exec 'uglifyjs -o jqconsole.min.js lib/jqconsole.js', (err, res)->
exec 'uglifyjs -m -o jqconsole.min.js lib/jqconsole.js', (err, res)->
if err
console.error 'failed with', err
else

View file

@ -66,3 +66,11 @@ info.
2013.1.26 Version 2.7.7
* Support for middle click paste on linux. #47.
2013.8.5 Version 2.7.8
* Fix issue #51.
2014.2.3 Version 2.8.0
* Remove browser sniffing. Fix #37 #42 #53
* Update android support. Fix #41
* Add wrapper div for padding/styling of console. Fix #40

View file

@ -134,8 +134,7 @@ Takes two arguments:
Sets the number of spaces inserted when indenting and removed when unindenting.
Takes one argument:
* __int__ *width*: The code of the key pressing which (when Ctrl is held) will
trigger this shortcut.
* __int__ *width*: The number of spaces in each indentation level.
Example:
@ -720,4 +719,8 @@ further customization.
##Contributors
[Max Shawabkeh](http://max99x.com/)
[Amjad Masad](http://twitter.com/amjad_masad)
[Amjad Masad](http://twitter.com/amasad)
## License
[MIT](http://opensource.org/licenses/MIT)

View file

@ -1,4 +1,3 @@
.jqconsole-ansi-bold {
/* font-weight: bold; */
}
@ -121,10 +120,10 @@
color: red;
}
.jqconsole-ansi-color-green {
color: #65b04b;
color: green;
}
.jqconsole-ansi-color-yellow {
color: #fed563;
color: yellow;
}
.jqconsole-ansi-color-blue {
color: rgb(49,123,249);
@ -146,10 +145,10 @@
background-color: red;
}
.jqconsole-ansi-background-color-green {
background-color: #65b04b;
background-color: green;
}
.jqconsole-ansi-background-color-yellow {
background-color: #fed563;
background-color: yellow;
}
.jqconsole-ansi-background-color-blue {
background-color: blue;

View file

@ -0,0 +1,78 @@
<!DOCTYPE html>
<html>
<head>
<style>
html, body {
background-color: #333;
color: white;
font-family: monospace;
margin: 0;
padding: 0;
}
/* The console container element */
#console {
height: 400px;
width: 750px;
position:relative;
background-color: black;
border: 2px solid #CCC;
margin: 0 auto;
margin-top: 50px;
}
/* The inner console element. */
.jqconsole {
padding: 10px;
}
/* The cursor. */
.jqconsole-cursor {
background-color: gray;
}
/* The cursor color when the console looses focus. */
.jqconsole-blurred .jqconsole-cursor {
background-color: #666;
}
/* The current prompt text color */
.jqconsole-prompt {
color: #0d0;
}
/* The command history */
.jqconsole-old-prompt {
color: #0b0;
font-weight: normal;
}
/* The text color when in input mode. */
.jqconsole-input {
color: #dd0;
}
/* Previously entered input. */
.jqconsole-old-input {
color: #bb0;
font-weight: normal;
}
/* The text color of the output. */
.jqconsole-output {
color: white;
}
</style>
</head>
<body>
<div id="console"></div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<script src="../lib/jqconsole.js" type="text/javascript" charset="utf-8"></script>
<script>
$(function () {
var jqconsole = $('#console').jqconsole('Hi\n', '>>> ');
var startPrompt = function () {
// Start the prompt with history enabled.
jqconsole.Prompt(true, function (input) {
// Output input with the class jqconsole-output.
jqconsole.Write(input + '\n', 'jqconsole-output');
// Restart the prompt.
startPrompt();
});
};
startPrompt();
});
</script>
</body>
</html>

View file

@ -0,0 +1,120 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<link rel="stylesheet" href="../css/ansi.css" type="text/css" media="all" />
<style>
html, body {
background-color: #333;
color: white;
font-family: monospace;
margin: 0;
padding: 0;
}
#console {
height: 400px;
width: 750px;
position:relative;
background-color: black;
border: 2px solid #CCC;
margin: 0 auto;
margin-top: 50px;
}
.jqconsole {
padding: 10px;
padding-bottom: 10px;
}
.jqconsole-cursor {
background-color: #999;
}
.jqconsole-blurred .jqconsole-cursor {
background-color: #666;
}
.jqconsole-prompt {
color: #0d0;
}
.jqconsole-old-prompt {
color: #0b0;
font-weight: normal;
}
.jqconsole-input {
color: #dd0;
}
.jqconsole-old-input {
color: #bb0;
font-weight: normal;
}
.brace {
color: #00FFFF;
}
.paran {
color: #FF00FF;
}
.bracket {
color: #FFFF00;
}
.jqconsole-composition {
background-color: red;
}
</style>
</head>
<body>
<div id="console"></div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<script src="../lib/jqconsole.js"></script>
<script>
$(function() {
// Creating the console.
var header = 'Welcome to JQConsole!\n' +
'Use jqconsole.Write() to write and ' +
'jqconsole.Input() to read.\n';
window.jqconsole = $('#console').jqconsole(header, 'JS> ');
// Abort prompt on Ctrl+Z.
jqconsole.RegisterShortcut('Z', function() {
jqconsole.AbortPrompt();
handler();
});
// Move to line start Ctrl+A.
jqconsole.RegisterShortcut('A', function() {
jqconsole.MoveToStart();
handler();
});
// Move to line end Ctrl+E.
jqconsole.RegisterShortcut('E', function() {
jqconsole.MoveToEnd();
handler();
});
jqconsole.RegisterMatching('{', '}', 'brace');
jqconsole.RegisterMatching('(', ')', 'paran');
jqconsole.RegisterMatching('[', ']', 'bracket');
// Handle a command.
var handler = function(command) {
if (command) {
try {
jqconsole.Write('==> ' + window.eval(command) + '\n');
} catch (e) {
jqconsole.Write('ERROR: ' + e.message + '\n');
}
}
jqconsole.Prompt(true, handler, function(command) {
// Continue line if can't compile the command.
try {
Function(command);
} catch (e) {
if (/[\[\{\(]$/.test(command)) {
return 1;
} else {
return 0;
}
}
return false;
});
};
// Initiate the first prompt.
handler();
});
</script>
</body>
</html>

View file

@ -1,6 +1,6 @@
{
"name": "jqconsole",
"version": "2.7.7",
"version": "2.8.0",
"title": "Feature complete web terminal.",
"author": {
"name": "Amjad Masad",

View file

@ -0,0 +1,23 @@
module.exports = function(config) {
config.set({
frameworks: ["mocha"],
files: [
'test/vendor/*.js',
'lib/*.js',
'test/setup.coffee',
'test/ansi-test.coffee',
'test/jqconsole-test.coffee',
'test/prompt-test.coffee',
'test/shortcuts-test.coffee',
'test/history-test.coffee',
],
browsers: ['Chrome'],
reporters: ['dots'],
coffeePreprocessor: {
// options passed to the coffee compiler
options: {
bare: false,
}
},
});
};

View file

@ -1,72 +1,9 @@
// Generated by CoffeeScript 1.3.3
// Generated by CoffeeScript 1.6.3
/*
Copyrights 2011, the repl.it project.
Licensed under the MIT license
*/
// Limit scope pollution from any deprecated API
(function() {
var matched, browser;
// Use of jQuery.browser is frowned upon.
// More details: http://api.jquery.com/jQuery.browser
// jQuery.uaMatch maintained for back-compat
jQuery.uaMatch = function( ua ) {
ua = ua.toLowerCase();
var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
/(webkit)[ \/]([\w.]+)/.exec( ua ) ||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
/(msie) ([\w.]+)/.exec( ua ) ||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
[];
return {
browser: match[ 1 ] || "",
version: match[ 2 ] || "0"
};
};
matched = jQuery.uaMatch( navigator.userAgent );
browser = {};
if ( matched.browser ) {
browser[ matched.browser ] = true;
browser.version = matched.version;
}
// Chrome is Webkit, but Webkit is also Safari.
if ( browser.chrome ) {
browser.webkit = true;
} else if ( browser.webkit ) {
browser.safari = true;
}
jQuery.browser = browser;
jQuery.sub = function() {
function jQuerySub( selector, context ) {
return new jQuerySub.fn.init( selector, context );
}
jQuery.extend( true, jQuerySub, this );
jQuerySub.superclass = this;
jQuerySub.fn = jQuerySub.prototype = this();
jQuerySub.fn.constructor = jQuerySub;
jQuerySub.sub = this.sub;
jQuerySub.fn.init = function init( selector, context ) {
if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
context = jQuerySub( context );
}
return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
};
jQuerySub.fn.init.prototype = jQuerySub.fn;
var rootjQuerySub = jQuerySub(document);
return jQuerySub;
};
})();
(function() {
var $, Ansi, CLASS_ANSI, CLASS_BLURRED, CLASS_CURSOR, CLASS_HEADER, CLASS_INPUT, CLASS_OLD_PROMPT, CLASS_PREFIX, CLASS_PROMPT, DEFAULT_INDENT_WIDTH, DEFAULT_PROMPT_CONINUE_LABEL, DEFAULT_PROMPT_LABEL, EMPTY_DIV, EMPTY_SELECTOR, EMPTY_SPAN, ESCAPE_CHAR, ESCAPE_SYNTAX, E_KEYPRESS, JQConsole, KEY_BACKSPACE, KEY_DELETE, KEY_DOWN, KEY_END, KEY_ENTER, KEY_HOME, KEY_LEFT, KEY_PAGE_DOWN, KEY_PAGE_UP, KEY_RIGHT, KEY_TAB, KEY_UP, NEWLINE, STATE_INPUT, STATE_OUTPUT, STATE_PROMPT, spanHtml,
@ -142,24 +79,16 @@ Licensed under the MIT license
ESCAPE_SYNTAX = /\[(\d*)(?:;(\d*))*m/;
Ansi = (function() {
Ansi.prototype.COLORS = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'];
function Ansi() {
this.stylize = __bind(this.stylize, this);
this._closeSpan = __bind(this._closeSpan, this);
this._openSpan = __bind(this._openSpan, this);
this.getClasses = __bind(this.getClasses, this);
this._style = __bind(this._style, this);
this._color = __bind(this._color, this);
this._remove = __bind(this._remove, this);
this._append = __bind(this._append, this);
this.klasses = [];
}
@ -344,27 +273,16 @@ Licensed under the MIT license
};
JQConsole = (function() {
function JQConsole(container, header, prompt_label, prompt_continue_label) {
this.container = container;
function JQConsole(outer_container, header, prompt_label, prompt_continue_label) {
this._HideComposition = __bind(this._HideComposition, this);
this._ShowComposition = __bind(this._ShowComposition, this);
this._UpdateComposition = __bind(this._UpdateComposition, this);
this._EndComposition = __bind(this._EndComposition, this);
this._StartComposition = __bind(this._StartComposition, this);
this._CheckComposition = __bind(this._CheckComposition, this);
this._ProcessMatch = __bind(this._ProcessMatch, this);
this._HandleKey = __bind(this._HandleKey, this);
this._HandleChar = __bind(this._HandleChar, this);
this.isMobile = !!navigator.userAgent.match(/iPhone|iPad|iPod|Android/i);
this.isIos = !!navigator.userAgent.match(/iPhone|iPad|iPod/i);
this.isAndroid = !!navigator.userAgent.match(/Android/i);
@ -382,26 +300,41 @@ Licensed under the MIT license
this.history_new = '';
this.history_active = false;
this.shortcuts = {};
this.$console = $('<pre class="jqconsole"/>').appendTo(this.container);
this.$container = $('<div/>').appendTo(outer_container);
this.$container.css({
'top': 0,
'left': 0,
'right': 0,
'bottom': 0,
'position': 'absolute',
'overflow': 'auto'
});
this.$console = $('<pre class="jqconsole"/>').appendTo(this.$container);
this.$console.css({
position: 'absolute',
top: 0,
bottom: 0,
right: 0,
left: 0,
margin: 0,
overflow: 'auto'
'margin': 0,
'position': 'relative',
'min-height': '100%',
'box-sizing': 'border-box',
'-moz-box-sizing': 'border-box',
'-webkit-box-sizing': 'border-box'
});
this.$console_focused = true;
this.$input_container = $(EMPTY_DIV).appendTo(this.container);
this.$input_container = $(EMPTY_DIV).appendTo(this.$container);
this.$input_container.css({
position: 'relative',
position: 'absolute',
width: 1,
height: 0,
overflow: 'hidden'
});
this.$input_source = $('<textarea/>');
this.$input_source.attr('wrap', 'off').css({
this.$input_source = this.isAndroid ? $('<input/>') : $('<textarea/>');
this.$input_source.attr({
wrap: 'off',
autocapitalize: 'off',
autocorrect: 'off',
spellcheck: 'false',
autocomplete: 'off'
});
this.$input_source.css({
position: 'absolute',
width: 2
});
@ -421,7 +354,7 @@ Licensed under the MIT license
this._InitPrompt();
this._SetupEvents();
this.Write(this.header, CLASS_HEADER);
$(this.container).data('jqconsole', this);
$(outer_container).data('jqconsole', this);
}
JQConsole.prototype.ResetHistory = function() {
@ -455,7 +388,7 @@ Licensed under the MIT license
this.$input_container.detach();
this.$console.html('');
this.$prompt.appendTo(this.$console);
this.$input_container.appendTo(this.container);
this.$input_container.appendTo(this.$container);
this.Write(this.header, CLASS_HEADER);
return void 0;
};
@ -469,8 +402,7 @@ Licensed under the MIT license
return this.history_index = this.history.length;
};
/*------------------------ Shortcut Methods -----------------------------
*/
/*------------------------ Shortcut Methods -----------------------------*/
JQConsole.prototype._CheckKeyCode = function(key_code) {
@ -529,8 +461,7 @@ Licensed under the MIT license
return void 0;
};
/*---------------------- END Shortcut Methods ---------------------------
*/
/*---------------------- END Shortcut Methods ---------------------------*/
JQConsole.prototype.GetColumn = function() {
@ -777,8 +708,7 @@ Licensed under the MIT license
return void 0;
};
/*------------------------ Private Methods -------------------------------
*/
/*------------------------ Private Methods -------------------------------*/
JQConsole.prototype._CheckInputQueue = function() {
@ -811,8 +741,7 @@ Licensed under the MIT license
};
JQConsole.prototype._SetupEvents = function() {
var cb, paste_event,
_this = this;
var _this = this;
if (this.isMobile) {
this.$console.click(function(e) {
e.preventDefault();
@ -865,8 +794,7 @@ Licensed under the MIT license
};
return setTimeout(addClass, 100);
});
paste_event = $.browser.opera ? 'input' : 'paste';
this.$input_source.bind(paste_event, function() {
this.$input_source.bind('paste', function() {
var handlePaste;
handlePaste = function() {
if (_this.in_composition) {
@ -881,21 +809,17 @@ Licensed under the MIT license
this.$input_source.keypress(this._HandleChar);
this.$input_source.keydown(this._HandleKey);
this.$input_source.keydown(this._CheckComposition);
if ($.browser.mozilla != null) {
this.$input_source.bind('compositionstart', this._StartComposition);
this.$input_source.bind('compositionend', this._EndCommposition);
this.$input_source.bind('text', this._UpdateComposition);
}
if ($.browser.opera != null) {
cb = function() {
if (_this.in_composition) {
return;
}
if (_this.$input_source.val().length) {
return _this._StartComposition();
}
};
return setInterval(cb, 200);
this.$input_source.bind('compositionstart', this._StartComposition);
this.$input_source.bind('compositionend', function(e) {
return setTimeout((function() {
return _this._EndComposition(e);
}), 0);
});
if (this.isAndroid) {
this.$input_source.bind('input', this._StartComposition);
return this.$input_source.bind('input', this._UpdateComposition);
} else {
return this.$input_source.bind('text', this._UpdateComposition);
}
};
@ -908,16 +832,6 @@ Licensed under the MIT license
if (char_code === 8 || char_code === 9 || char_code === 13) {
return false;
}
if ($.browser.mozilla) {
if (event.keyCode || event.altKey) {
return true;
}
}
if ($.browser.opera) {
if (event.altKey) {
return true;
}
}
this.$prompt_left.text(this.$prompt_left.text() + String.fromCharCode(char_code));
this._ScrollToEnd();
return false;
@ -949,10 +863,10 @@ Licensed under the MIT license
this._MoveDown();
break;
case KEY_PAGE_UP:
this._ScrollUp();
this._ScrollPage('up');
break;
case KEY_PAGE_DOWN:
this._ScrollDown();
this._ScrollPage('down');
break;
default:
return true;
@ -991,10 +905,10 @@ Licensed under the MIT license
this.MoveToEnd(false);
break;
case KEY_PAGE_UP:
this._ScrollUp();
this._ScrollPage('up');
break;
case KEY_PAGE_DOWN:
this._ScrollDown();
this._ScrollPage('down');
break;
default:
return true;
@ -1048,6 +962,7 @@ Licensed under the MIT license
JQConsole.prototype._HandleEnter = function(shift) {
var continuation, text,
_this = this;
this._EndComposition();
if (shift) {
return this._InsertNewLine(true);
} else {
@ -1301,52 +1216,49 @@ Licensed under the MIT license
return _results;
};
JQConsole.prototype._ScrollUp = function() {
JQConsole.prototype._ScrollPage = function(dir) {
var target;
target = this.$console[0].scrollTop - this.$console.height();
return this.$console.stop().animate({
scrollTop: target
}, 'fast');
};
JQConsole.prototype._ScrollDown = function() {
var target;
target = this.$console[0].scrollTop + this.$console.height();
return this.$console.stop().animate({
target = this.$container[0].scrollTop;
if (dir === 'up') {
target -= this.$container.height();
} else {
target += this.$container.height();
}
return this.$container.stop().animate({
scrollTop: target
}, 'fast');
};
JQConsole.prototype._ScrollToEnd = function() {
var cont,
_this = this;
this.$console.scrollTop(this.$console[0].scrollHeight);
cont = function() {
var doc_height, line_height, optimal_pos, pos, rel_pos, screen_left, screen_top;
line_height = _this.$prompt_cursor.height();
screen_top = _this.$window.scrollTop();
screen_left = _this.$window.scrollLeft();
doc_height = document.documentElement.clientHeight;
pos = _this.$prompt_cursor.offset();
rel_pos = _this.$prompt_cursor.position();
_this.$input_container.css({
left: rel_pos.left,
top: rel_pos.top
});
optimal_pos = pos.top - (2 * line_height);
if (_this.isMobile && (typeof orientation !== "undefined" && orientation !== null)) {
if (screen_top < pos.top || screen_top > pos.top) {
return _this.$window.scrollTop(optimal_pos);
}
} else {
if (screen_top + doc_height < pos.top) {
return _this.$window.scrollTop(pos.top - doc_height + line_height);
} else if (screen_top > optimal_pos) {
return _this.$window.scrollTop(pos.top);
}
var pos;
this.$container.scrollTop(this.$container[0].scrollHeight);
pos = this.$prompt_cursor.position();
this.$input_container.css({
left: pos.left,
top: pos.top
});
return setTimeout(this.ScrollWindowToPrompt.bind(this), 50);
};
JQConsole.prototype.ScrollWindowToPrompt = function() {
var doc_height, line_height, optimal_pos, pos, screen_left, screen_top;
line_height = this.$prompt_cursor.height();
screen_top = this.$window.scrollTop();
screen_left = this.$window.scrollLeft();
doc_height = document.documentElement.clientHeight;
pos = this.$prompt_cursor.offset();
optimal_pos = pos.top - (2 * line_height);
if (this.isMobile && (typeof orientation !== "undefined" && orientation !== null)) {
if (screen_top < pos.top || screen_top > pos.top) {
return this.$window.scrollTop(optimal_pos);
}
};
return setTimeout(cont, 0);
} else {
if (screen_top + doc_height < pos.top) {
return this.$window.scrollTop(pos.top - doc_height + line_height);
} else if (screen_top > optimal_pos) {
return this.$window.scrollTop(pos.top);
}
}
};
JQConsole.prototype._SelectPromptLabel = function(continuation) {
@ -1511,9 +1423,6 @@ Licensed under the MIT license
JQConsole.prototype._CheckComposition = function(e) {
var key;
key = e.keyCode || e.which;
if (($.browser.opera != null) && this.in_composition) {
this._UpdateComposition();
}
if (key === 229) {
if (this.in_composition) {
return this._UpdateComposition();
@ -1524,17 +1433,23 @@ Licensed under the MIT license
};
JQConsole.prototype._StartComposition = function() {
this.$input_source.bind(E_KEYPRESS, this._EndComposition);
if (this.in_composition) {
return;
}
this.in_composition = true;
this._ShowComposition();
return setTimeout(this._UpdateComposition, 0);
};
JQConsole.prototype._EndComposition = function() {
this.$input_source.unbind(E_KEYPRESS, this._EndComposition);
this.in_composition = false;
if (!this.in_composition) {
return;
}
this._HideComposition();
return this.$input_source.val('');
this.$prompt_left.text(this.$prompt_left.text() + this.$composition.text());
this.$composition.text('');
this.$input_source.val('');
return this.in_composition = false;
};
JQConsole.prototype._UpdateComposition = function(e) {

View file

@ -0,0 +1,40 @@
{
"name": "jq-console",
"version": "2.8.0",
"description": "Feature complete web terminal",
"main": "jqconsole.min.js",
"directories": {
"test": "test"
},
"scripts": {
"test": "./node_modules/karma/bin/karma start --single-run"
},
"repository": {
"type": "git",
"url": "git://github.com/replit/jq-console.git"
},
"keywords": [
"jq-consoel",
"console",
"terminal"
],
"author": "amasad",
"license": "MIT",
"bugs": {
"url": "https://github.com/replit/jq-console/issues"
},
"devDependencies": {
"karma-coffee-preprocessor": "~0.1.2",
"mocha": "~1.17.1",
"karma-script-launcher": "~0.1.0",
"karma-chrome-launcher": "~0.1.2",
"karma-firefox-launcher": "~0.1.3",
"karma-html2js-preprocessor": "~0.1.0",
"karma-jasmine": "~0.1.5",
"requirejs": "~2.1.10",
"karma-requirejs": "~0.2.1",
"karma-phantomjs-launcher": "~0.1.1",
"karma": "~0.10.9",
"karma-mocha": "~0.1.1"
}
}

View file

@ -0,0 +1,50 @@
Ansi = $().jqconsole.Ansi
CssPre = 'jqconsole-ansi-'
describe 'Ansi', ->
describe '#_style', ->
ansi = null
beforeEach -> ansi = new Ansi()
it 'applies and replaces font', ->
ansi._style '11'
assert.deepEqual ["#{CssPre}fonts-1"], ansi.klasses
ansi._style '19'
assert.deepEqual ["#{CssPre}fonts-9"], ansi.klasses
it 'applies and replaces color', ->
ansi._style '31'
assert.deepEqual ["#{CssPre}color-#{ansi._color(1)}"], ansi.klasses
ansi._style '37'
assert.deepEqual ["#{CssPre}color-#{ansi._color(7)}"], ansi.klasses
ansi._style '39'
assert.deepEqual [], ansi.klasses
it 'applies and replaces background-color', ->
ansi._style '41'
assert.deepEqual ["#{CssPre}background-color-#{ansi._color(1)}"], ansi.klasses
ansi._style '47'
assert.deepEqual ["#{CssPre}background-color-#{ansi._color(7)}"], ansi.klasses
ansi._style '49'
assert.deepEqual [], ansi.klasses
describe '#stylize', ->
ansi = null
beforeEach -> ansi = new Ansi()
it 'appends a styles', ->
html = ansi.stylize 'test\x1B[1mhello'
assert.equal html, "<span class=\"\">test</span><span class=\"#{CssPre}bold\">hello</span>"
it 'appends multiple styles', ->
html = ansi.stylize 'test\x1B[1;2mhello'
assert.equal html, "<span class=\"\">test</span><span class=\"#{CssPre}bold #{CssPre}lighter\">hello</span>"
it 'appends multiple styles at different intervals', ->
html = ansi.stylize 'test\x1B[1mhello\x1B[2mhi'
assert.equal html, "<span class=\"\">test</span><span class=\"#{CssPre}bold\">hello</span><span class=\"#{CssPre}bold #{CssPre}lighter\">hi</span>"
html = ansi.stylize 'a\x1B[53mb\x1B[21mc\x1B[md'
assert.equal html, "<span class=\"#{CssPre}bold #{CssPre}lighter\">a</span><span class=\"#{CssPre}bold #{CssPre}lighter #{CssPre}overline\">b</span><span class=\"#{CssPre}overline\">c</span><span class=\"\">d</span>"

View file

@ -0,0 +1,49 @@
{jqconsole, typer: {typeA, keyDown, type}} = jqconsoleSetup()
describe 'History', ->
describe '#GetHistory', ->
it 'gets the history', ->
jqconsole.Prompt true, ->
typeA()
keyDown 13
deepEqual ['a'], jqconsole.GetHistory()
describe '#SetHistory', ->
it 'sets history', ->
h = ['a', 'b']
jqconsole.SetHistory h
deepEqual h, jqconsole.GetHistory()
describe '#ResetHistory', ->
it 'resets the history', ->
jqconsole.ResetHistory()
deepEqual jqconsole.history, []
describe 'History interaction in the prompt', ->
it 'gets the prev history item', ->
jqconsole.Prompt true, ->
type 'foo'
equal jqconsole.GetPromptText(), 'foo'
keyDown 13
jqconsole.Prompt true, ->
equal jqconsole.GetPromptText(), ''
keyDown 38
equal jqconsole.GetPromptText(), 'foo'
jqconsole.AbortPrompt()
it 'gets the next history item', ->
jqconsole.Prompt true, ->
type 'foo'
keyDown 13
jqconsole.Prompt true, ->
type 'bar'
keyDown 13
jqconsole.Prompt true, ->
keyDown 38
equal jqconsole.GetPromptText(), 'bar'
keyDown 38
equal jqconsole.GetPromptText(), 'foo'
keyDown 40
equal jqconsole.GetPromptText(), 'bar'
keyDown 40
equal jqconsole.GetPromptText(), ''

View file

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<title>Mocha</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="vendor/mocha.css" />
</head>
<body>
<div id="mocha"></div>
<script src="vendor/mocha.js"></script>
<script>mocha.setup('bdd')</script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<script src="../lib/jqconsole.js"></script>
<script src="vendor/assert.js"></script>
<script src="vendor/coffeescript.js"></script>
<script>
var tests = [ 'setup.coffee'
, 'ansi-test.coffee'
, 'jqconsole-test.coffee'
, 'prompt-test.coffee'
, 'shortcuts-test.coffee'
, 'history-test.coffee'
]
tests.forEach(function (test) {
CoffeeScript.load(test, start)
})
function start () {
if (start.called == null) start.called = 0;
if (++start.called == tests.length) {
mocha.run();
}
}
</script>
</body>
</html>

View file

@ -0,0 +1,29 @@
describe 'JQConsole', ->
{$container, jqconsole} = jqconsoleSetup()
describe '#constructor', ->
it 'instantiates', ->
equal jqconsole.header, 'header'
equal jqconsole.prompt_label_main, 'prompt_label'
equal jqconsole.prompt_label_continue, 'prompt_continue'
equal jqconsole.indent_width, 2
equal jqconsole.GetState(), 'output'
deepEqual jqconsole.input_queue, []
deepEqual jqconsole.history, []
ok jqconsole.$console.length
ok jqconsole.$console instanceof jQuery
equal $container.text().trim(), 'header'
strictEqual $container.data('jqconsole'), jqconsole
ok jqconsole.$prompt.length
ok jqconsole.$input_source.length
it 'setup events', (done)->
counter = 0
jqconsole.$input_source.focus ->
counter++
jqconsole.$console.mouseup()
fn = ->
ok counter
done()
setTimeout fn, 10

View file

@ -0,0 +1,394 @@
{jqconsole, createScroll, typer: {typeA, keyDown, type}} = jqconsoleSetup()
describe 'Prompt Interaction', ->
describe '#Prompt', ->
after ->
jqconsole.AbortPrompt()
it 'inits prompt and auto-focuses', ->
counter = 0
jqconsole.$input_source.focus ->
counter++
resultCb = ->
jqconsole.Prompt true, resultCb
equal jqconsole.GetState(), 'prompt'
ok counter
ok jqconsole.history_active
strictEqual jqconsole.input_callback, resultCb
equal jqconsole.$prompt.text().trim(), 'prompt_label'
describe '#AbortPrompt', ->
it 'aborts the prompt', ->
jqconsole.Prompt true, ->
jqconsole.AbortPrompt()
equal jqconsole.$prompt.text().trim(), ''
it 'restarts queued prompts', ->
aCb = ->
jqconsole.Prompt false, aCb
bCb = ->
jqconsole.Prompt true, bCb
strictEqual jqconsole.input_callback, aCb
strictEqual jqconsole.history_active, false
jqconsole.AbortPrompt()
strictEqual jqconsole.input_callback, bCb
strictEqual jqconsole.history_active, true
jqconsole.AbortPrompt()
describe '#GetPromptText', ->
beforeEach -> jqconsole.Prompt true, ->
afterEach -> jqconsole.AbortPrompt()
it 'gets the current prompt text', ->
type 'foo'
equal jqconsole.$prompt.text().trim(), 'prompt_labelfoo'
equal jqconsole.GetPromptText(), 'foo'
it 'gets the current prompt text with the label', ->
type 'foo'
equal jqconsole.$prompt.text().trim(), 'prompt_labelfoo'
equal jqconsole.GetPromptText(true), 'prompt_labelfoo'
describe '#ClearPromptText', ->
beforeEach -> jqconsole.Prompt true, ->
afterEach -> jqconsole.AbortPrompt()
it 'Clears the current prompt text', ->
type 'foo'
equal jqconsole.GetPromptText(), 'foo'
jqconsole.ClearPromptText()
equal jqconsole.GetPromptText(), ''
it 'Clears prompt text with label', ->
type 'foo'
equal jqconsole.GetPromptText(), 'foo'
jqconsole.ClearPromptText true
equal jqconsole.GetPromptText(true), ''
describe '#SetPromptText', ->
beforeEach -> jqconsole.Prompt true, ->
afterEach -> jqconsole.AbortPrompt()
it 'sets the current prompt text', ->
type 'bar'
jqconsole.SetPromptText('foo')
equal jqconsole.GetPromptText(), 'foo'
describe 'Moving', ->
beforeEach -> jqconsole.Prompt true, ->
afterEach -> jqconsole.AbortPrompt()
it 'moves to the left', ->
type 'xyz'
keyDown 37
equal jqconsole.$prompt_left.text().trim(), 'xy'
keyDown 37
equal jqconsole.$prompt_left.text().trim(), 'x'
keyDown 37
equal jqconsole.$prompt_left.text().trim(), ''
keyDown 37
equal jqconsole.$prompt_left.text().trim(), ''
it 'moves to the right', ->
type 'xyz'
keyDown 37
keyDown 37
equal jqconsole.$prompt_left.text().trim(), 'x'
keyDown 39
equal jqconsole.$prompt_left.text().trim(), 'xy'
keyDown 39
equal jqconsole.$prompt_left.text().trim(), 'xyz'
keyDown 39
equal jqconsole.$prompt_left.text().trim(), 'xyz'
it 'moves to the prev line when at the first char of the line moving left', ->
type 'xyz'
keyDown 13, shiftKey: on
type 'abc'
equal jqconsole.$prompt_left.text().trim(), 'abc'
keyDown 37
keyDown 37
keyDown 37
keyDown 37
equal jqconsole.$prompt_left.text().trim(), 'xyz'
it 'moves to the next line when at the last char of the line moving right', ->
type 'xyz'
keyDown 13, shiftKey: on
type 'abc'
equal jqconsole.$prompt_left.text().trim(), 'abc'
keyDown 37
keyDown 37
keyDown 37
keyDown 37
equal jqconsole.$prompt_left.text().trim(), 'xyz'
keyDown 39
equal jqconsole.$prompt_right.text().trim(), 'abc'
it 'moves to the start of the word', ->
type 'xyz abc'
keyDown 37, metaKey: on
equal jqconsole.$prompt_right.text().trim(), 'abc'
equal jqconsole.$prompt_left.text().trim(), 'xyz'
it 'moves to the end of the word', ->
type 'xyz abc'
keyDown 37, metaKey: on
keyDown 37, metaKey: on
keyDown 39, metaKey: on
equal jqconsole.$prompt_right.text().trim(), 'abc'
equal jqconsole.$prompt_left.text().trim(), 'xyz'
it 'moves to the end of the word', ->
type 'xyz abc'
keyDown 37, metaKey: on
keyDown 37, metaKey: on
keyDown 39, metaKey: on
equal jqconsole.$prompt_right.text().trim(), 'abc'
equal jqconsole.$prompt_left.text().trim(), 'xyz'
it 'moves to the start of the line', ->
type 'xyz abc'
keyDown 36
equal jqconsole.$prompt_right.text().trim(), 'xyz abc'
it 'moves to the end of the line', ->
type 'xyz abc'
keyDown 36
equal jqconsole.$prompt_right.text().trim(), 'xyz abc'
keyDown 35
equal jqconsole.$prompt_right.text().trim(), ''
equal jqconsole.$prompt_left.text().trim(), 'xyz abc'
it 'moves to the start of the prompt', ->
type 'xyz abc'
keyDown 13, shiftKey: on
type 'hafm olim'
keyDown 36, metaKey: on
equal jqconsole.$prompt_right.text().trim(), 'xyz abc'
equal jqconsole.$prompt_after.text().trim(), 'prompt_continuehafm olim'
it 'moves to the end of the prompt', ->
type 'xyz abc'
keyDown 13, shiftKey: on
type 'hafm olim'
keyDown 36, metaKey: on
equal jqconsole.$prompt_right.text().trim(), 'xyz abc'
equal jqconsole.$prompt_after.text().trim(), 'prompt_continuehafm olim'
keyDown 35, metaKey: on
equal jqconsole.$prompt_left.text().trim(), 'hafm olim'
equal jqconsole.$prompt_before.text().trim(), 'prompt_labelxyz abc'
it 'moves up one line', ->
type 'xyz'
keyDown 13, shiftKey: on
type 'a'
keyDown 38, shiftKey: on
equal jqconsole.$prompt_right.text().trim(), 'yz'
it 'moves down one line', ->
type 'xyz'
keyDown 13, shiftKey: on
type 'a'
# Meta key also works.
keyDown 38, metaKey: on
equal jqconsole.$prompt_right.text().trim(), 'yz'
keyDown 40, metaKey: on
equal jqconsole.$prompt_right.text().trim(), ''
it 'respects the column when moving vertically', ->
type 'xyz'
keyDown 13, shiftKey: on
type 'ab'
keyDown 38, shiftKey: on
equal jqconsole.$prompt_right.text().trim(), 'z'
keyDown 40, shiftKey: on
keyDown 37
keyDown 37
equal jqconsole.$prompt_right.text().trim(), 'ab'
keyDown 38, shiftKey: on
equal jqconsole.$prompt_right.text().trim(), 'xyz'
describe 'Control Keys', ->
beforeEach -> jqconsole.Prompt true, ->
afterEach -> jqconsole.AbortPrompt()
it 'handles enter', ->
jqconsole.AbortPrompt()
counter = 0
jqconsole.Prompt true, -> counter++
typeA()
keyDown 13
ok counter
equal jqconsole.$console.find('.jqconsole-old-prompt').last().text().trim(), 'prompt_labela'
# Restart the prompt for other tests.
jqconsole.Prompt true, ->
it 'handles shift+enter', ->
keyDown 13, shiftKey: on
equal jqconsole.$prompt.text().trim(), 'prompt_label \nprompt_continue'
it 'handles tab', ->
typeA()
keyDown 9
equal jqconsole.$prompt.text().trim(), 'prompt_label a'
it 'handles shift+tab', ->
typeA()
keyDown 9, shiftKey: on
equal jqconsole.$prompt.text().trim(), 'prompt_labela'
it 'backspace', ->
typeA()
keyDown 8
equal jqconsole.$prompt.text().trim(), 'prompt_label'
it 'cntrl+backspace', ->
typeA()
typeA()
keyDown 8, metaKey: on
equal jqconsole.$prompt.text().trim(), 'prompt_label'
it 'deletes a char', ->
type 'xyz'
keyDown 37
equal jqconsole.$prompt_right.text().trim(), 'z'
keyDown 46
equal jqconsole.$prompt_right.text().trim(), ''
it 'deletes a word', ->
type 'xyz abc'
keyDown 37
keyDown 37
keyDown 37
equal jqconsole.$prompt_right.text().trim(), 'abc'
keyDown 46, metaKey: on
equal jqconsole.$prompt_right.text().trim(), ''
describe 'scrolling', ->
console_height = null
_fast = null
before ->
jQuery.fx.speeds.fast = 10
after ->
jQuery.fx.speeds.fast = _fast
beforeEach ->
jqconsole.Reset()
jqconsole.Prompt true, ->
# Make sure the console has a scroll.
{ console_height } = createScroll()
it 'scrolls up', (done) ->
before = jqconsole.$container[0].scrollTop
keyDown 33
cb = ->
equal jqconsole.$container[0].scrollTop, before - console_height
done()
# * 2 is some arbitrary number otherwise it fails.
setTimeout cb, jQuery.fx.speeds.fast * 2
it 'scrolls up twice', (done) ->
before = jqconsole.$container[0].scrollTop
keyDown 33
cb = ->
keyDown 33
cb = ->
equal jqconsole.$container[0].scrollTop, before - (console_height * 2)
done()
setTimeout cb, jQuery.fx.speeds.fast * 2
# * 2 is some arbitrary number otherwise it fails.
setTimeout cb, jQuery.fx.speeds.fast * 2
it 'scrolls down', (done) ->
before = jqconsole.$container[0].scrollTop
keyDown 33
cb = ->
keyDown 34
cb = ->
equal jqconsole.$container[0].scrollTop, before
done()
setTimeout cb, jQuery.fx.speeds.fast * 2
# * 2 is some arbitrary number otherwise it fails.
setTimeout cb, jQuery.fx.speeds.fast * 2
describe 'Typing', ->
beforeEach -> jqconsole.Prompt true, ->
afterEach -> jqconsole.AbortPrompt()
it 'handles chars', ->
str = ''
test = (ch) ->
str += ch
e = $.Event('keypress')
e.which = ch.charCodeAt(0)
jqconsole.$input_source.trigger e
equal jqconsole.$prompt.text().trim(), 'prompt_label' + str
test 'a'
test 'Z'
test '$'
test 'ƒ'
it 'scrolls all the way down when typing', (done) ->
createScroll()
keyDown 33
cb = ->
before = jqconsole.$container[0].scrollTop
type('a')
cb = ->
notEqual jqconsole.$container[0].scrollTop, before
done()
setTimeout cb, 0
setTimeout cb, jQuery.fx.speeds.fast * 2
describe 'Multiline', ->
beforeEach ->
if jqconsole.GetState() is 'prompt'
jqconsole.AbortPrompt()
it 'executes multiline callback', (done) ->
jqconsole.Prompt true, (-> ), ->
done()
type('foo')
keyDown 13
it 'indents', ->
jqconsole.Prompt true, (-> ), ->
return 2
type('foo')
keyDown 13
equal jqconsole.GetState(), 'prompt'
equal jqconsole.GetPromptText(), 'foo\n '
it 'keeps indentation on shift+enter', ->
jqconsole.Prompt true, (-> ), ->
return 2
type('foo')
keyDown 9
keyDown 13, shiftKey: on
equal jqconsole.GetState(), 'prompt'
equal jqconsole.GetPromptText(), ' foo\n '
it 'unindents', ->
jqconsole.Prompt true, (-> ), ->
return -2
type('foo')
keyDown 9
keyDown 13
equal jqconsole.GetPromptText(), ' foo\n'
it 'skip indent callback', (done) ->
jqconsole.Prompt true, done.bind(null, null), ->
return false
type('foo')
keyDown 13
it 'handles async treatment', (done) ->
jqconsole.Prompt true, done.bind(null, null), ((text, cb) -> cb false), on
type('foo')
keyDown 13

View file

@ -0,0 +1,44 @@
window.equal = assert.equal
window.notEqual = assert.notEqual
window.deepEqual = assert.deepEqual
window.strictEqual = assert.strictEqual
window.ok = assert.ok
JQConsole = $().jqconsole.JQConsole
window.jqconsoleSetup = ->
$container = $('<div/>').css
height: '100px'
widht: '200px'
position: 'relative'
$container.appendTo('body')
jqconsole = new JQConsole($container, 'header', 'prompt_label', 'prompt_continue')
typer =
typeA: ->
e = $.Event('keypress')
e.which = 'a'.charCodeAt(0)
jqconsole.$input_source.trigger e
keyDown: (code, options = {}) ->
e = $.Event('keydown')
e.which = code
e[k] = v for k, v of options
jqconsole.$input_source.trigger e
type: (str) ->
type = (chr) ->
e = $.Event('keypress')
e.which = chr.charCodeAt(0)
jqconsole.$input_source.trigger(e)
type chr for chr in str
createScroll = ->
line_height = jqconsole.$prompt.height()
console_height = jqconsole.$container.height()
lines_per_page = Math.ceil(console_height / line_height)
for i in [0..lines_per_page * 5]
jqconsole.SetPromptText('foo')
jqconsole._HandleEnter()
jqconsole.Prompt true, ->
{line_height, console_height, lines_per_page}
{$container, jqconsole, typer, createScroll}

View file

@ -0,0 +1,60 @@
{jqconsole, typer: {keyDown}} = jqconsoleSetup()
describe 'Shortcuts', ->
describe '#RegisterShortcut', ->
# Fails in v2.7.7
it 'throws if callback not function', ->
assert.throws ->
jqconsole.RegisterShortcut 'b', 'c'
it 'registers shortcut by string', ->
cb = ->
jqconsole.RegisterShortcut 'a', cb
deepEqual jqconsole.shortcuts['a'.charCodeAt(0)], [cb]
deepEqual jqconsole.shortcuts['A'.charCodeAt(0)], [cb]
it 'registers shortcut by charcode', ->
cb = ->
jqconsole.RegisterShortcut 'c'.charCodeAt(0), cb
deepEqual jqconsole.shortcuts['c'.charCodeAt(0)], [cb]
deepEqual jqconsole.shortcuts['C'.charCodeAt(0)], [cb]
it 'shortcuts must be ascii', ->
assert.throws ->
jqconsole.RegisterShortcut 'ƒ', ->
describe '#UnRegisterShortcut', ->
it 'removes all callback for a shortcut', ->
cb = ->
jqconsole.RegisterShortcut 'a', cb
jqconsole.UnRegisterShortcut 'a'
deepEqual jqconsole.shortcuts['a'.charCodeAt(0)], undefined
it 'removes specific callback', ->
aCb = ->
bCb = ->
jqconsole.RegisterShortcut 'a', aCb
jqconsole.RegisterShortcut 'a', bCb
jqconsole.UnRegisterShortcut 'a', aCb
deepEqual jqconsole.shortcuts['a'.charCodeAt(0)], [bCb]
describe '#ResetShortcuts', ->
it 'resets all shortcuts', ->
cb1 = ->
cb2 = ->
jqconsole.RegisterShortcut 'a', cb1
jqconsole.RegisterShortcut 'b', cb2
jqconsole.ResetShortcuts()
deepEqual jqconsole.shortcuts, {}
describe 'Invoking Shortcuts', ->
it 'invokes shortcuts', ->
jqconsole.Prompt true, ->
counter = 0
jqconsole.RegisterShortcut 'a', ->
strictEqual this, jqconsole
counter++
keyDown 'a'.charCodeAt(0), metaKey: on
ok counter

369
lib/client/console/test/vendor/assert.js vendored Normal file
View file

@ -0,0 +1,369 @@
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
//
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
//
// Copyright (c) 2011 Jxck
//
// Originally from node.js (http://nodejs.org)
// Copyright Joyent, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the 'Software'), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
(function(global) {
// Object.create compatible in IE
var create = Object.create || function(p) {
if (!p) throw Error('no type');
function f() {};
f.prototype = p;
return new f();
};
// UTILITY
var util = {
inherits: function(ctor, superCtor) {
ctor.super_ = superCtor;
ctor.prototype = create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
}
};
var pSlice = Array.prototype.slice;
// 1. The assert module provides functions that throw
// AssertionError's when particular conditions are not met. The
// assert module must conform to the following interface.
var assert = ok;
global['assert'] = assert;
if (typeof module === 'object' && typeof module.exports === 'object') {
module.exports = assert;
};
// 2. The AssertionError is defined in assert.
// new assert.AssertionError({ message: message,
// actual: actual,
// expected: expected })
assert.AssertionError = function AssertionError(options) {
this.name = 'AssertionError';
this.message = options.message || (options.actual + ' ' + options.operator + ' ' +options.expected)
this.actual = options.actual;
this.expected = options.expected;
this.operator = options.operator;
var stackStartFunction = options.stackStartFunction || fail;
if (Error.captureStackTrace) {
Error.captureStackTrace(this, stackStartFunction);
}
};
util.inherits(assert.AssertionError, Error);
function replacer(key, value) {
if (value === undefined) {
return '' + value;
}
if (typeof value === 'number' && (isNaN(value) || !isFinite(value))) {
return value.toString();
}
if (typeof value === 'function' || value instanceof RegExp) {
return value.toString();
}
return value;
}
function truncate(s, n) {
if (typeof s == 'string') {
return s.length < n ? s : s.slice(0, n);
} else {
return s;
}
}
assert.AssertionError.prototype.toString = function() {
if (this.message) {
return [this.name + ':', this.message].join(' ');
} else {
return [
this.name + ':',
truncate(JSON.stringify(this.actual, replacer), 128),
this.operator,
truncate(JSON.stringify(this.expected, replacer), 128)
].join(' ');
}
};
// assert.AssertionError instanceof Error
assert.AssertionError.__proto__ = Error.prototype;
// At present only the three keys mentioned above are used and
// understood by the spec. Implementations or sub modules can pass
// other keys to the AssertionError's constructor - they will be
// ignored.
// 3. All of the following functions must throw an AssertionError
// when a corresponding condition is not met, with a message that
// may be undefined if not provided. All assertion methods provide
// both the actual and expected values to the assertion error for
// display purposes.
function fail(actual, expected, message, operator, stackStartFunction) {
throw new assert.AssertionError({
message: message,
actual: actual,
expected: expected,
operator: operator,
stackStartFunction: stackStartFunction
});
}
// EXTENSION! allows for well behaved errors defined elsewhere.
assert.fail = fail;
// 4. Pure assertion tests whether a value is truthy, as determined
// by !!guard.
// assert.ok(guard, message_opt);
// This statement is equivalent to assert.equal(true, !!guard,
// message_opt);. To test strictly for the value true, use
// assert.strictEqual(true, guard, message_opt);.
function ok(value, message) {
if (!!!value) fail(value, true, message, '==', assert.ok);
}
assert.ok = ok;
// 5. The equality assertion tests shallow, coercive equality with
// ==.
// assert.equal(actual, expected, message_opt);
assert.equal = function equal(actual, expected, message) {
if (actual != expected) fail(actual, expected, message, '==', assert.equal);
};
// 6. The non-equality assertion tests for whether two objects are not equal
// with != assert.notEqual(actual, expected, message_opt);
assert.notEqual = function notEqual(actual, expected, message) {
if (actual == expected) {
fail(actual, expected, message, '!=', assert.notEqual);
}
};
// 7. The equivalence assertion tests a deep equality relation.
// assert.deepEqual(actual, expected, message_opt);
assert.deepEqual = function deepEqual(actual, expected, message) {
if (!_deepEqual(actual, expected)) {
fail(actual, expected, message, 'deepEqual', assert.deepEqual);
}
};
function _deepEqual(actual, expected) {
// 7.1. All identical values are equivalent, as determined by ===.
if (actual === expected) {
return true;
// } else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
// if (actual.length != expected.length) return false;
//
// for (var i = 0; i < actual.length; i++) {
// if (actual[i] !== expected[i]) return false;
// }
//
// return true;
//
// 7.2. If the expected value is a Date object, the actual value is
// equivalent if it is also a Date object that refers to the same time.
} else if (actual instanceof Date && expected instanceof Date) {
return actual.getTime() === expected.getTime();
// 7.3 If the expected value is a RegExp object, the actual value is
// equivalent if it is also a RegExp object with the same source and
// properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
} else if (actual instanceof RegExp && expected instanceof RegExp) {
return actual.source === expected.source &&
actual.global === expected.global &&
actual.multiline === expected.multiline &&
actual.lastIndex === expected.lastIndex &&
actual.ignoreCase === expected.ignoreCase;
// 7.4. Other pairs that do not both pass typeof value == 'object',
// equivalence is determined by ==.
} else if (typeof actual != 'object' && typeof expected != 'object') {
return actual == expected;
// 7.5 For all other Object pairs, including Array objects, equivalence is
// determined by having the same number of owned properties (as verified
// with Object.prototype.hasOwnProperty.call), the same set of keys
// (although not necessarily the same order), equivalent values for every
// corresponding key, and an identical 'prototype' property. Note: this
// accounts for both named and indexed properties on Arrays.
} else {
return objEquiv(actual, expected);
}
}
function isUndefinedOrNull(value) {
return value === null || value === undefined;
}
function isArguments(object) {
return Object.prototype.toString.call(object) == '[object Arguments]';
}
function objEquiv(a, b) {
if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
return false;
// an identical 'prototype' property.
if (a.prototype !== b.prototype) return false;
//~~~I've managed to break Object.keys through screwy arguments passing.
// Converting to array solves the problem.
if (isArguments(a)) {
if (!isArguments(b)) {
return false;
}
a = pSlice.call(a);
b = pSlice.call(b);
return _deepEqual(a, b);
}
try {
var ka = Object.keys(a),
kb = Object.keys(b),
key, i;
} catch (e) {//happens when one is a string literal and the other isn't
return false;
}
// having the same number of owned properties (keys incorporates
// hasOwnProperty)
if (ka.length != kb.length)
return false;
//the same set of keys (although not necessarily the same order),
ka.sort();
kb.sort();
//~~~cheap key test
for (i = ka.length - 1; i >= 0; i--) {
if (ka[i] != kb[i])
return false;
}
//equivalent values for every corresponding key, and
//~~~possibly expensive deep test
for (i = ka.length - 1; i >= 0; i--) {
key = ka[i];
if (!_deepEqual(a[key], b[key])) return false;
}
return true;
}
// 8. The non-equivalence assertion tests for any deep inequality.
// assert.notDeepEqual(actual, expected, message_opt);
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
if (_deepEqual(actual, expected)) {
fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
}
};
// 9. The strict equality assertion tests strict equality, as determined by ===.
// assert.strictEqual(actual, expected, message_opt);
assert.strictEqual = function strictEqual(actual, expected, message) {
if (actual !== expected) {
fail(actual, expected, message, '===', assert.strictEqual);
}
};
// 10. The strict non-equality assertion tests for strict inequality, as
// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
if (actual === expected) {
fail(actual, expected, message, '!==', assert.notStrictEqual);
}
};
function expectedException(actual, expected) {
if (!actual || !expected) {
return false;
}
if (expected instanceof RegExp) {
return expected.test(actual);
} else if (actual instanceof expected) {
return true;
} else if (expected.call({}, actual) === true) {
return true;
}
return false;
}
function _throws(shouldThrow, block, expected, message) {
var actual;
if (typeof expected === 'string') {
message = expected;
expected = null;
}
try {
block();
} catch (e) {
actual = e;
}
message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
(message ? ' ' + message : '.');
if (shouldThrow && !actual) {
fail('Missing expected exception' + message);
}
if (!shouldThrow && expectedException(actual, expected)) {
fail('Got unwanted exception' + message);
}
if ((shouldThrow && actual && expected &&
!expectedException(actual, expected)) || (!shouldThrow && actual)) {
throw actual;
}
}
// 11. Expected to throw an error:
// assert.throws(block, Error_opt, message_opt);
assert.throws = function(block, /*optional*/error, /*optional*/message) {
_throws.apply(this, [true].concat(pSlice.call(arguments)));
};
// EXTENSION! This is annoying to write outside this module.
assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {
_throws.apply(this, [false].concat(pSlice.call(arguments)));
};
assert.ifError = function(err) { if (err) {throw err;}};
})(this);

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

241
lib/client/console/test/vendor/mocha.css vendored Normal file
View file

@ -0,0 +1,241 @@
@charset "utf-8";
body {
font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
padding: 60px 50px;
}
#mocha ul, #mocha li {
margin: 0;
padding: 0;
}
#mocha ul {
list-style: none;
}
#mocha h1, #mocha h2 {
margin: 0;
}
#mocha h1 {
margin-top: 15px;
font-size: 1em;
font-weight: 200;
}
#mocha h1 a {
text-decoration: none;
color: inherit;
}
#mocha h1 a:hover {
text-decoration: underline;
}
#mocha .suite .suite h1 {
margin-top: 0;
font-size: .8em;
}
.hidden {
display: none;
}
#mocha h2 {
font-size: 12px;
font-weight: normal;
cursor: pointer;
}
#mocha .suite {
margin-left: 15px;
}
#mocha .test {
margin-left: 15px;
overflow: hidden;
}
#mocha .test.pending:hover h2::after {
content: '(pending)';
font-family: arial;
}
#mocha .test.pass.medium .duration {
background: #C09853;
}
#mocha .test.pass.slow .duration {
background: #B94A48;
}
#mocha .test.pass::before {
content: '✓';
font-size: 12px;
display: block;
float: left;
margin-right: 5px;
color: #00d6b2;
}
#mocha .test.pass .duration {
font-size: 9px;
margin-left: 5px;
padding: 2px 5px;
color: white;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;
}
#mocha .test.pass.fast .duration {
display: none;
}
#mocha .test.pending {
color: #0b97c4;
}
#mocha .test.pending::before {
content: '◦';
color: #0b97c4;
}
#mocha .test.fail {
color: #c00;
}
#mocha .test.fail pre {
color: black;
}
#mocha .test.fail::before {
content: '✖';
font-size: 12px;
display: block;
float: left;
margin-right: 5px;
color: #c00;
}
#mocha .test pre.error {
color: #c00;
max-height: 300px;
overflow: auto;
}
#mocha .test pre {
display: block;
float: left;
clear: left;
font: 12px/1.5 monaco, monospace;
margin: 5px;
padding: 15px;
border: 1px solid #eee;
border-bottom-color: #ddd;
-webkit-border-radius: 3px;
-webkit-box-shadow: 0 1px 3px #eee;
-moz-border-radius: 3px;
-moz-box-shadow: 0 1px 3px #eee;
}
#mocha .test h2 {
position: relative;
}
#mocha .test a.replay {
position: absolute;
top: 3px;
right: 0;
text-decoration: none;
vertical-align: middle;
display: block;
width: 15px;
height: 15px;
line-height: 15px;
text-align: center;
background: #eee;
font-size: 15px;
-moz-border-radius: 15px;
border-radius: 15px;
-webkit-transition: opacity 200ms;
-moz-transition: opacity 200ms;
transition: opacity 200ms;
opacity: 0.3;
color: #888;
}
#mocha .test:hover a.replay {
opacity: 1;
}
#mocha-report.pass .test.fail {
display: none;
}
#mocha-report.fail .test.pass {
display: none;
}
#mocha-error {
color: #c00;
font-size: 1.5 em;
font-weight: 100;
letter-spacing: 1px;
}
#mocha-stats {
position: fixed;
top: 15px;
right: 10px;
font-size: 12px;
margin: 0;
color: #888;
}
#mocha-stats .progress {
float: right;
padding-top: 0;
}
#mocha-stats em {
color: black;
}
#mocha-stats a {
text-decoration: none;
color: inherit;
}
#mocha-stats a:hover {
border-bottom: 1px solid #eee;
}
#mocha-stats li {
display: inline-block;
margin: 0 5px;
list-style: none;
padding-top: 11px;
}
code .comment { color: #ddd }
code .init { color: #2F6FAD }
code .string { color: #5890AD }
code .keyword { color: #8A6343 }
code .number { color: #2F6FAD }
@media screen and (max-device-width: 480px) {
body {
padding: 60px 0px;
}
#stats {
position: absolute;
}
}

5341
lib/client/console/test/vendor/mocha.js vendored Normal file

File diff suppressed because it is too large Load diff