Update for underscore 1.8.3.
This commit is contained in:
parent
7c3686a5b3
commit
96712db8cb
|
@ -547,7 +547,7 @@ define([
|
||||||
'<% _.each(items, function(item) { %>',
|
'<% _.each(items, function(item) { %>',
|
||||||
'<li id="<%= item.id %>" data-value="<%= item.value %>"><a tabindex="-1" type="menuitem"><%= scope.getDisplayValue(item) %></a></li>',
|
'<li id="<%= item.id %>" data-value="<%= item.value %>"><a tabindex="-1" type="menuitem"><%= scope.getDisplayValue(item) %></a></li>',
|
||||||
'<% }); %>'
|
'<% }); %>'
|
||||||
].join(''), {
|
].join(''))({
|
||||||
items: this.store.toJSON(),
|
items: this.store.toJSON(),
|
||||||
scope: this
|
scope: this
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -353,7 +353,7 @@ define([
|
||||||
'<li id="<%= item.id %>">',
|
'<li id="<%= item.id %>">',
|
||||||
'<a class="font-item" tabindex="-1" type="menuitem" style="vertical-align:middle; margin: 0 0 0 -10px; height:<%=scope.getListItemHeight()%>px;"/>',
|
'<a class="font-item" tabindex="-1" type="menuitem" style="vertical-align:middle; margin: 0 0 0 -10px; height:<%=scope.getListItemHeight()%>px;"/>',
|
||||||
'</li>'
|
'</li>'
|
||||||
].join(''), {
|
].join(''))({
|
||||||
item: item.attributes,
|
item: item.attributes,
|
||||||
scope: this
|
scope: this
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -421,7 +421,7 @@ define([
|
||||||
_.extend(options, {
|
_.extend(options, {
|
||||||
cls: 'alert',
|
cls: 'alert',
|
||||||
onprimary: onKeyDown,
|
onprimary: onKeyDown,
|
||||||
tpl: _.template(template, options)
|
tpl: _.template(template)(options)
|
||||||
});
|
});
|
||||||
|
|
||||||
var win = new Common.UI.Window(options),
|
var win = new Common.UI.Window(options),
|
||||||
|
@ -556,7 +556,7 @@ define([
|
||||||
render : function() {
|
render : function() {
|
||||||
var renderto = this.initConfig.renderTo || document.body;
|
var renderto = this.initConfig.renderTo || document.body;
|
||||||
$(renderto).append(
|
$(renderto).append(
|
||||||
_.template(template, this.initConfig)
|
_.template(template)(this.initConfig)
|
||||||
);
|
);
|
||||||
|
|
||||||
this.$window = $('#' + this.initConfig.id);
|
this.$window = $('#' + this.initConfig.id);
|
||||||
|
|
|
@ -71,7 +71,7 @@ define([
|
||||||
'</div>'
|
'</div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
_options.tpl = _.template(this.template, _options);
|
_options.tpl = _.template(this.template)(_options);
|
||||||
|
|
||||||
this.handler = _options.handler;
|
this.handler = _options.handler;
|
||||||
this.toggleGroup = _options.toggleGroup;
|
this.toggleGroup = _options.toggleGroup;
|
||||||
|
|
|
@ -67,7 +67,7 @@ define([
|
||||||
|
|
||||||
templateUserList: _.template('<ul>' +
|
templateUserList: _.template('<ul>' +
|
||||||
'<% _.each(users, function(item) { %>' +
|
'<% _.each(users, function(item) { %>' +
|
||||||
'<%= _.template(usertpl, {user: item, scope: scope}) %>' +
|
'<%= _.template(usertpl)({user: item, scope: scope}) %>' +
|
||||||
'<% }); %>' +
|
'<% }); %>' +
|
||||||
'</ul>'),
|
'</ul>'),
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ define([
|
||||||
|
|
||||||
templateMsgList: _.template('<ul>' +
|
templateMsgList: _.template('<ul>' +
|
||||||
'<% _.each(messages, function(item) { %>' +
|
'<% _.each(messages, function(item) { %>' +
|
||||||
'<%= _.template(msgtpl, {msg: item, scope: scope}) %>' +
|
'<%= _.template(msgtpl)({msg: item, scope: scope}) %>' +
|
||||||
'<% }); %>' +
|
'<% }); %>' +
|
||||||
'</ul>'),
|
'</ul>'),
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ define([
|
||||||
|
|
||||||
_onAddUser: function(m, c, opts) {
|
_onAddUser: function(m, c, opts) {
|
||||||
if (this.panelUsers) {
|
if (this.panelUsers) {
|
||||||
this.panelUsers.find('ul').append(_.template(this.tplUser, {user: m, scope: this}));
|
this.panelUsers.find('ul').append(_.template(this.tplUser)({user: m, scope: this}));
|
||||||
this.panelUsers.scroller.update({minScrollbarLength : 25, alwaysVisibleY: true});
|
this.panelUsers.scroller.update({minScrollbarLength : 25, alwaysVisibleY: true});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -186,7 +186,7 @@ define([
|
||||||
var content = this.panelMessages.find('ul');
|
var content = this.panelMessages.find('ul');
|
||||||
if (content && content.length) {
|
if (content && content.length) {
|
||||||
this._prepareMessage(m);
|
this._prepareMessage(m);
|
||||||
content.append(_.template(this.tplMsg, {msg: m, scope: this}));
|
content.append(_.template(this.tplMsg)({msg: m, scope: this}));
|
||||||
|
|
||||||
// scroll to end
|
// scroll to end
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ define([
|
||||||
this.store = options.store;
|
this.store = options.store;
|
||||||
this.delegate = options.delegate;
|
this.delegate = options.delegate;
|
||||||
|
|
||||||
_options.tpl = _.template(this.template, _options);
|
_options.tpl = _.template(this.template)(_options);
|
||||||
|
|
||||||
this.arrow = {margin: 20, width: 12, height: 34};
|
this.arrow = {margin: 20, width: 12, height: 34};
|
||||||
this.sdkBounds = {width: 0, height: 0, padding: 10, paddingTop: 20};
|
this.sdkBounds = {width: 0, height: 0, padding: 10, paddingTop: 20};
|
||||||
|
|
|
@ -83,7 +83,7 @@ define([
|
||||||
'</div>'
|
'</div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
this.options.tpl = _.template(this.template, this.options);
|
this.options.tpl = _.template(this.template)(this.options);
|
||||||
|
|
||||||
Common.UI.Window.prototype.initialize.call(this, this.options);
|
Common.UI.Window.prototype.initialize.call(this, this.options);
|
||||||
},
|
},
|
||||||
|
|
|
@ -57,7 +57,7 @@ define([
|
||||||
'<div id="id-sharing-placeholder"></div>'
|
'<div id="id-sharing-placeholder"></div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
_options.tpl = _.template(this.template, _options);
|
_options.tpl = _.template(this.template)(_options);
|
||||||
|
|
||||||
this.settingsurl = options.settingsurl || '';
|
this.settingsurl = options.settingsurl || '';
|
||||||
Common.UI.Window.prototype.initialize.call(this, _options);
|
Common.UI.Window.prototype.initialize.call(this, _options);
|
||||||
|
|
|
@ -66,7 +66,7 @@ define([
|
||||||
'</div>'
|
'</div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
_options.tpl = _.template(this.template, _options);
|
_options.tpl = _.template(this.template)(_options);
|
||||||
|
|
||||||
this.handler = _options.handler;
|
this.handler = _options.handler;
|
||||||
this._chartData = null;
|
this._chartData = null;
|
||||||
|
|
|
@ -66,7 +66,7 @@ define([
|
||||||
'</div>'
|
'</div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
_options.tpl = _.template(this.template, _options);
|
_options.tpl = _.template(this.template)(_options);
|
||||||
|
|
||||||
this.handler = _options.handler;
|
this.handler = _options.handler;
|
||||||
this._mergeData = null;
|
this._mergeData = null;
|
||||||
|
|
|
@ -65,7 +65,7 @@ define([
|
||||||
'</div>'
|
'</div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
this.options.tpl = _.template(this.template, this.options);
|
this.options.tpl = _.template(this.template)(this.options);
|
||||||
|
|
||||||
Common.UI.Window.prototype.initialize.call(this, this.options);
|
Common.UI.Window.prototype.initialize.call(this, this.options);
|
||||||
},
|
},
|
||||||
|
|
|
@ -73,7 +73,7 @@ define([
|
||||||
'</div>'
|
'</div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
this.options.tpl = _.template(this.template, this.options);
|
this.options.tpl = _.template(this.template)(this.options);
|
||||||
|
|
||||||
Common.UI.Window.prototype.initialize.call(this, this.options);
|
Common.UI.Window.prototype.initialize.call(this, this.options);
|
||||||
},
|
},
|
||||||
|
|
|
@ -93,7 +93,7 @@ define([
|
||||||
this.codepages = options.codepages;
|
this.codepages = options.codepages;
|
||||||
this.settings = options.settings;
|
this.settings = options.settings;
|
||||||
|
|
||||||
_options.tpl = _.template(this.template, _options);
|
_options.tpl = _.template(this.template)(_options);
|
||||||
|
|
||||||
Common.UI.Window.prototype.initialize.call(this, _options);
|
Common.UI.Window.prototype.initialize.call(this, _options);
|
||||||
},
|
},
|
||||||
|
|
|
@ -314,7 +314,7 @@ define([
|
||||||
'<% } %>'
|
'<% } %>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
_options.tpl = _.template(this.template, _options);
|
_options.tpl = _.template(this.template)(_options);
|
||||||
|
|
||||||
this.url = options.url || '';
|
this.url = options.url || '';
|
||||||
Common.UI.Window.prototype.initialize.call(this, _options);
|
Common.UI.Window.prototype.initialize.call(this, _options);
|
||||||
|
|
|
@ -66,7 +66,7 @@ define([
|
||||||
'</div>'
|
'</div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
this.options.tpl = _.template(this.template, this.options);
|
this.options.tpl = _.template(this.template)(this.options);
|
||||||
|
|
||||||
Common.UI.Window.prototype.initialize.call(this, this.options);
|
Common.UI.Window.prototype.initialize.call(this, this.options);
|
||||||
},
|
},
|
||||||
|
|
|
@ -80,7 +80,7 @@ define([
|
||||||
this.store = options.store;
|
this.store = options.store;
|
||||||
this.delegate = options.delegate;
|
this.delegate = options.delegate;
|
||||||
|
|
||||||
_options.tpl = _.template(this.template, _options);
|
_options.tpl = _.template(this.template)(_options);
|
||||||
|
|
||||||
this.arrow = {margin: 20, width: 12, height: 34};
|
this.arrow = {margin: 20, width: 12, height: 34};
|
||||||
this.sdkBounds = {width: 0, height: 0, padding: 10, paddingTop: 20};
|
this.sdkBounds = {width: 0, height: 0, padding: 10, paddingTop: 20};
|
||||||
|
@ -616,7 +616,7 @@ define([
|
||||||
},
|
},
|
||||||
|
|
||||||
getPanel: function () {
|
getPanel: function () {
|
||||||
this.$el = $(_.template( template, {} ));
|
this.$el = $(_.template(template)( {} ));
|
||||||
|
|
||||||
if ( this.appConfig.canReview ) {
|
if ( this.appConfig.canReview ) {
|
||||||
this.btnPrev.render(this.$el.find('#btn-change-prev'));
|
this.btnPrev.render(this.$el.find('#btn-change-prev'));
|
||||||
|
|
|
@ -105,7 +105,7 @@
|
||||||
'</div>'
|
'</div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
this.options.tpl = _.template(this.template, this.options);
|
this.options.tpl = _.template(this.template)(this.options);
|
||||||
|
|
||||||
Common.UI.Window.prototype.initialize.call(this, this.options);
|
Common.UI.Window.prototype.initialize.call(this, this.options);
|
||||||
},
|
},
|
||||||
|
|
|
@ -81,7 +81,7 @@ define([
|
||||||
'</div>'
|
'</div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
this.options.tpl = _.template(this.template, this.options);
|
this.options.tpl = _.template(this.template)(this.options);
|
||||||
this.api = this.options.api;
|
this.api = this.options.api;
|
||||||
|
|
||||||
Common.UI.Window.prototype.initialize.call(this, this.options);
|
Common.UI.Window.prototype.initialize.call(this, this.options);
|
||||||
|
|
|
@ -54,7 +54,7 @@ define([
|
||||||
'<div id="id-mail-recepients-placeholder"></div>'
|
'<div id="id-mail-recepients-placeholder"></div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
_options.tpl = _.template(this.template, _options);
|
_options.tpl = _.template(this.template)(_options);
|
||||||
|
|
||||||
this.fileChoiceUrl = options.fileChoiceUrl || '';
|
this.fileChoiceUrl = options.fileChoiceUrl || '';
|
||||||
Common.UI.Window.prototype.initialize.call(this, _options);
|
Common.UI.Window.prototype.initialize.call(this, _options);
|
||||||
|
|
|
@ -55,7 +55,7 @@ define([
|
||||||
'<div id="id-mail-merge-folder-placeholder"></div>'
|
'<div id="id-mail-merge-folder-placeholder"></div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
_options.tpl = _.template(this.template, _options);
|
_options.tpl = _.template(this.template)(_options);
|
||||||
|
|
||||||
this.mergeFolderUrl = options.mergeFolderUrl || '';
|
this.mergeFolderUrl = options.mergeFolderUrl || '';
|
||||||
this.mergedFileUrl = options.mergedFileUrl || '';
|
this.mergedFileUrl = options.mergedFileUrl || '';
|
||||||
|
|
|
@ -89,7 +89,7 @@ define([
|
||||||
'</div>'
|
'</div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
this.options.tpl = _.template(this.template, this.options);
|
this.options.tpl = _.template(this.template)(this.options);
|
||||||
|
|
||||||
this.spinners = [];
|
this.spinners = [];
|
||||||
this._noApply = false;
|
this._noApply = false;
|
||||||
|
|
|
@ -79,7 +79,7 @@ define([
|
||||||
'</div>'
|
'</div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
this.options.tpl = _.template(this.template, this.options);
|
this.options.tpl = _.template(this.template)(this.options);
|
||||||
|
|
||||||
this.spinners = [];
|
this.spinners = [];
|
||||||
this._noApply = false;
|
this._noApply = false;
|
||||||
|
|
|
@ -430,7 +430,7 @@ define([
|
||||||
label: this.labelSelect,
|
label: this.labelSelect,
|
||||||
btns: {ok: this.btnOk, cancel: this.btnCancel}
|
btns: {ok: this.btnOk, cancel: this.btnCancel}
|
||||||
});
|
});
|
||||||
this.options.tpl = _.template(this.template, this.options);
|
this.options.tpl = _.template(this.template)(this.options);
|
||||||
|
|
||||||
Common.UI.Window.prototype.initialize.call(this, this.options);
|
Common.UI.Window.prototype.initialize.call(this, this.options);
|
||||||
},
|
},
|
||||||
|
|
|
@ -70,7 +70,7 @@ define([
|
||||||
'</div>'
|
'</div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
this.options.tpl = _.template(this.template, this.options);
|
this.options.tpl = _.template(this.template)(this.options);
|
||||||
|
|
||||||
Common.UI.Window.prototype.initialize.call(this, this.options);
|
Common.UI.Window.prototype.initialize.call(this, this.options);
|
||||||
},
|
},
|
||||||
|
|
|
@ -195,7 +195,7 @@ define([
|
||||||
{ caption: me.textTabHome, action: 'home', extcls: 'canedit'},
|
{ caption: me.textTabHome, action: 'home', extcls: 'canedit'},
|
||||||
{ caption: me.textTabInsert, action: 'ins', extcls: 'canedit'},
|
{ caption: me.textTabInsert, action: 'ins', extcls: 'canedit'},
|
||||||
{ caption: me.textTabLayout, action: 'layout', extcls: 'canedit'} ];
|
{ caption: me.textTabLayout, action: 'layout', extcls: 'canedit'} ];
|
||||||
config.$dom = $(_.template(template, config));
|
config.$dom = $(_.template(template)(config));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UI Components
|
* UI Components
|
||||||
|
@ -2476,7 +2476,7 @@ define([
|
||||||
var _elements = $tabs || config.$dom.find('.tabs');
|
var _elements = $tabs || config.$dom.find('.tabs');
|
||||||
var $target = _elements.find('a[data-tab=' + _after_action + ']');
|
var $target = _elements.find('a[data-tab=' + _after_action + ']');
|
||||||
if ( $target.length ) {
|
if ( $target.length ) {
|
||||||
$target.parent().after( _.template(_tplTab, tab) );
|
$target.parent().after( _.template(_tplTab)(tab) );
|
||||||
|
|
||||||
if ( panel ) {
|
if ( panel ) {
|
||||||
_elements = $panels || config.$dom.find('.box-panels > .panel');
|
_elements = $panels || config.$dom.find('.box-panels > .panel');
|
||||||
|
|
|
@ -175,7 +175,7 @@ define([
|
||||||
'</div>',
|
'</div>',
|
||||||
'</label>',
|
'</label>',
|
||||||
'</li>'
|
'</li>'
|
||||||
].join(''), {
|
].join(''))({
|
||||||
android: Framework7.prototype.device.android,
|
android: Framework7.prototype.device.android,
|
||||||
item: size,
|
item: size,
|
||||||
index: index,
|
index: index,
|
||||||
|
|
|
@ -203,7 +203,7 @@ define([
|
||||||
'<% }); %>',
|
'<% }); %>',
|
||||||
'</ul>',
|
'</ul>',
|
||||||
'<% }); %>'
|
'<% }); %>'
|
||||||
].join(''), {
|
].join(''))({
|
||||||
styles: styles
|
styles: styles
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,7 @@ define([
|
||||||
'</div>',
|
'</div>',
|
||||||
'<% }); %>',
|
'<% }); %>',
|
||||||
'</div>'
|
'</div>'
|
||||||
].join(''), {
|
].join(''))({
|
||||||
styles: styles
|
styles: styles
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ define([
|
||||||
render: function () {
|
render: function () {
|
||||||
var el = $(this.el),
|
var el = $(this.el),
|
||||||
me = this;
|
me = this;
|
||||||
el.html(_.template(this.template, {
|
el.html(_.template(this.template)({
|
||||||
scope: this
|
scope: this
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ define([
|
||||||
'</div>'
|
'</div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
this.options.tpl = _.template(this.template, this.options);
|
this.options.tpl = _.template(this.template)(this.options);
|
||||||
this.slides = this.options.slides;
|
this.slides = this.options.slides;
|
||||||
this.api = this.options.api;
|
this.api = this.options.api;
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ define([
|
||||||
'</div>'
|
'</div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
this.options.tpl = _.template(this.template, this.options);
|
this.options.tpl = _.template(this.template)(this.options);
|
||||||
|
|
||||||
this.spinners = [];
|
this.spinners = [];
|
||||||
this._noApply = false;
|
this._noApply = false;
|
||||||
|
|
|
@ -68,7 +68,7 @@ define([
|
||||||
'</div>'
|
'</div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
this.options.tpl = _.template(this.template, this.options);
|
this.options.tpl = _.template(this.template)(this.options);
|
||||||
|
|
||||||
this.spinners = [];
|
this.spinners = [];
|
||||||
this._noApply = false;
|
this._noApply = false;
|
||||||
|
|
|
@ -251,7 +251,7 @@ define([
|
||||||
{ caption: 'Home', action: 'home', extcls: 'canedit'},
|
{ caption: 'Home', action: 'home', extcls: 'canedit'},
|
||||||
{ caption: 'Insert', action: 'ins', extcls: 'canedit'} ];
|
{ caption: 'Insert', action: 'ins', extcls: 'canedit'} ];
|
||||||
|
|
||||||
config.$layout = $(_.template(template, config));
|
config.$layout = $(_.template(template)(config));
|
||||||
|
|
||||||
me.paragraphControls = [];
|
me.paragraphControls = [];
|
||||||
me.shapeControls = [];
|
me.shapeControls = [];
|
||||||
|
@ -1795,7 +1795,7 @@ define([
|
||||||
var _elements = $tabs || config.$layout.find('.tabs');
|
var _elements = $tabs || config.$layout.find('.tabs');
|
||||||
var $target = _elements.find('a[data-tab=' + _after_action + ']');
|
var $target = _elements.find('a[data-tab=' + _after_action + ']');
|
||||||
if ( $target.length ) {
|
if ( $target.length ) {
|
||||||
$target.parent().after( _.template(_tplTab, tab) );
|
$target.parent().after( _.template(_tplTab)(tab) );
|
||||||
|
|
||||||
if ( panel ) {
|
if ( panel ) {
|
||||||
_elements = $panels || config.$layout.find('.box-panels > .panel');
|
_elements = $panels || config.$layout.find('.box-panels > .panel');
|
||||||
|
|
|
@ -123,7 +123,7 @@ define([
|
||||||
'<% }); %>',
|
'<% }); %>',
|
||||||
'</ul>',
|
'</ul>',
|
||||||
'<% }); %>'
|
'<% }); %>'
|
||||||
].join(''), {
|
].join(''))({
|
||||||
layouts: layouts
|
layouts: layouts
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -203,7 +203,7 @@ define([
|
||||||
'<% }); %>',
|
'<% }); %>',
|
||||||
'</ul>',
|
'</ul>',
|
||||||
'<% }); %>'
|
'<% }); %>'
|
||||||
].join(''), {
|
].join(''))({
|
||||||
styles: styles
|
styles: styles
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -235,7 +235,7 @@ define([
|
||||||
'<% }); %>',
|
'<% }); %>',
|
||||||
'</ul>',
|
'</ul>',
|
||||||
'<% }); %>'
|
'<% }); %>'
|
||||||
].join(''), {
|
].join(''))({
|
||||||
layouts: layouts
|
layouts: layouts
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -268,7 +268,7 @@ define([
|
||||||
'<% }); %>',
|
'<% }); %>',
|
||||||
'</div>',
|
'</div>',
|
||||||
'<% }); %>'
|
'<% }); %>'
|
||||||
].join(''), {
|
].join(''))({
|
||||||
themes: themes
|
themes: themes
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -291,7 +291,7 @@ define([
|
||||||
'</label>',
|
'</label>',
|
||||||
'</li>',
|
'</li>',
|
||||||
'<% }); %>'
|
'<% }); %>'
|
||||||
].join(''), {
|
].join(''))({
|
||||||
android : Common.SharedSettings.get('android'),
|
android : Common.SharedSettings.get('android'),
|
||||||
types: _arrCurrentEffectTypes
|
types: _arrCurrentEffectTypes
|
||||||
});
|
});
|
||||||
|
|
|
@ -138,7 +138,7 @@ define([
|
||||||
'</div>',
|
'</div>',
|
||||||
'<% }); %>',
|
'<% }); %>',
|
||||||
'</div>'
|
'</div>'
|
||||||
].join(''), {
|
].join(''))({
|
||||||
styles: styles
|
styles: styles
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -93,7 +93,7 @@ define([
|
||||||
this.handler = options.handler;
|
this.handler = options.handler;
|
||||||
this.type = options.type || 'number';
|
this.type = options.type || 'number';
|
||||||
|
|
||||||
_options.tpl = _.template(this.template, _options);
|
_options.tpl = _.template(this.template)(_options);
|
||||||
|
|
||||||
Common.UI.Window.prototype.initialize.call(this, _options);
|
Common.UI.Window.prototype.initialize.call(this, _options);
|
||||||
},
|
},
|
||||||
|
@ -342,7 +342,7 @@ define([
|
||||||
this.api = options.api;
|
this.api = options.api;
|
||||||
this.handler = options.handler;
|
this.handler = options.handler;
|
||||||
|
|
||||||
_options.tpl = _.template(this.template, _options);
|
_options.tpl = _.template(this.template)(_options);
|
||||||
|
|
||||||
Common.UI.Window.prototype.initialize.call(this, _options);
|
Common.UI.Window.prototype.initialize.call(this, _options);
|
||||||
},
|
},
|
||||||
|
@ -516,7 +516,7 @@ define([
|
||||||
this.throughIndexes = [];
|
this.throughIndexes = [];
|
||||||
this.filteredIndexes = [];
|
this.filteredIndexes = [];
|
||||||
|
|
||||||
_options.tpl = _.template(this.template, _options);
|
_options.tpl = _.template(this.template)(_options);
|
||||||
|
|
||||||
Common.UI.Window.prototype.initialize.call(this, _options);
|
Common.UI.Window.prototype.initialize.call(this, _options);
|
||||||
},
|
},
|
||||||
|
|
|
@ -69,7 +69,7 @@ define([
|
||||||
'</div>'
|
'</div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
this.options.tpl = _.template(this.template, this.options);
|
this.options.tpl = _.template(this.template)(this.options);
|
||||||
|
|
||||||
Common.UI.Window.prototype.initialize.call(this, this.options);
|
Common.UI.Window.prototype.initialize.call(this, this.options);
|
||||||
},
|
},
|
||||||
|
|
|
@ -92,7 +92,7 @@ define([
|
||||||
this.formulasGroups = options.formulasGroups;
|
this.formulasGroups = options.formulasGroups;
|
||||||
this.handler = options.handler;
|
this.handler = options.handler;
|
||||||
|
|
||||||
_options.tpl = _.template(this.template, _options);
|
_options.tpl = _.template(this.template)(_options);
|
||||||
|
|
||||||
Common.UI.Window.prototype.initialize.call(this, _options);
|
Common.UI.Window.prototype.initialize.call(this, _options);
|
||||||
},
|
},
|
||||||
|
|
|
@ -99,7 +99,7 @@ define([
|
||||||
'</div>'
|
'</div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
this.options.tpl = _.template(this.template, this.options);
|
this.options.tpl = _.template(this.template)(this.options);
|
||||||
this.api = this.options.api;
|
this.api = this.options.api;
|
||||||
|
|
||||||
Common.UI.Window.prototype.initialize.call(this, this.options);
|
Common.UI.Window.prototype.initialize.call(this, this.options);
|
||||||
|
|
|
@ -67,7 +67,7 @@ define([
|
||||||
'</div>'
|
'</div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
this.options.tpl = _.template(this.template, this.options);
|
this.options.tpl = _.template(this.template)(this.options);
|
||||||
this.startvalue = this.options.startvalue;
|
this.startvalue = this.options.startvalue;
|
||||||
this.maxvalue = this.options.maxvalue;
|
this.maxvalue = this.options.maxvalue;
|
||||||
this.defaultUnit = this.options.defaultUnit;
|
this.defaultUnit = this.options.defaultUnit;
|
||||||
|
|
|
@ -68,7 +68,7 @@ define([
|
||||||
|
|
||||||
templateUserList: _.template('<ul>' +
|
templateUserList: _.template('<ul>' +
|
||||||
'<% _.each(users, function(item) { %>' +
|
'<% _.each(users, function(item) { %>' +
|
||||||
'<%= _.template(usertpl, {user: item, scope: scope}) %>' +
|
'<%= _.template(usertpl)({user: item, scope: scope}) %>' +
|
||||||
'<% }); %>' +
|
'<% }); %>' +
|
||||||
'</ul>'),
|
'</ul>'),
|
||||||
|
|
||||||
|
@ -489,7 +489,7 @@ define([
|
||||||
|
|
||||||
_onAddUser: function(m, c, opts) {
|
_onAddUser: function(m, c, opts) {
|
||||||
if (this.panelUsersList) {
|
if (this.panelUsersList) {
|
||||||
this.panelUsersList.find('ul').append(_.template(this.tplUser, {user: m, scope: this}));
|
this.panelUsersList.find('ul').append(_.template(this.tplUser)({user: m, scope: this}));
|
||||||
this.panelUsersList.scroller.update({minScrollbarLength : 40, alwaysVisibleY: true});
|
this.panelUsersList.scroller.update({minScrollbarLength : 40, alwaysVisibleY: true});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -706,7 +706,7 @@ define([
|
||||||
label: this.labelSheetName,
|
label: this.labelSheetName,
|
||||||
btns: {ok: this.okButtonText, cancel: this.cancelButtonText}
|
btns: {ok: this.okButtonText, cancel: this.cancelButtonText}
|
||||||
});
|
});
|
||||||
this.options.tpl = _.template(this.template, this.options);
|
this.options.tpl = _.template(this.template)(this.options);
|
||||||
|
|
||||||
Common.UI.Window.prototype.initialize.call(this, this.options);
|
Common.UI.Window.prototype.initialize.call(this, this.options);
|
||||||
},
|
},
|
||||||
|
@ -823,7 +823,7 @@ define([
|
||||||
label: options.ismove ? this.textMoveBefore : this.textCopyBefore,
|
label: options.ismove ? this.textMoveBefore : this.textCopyBefore,
|
||||||
btns: {ok: this.okButtonText, cancel: this.cancelButtonText}
|
btns: {ok: this.okButtonText, cancel: this.cancelButtonText}
|
||||||
});
|
});
|
||||||
this.options.tpl = _.template(this.template, this.options);
|
this.options.tpl = _.template(this.template)(this.options);
|
||||||
|
|
||||||
Common.UI.Window.prototype.initialize.call(this, this.options);
|
Common.UI.Window.prototype.initialize.call(this, this.options);
|
||||||
},
|
},
|
||||||
|
|
|
@ -72,7 +72,7 @@ define([
|
||||||
'</div>'
|
'</div>'
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
this.options.tpl = _.template(this.template, this.options);
|
this.options.tpl = _.template(this.template)(this.options);
|
||||||
this.checkRangeType = Asc.c_oAscSelectionDialogType.FormatTable;
|
this.checkRangeType = Asc.c_oAscSelectionDialogType.FormatTable;
|
||||||
this.selectionType = Asc.c_oAscSelectionType.RangeCells;
|
this.selectionType = Asc.c_oAscSelectionType.RangeCells;
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ define([
|
||||||
};
|
};
|
||||||
|
|
||||||
_.extend(_params, args);
|
_.extend(_params, args);
|
||||||
var $content = $('<div/>').append(_.template(this.template, _params));
|
var $content = $('<div/>').append(_.template(this.template)(_params));
|
||||||
|
|
||||||
// Android fix for navigation
|
// Android fix for navigation
|
||||||
if (Framework7.prototype.device.android) {
|
if (Framework7.prototype.device.android) {
|
||||||
|
@ -121,7 +121,7 @@ define([
|
||||||
'Logical': me.sCatLogical
|
'Logical': me.sCatLogical
|
||||||
};
|
};
|
||||||
|
|
||||||
me.layout = $('<div/>').append(_.template(me.template, {
|
me.layout = $('<div/>').append(_.template(me.template)({
|
||||||
android : Common.SharedSettings.get('android'),
|
android : Common.SharedSettings.get('android'),
|
||||||
phone : Common.SharedSettings.get('phone'),
|
phone : Common.SharedSettings.get('phone'),
|
||||||
textGroups : me.textGroups,
|
textGroups : me.textGroups,
|
||||||
|
|
|
@ -210,7 +210,7 @@ define([
|
||||||
'<% }) %>';
|
'<% }) %>';
|
||||||
|
|
||||||
this.layout.find('#add-link-sheet select').html(
|
this.layout.find('#add-link-sheet select').html(
|
||||||
_.template(tpl, {
|
_.template(tpl)({
|
||||||
worksheets: sheets
|
worksheets: sheets
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -219,7 +219,7 @@ define([
|
||||||
|
|
||||||
if ($view.length > 0) {
|
if ($view.length > 0) {
|
||||||
$view.find('#add-link-sheet select').html(
|
$view.find('#add-link-sheet select').html(
|
||||||
_.template(tpl, {
|
_.template(tpl)({
|
||||||
worksheets: sheets
|
worksheets: sheets
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
@ -76,8 +76,7 @@ define([
|
||||||
}
|
}
|
||||||
|
|
||||||
mapNavigation =
|
mapNavigation =
|
||||||
el = _.template(tplNavigation,
|
el = _.template(tplNavigation)({
|
||||||
{
|
|
||||||
android : Common.SharedSettings.get('android'),
|
android : Common.SharedSettings.get('android'),
|
||||||
phone : Common.SharedSettings.get('phone'),
|
phone : Common.SharedSettings.get('phone'),
|
||||||
textBack : this.textBack,
|
textBack : this.textBack,
|
||||||
|
|
|
@ -133,7 +133,7 @@ define([
|
||||||
'<% }); %>',
|
'<% }); %>',
|
||||||
'</ul>',
|
'</ul>',
|
||||||
'<% }); %>'
|
'<% }); %>'
|
||||||
].join(''), {
|
].join(''))({
|
||||||
styles: styles,
|
styles: styles,
|
||||||
styleSize: styleSize
|
styleSize: styleSize
|
||||||
});
|
});
|
||||||
|
|
|
@ -160,7 +160,7 @@ define([
|
||||||
'<% }); %>',
|
'<% }); %>',
|
||||||
'</ul>',
|
'</ul>',
|
||||||
'<% }); %>'
|
'<% }); %>'
|
||||||
].join(''), {
|
].join(''))({
|
||||||
styles: styles
|
styles: styles
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
93
vendor/underscore/.eslintrc
vendored
Normal file
93
vendor/underscore/.eslintrc
vendored
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"node": true,
|
||||||
|
"amd": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"rules": {
|
||||||
|
"array-bracket-spacing": [2],
|
||||||
|
"block-scoped-var": 1,
|
||||||
|
"brace-style": [1, "1tbs"],
|
||||||
|
"camelcase": 2,
|
||||||
|
"comma-dangle": [2, "never"],
|
||||||
|
"comma-spacing": 2,
|
||||||
|
"computed-property-spacing": [2, "never"],
|
||||||
|
"consistent-return": 1,
|
||||||
|
"dot-notation": [2, { "allowKeywords": false }],
|
||||||
|
"eol-last": 2,
|
||||||
|
"eqeqeq": [2, "smart"],
|
||||||
|
"indent": [2, 2, {"SwitchCase": 1, "VariableDeclarator": 2}],
|
||||||
|
"key-spacing": 1,
|
||||||
|
"linebreak-style": 2,
|
||||||
|
"max-depth": [1, 4],
|
||||||
|
"max-params": [1, 5],
|
||||||
|
"new-cap": 2,
|
||||||
|
"no-alert": 2,
|
||||||
|
"no-caller": 2,
|
||||||
|
"no-catch-shadow": 2,
|
||||||
|
"no-console": 2,
|
||||||
|
"no-debugger": 2,
|
||||||
|
"no-delete-var": 2,
|
||||||
|
"no-div-regex": 1,
|
||||||
|
"no-dupe-args": 2,
|
||||||
|
"no-dupe-keys": 2,
|
||||||
|
"no-duplicate-case": 2,
|
||||||
|
"no-else-return": 1,
|
||||||
|
"no-empty-character-class": 2,
|
||||||
|
"no-empty-label": 2,
|
||||||
|
"no-eval": 2,
|
||||||
|
"no-ex-assign": 2,
|
||||||
|
"no-extend-native": 2,
|
||||||
|
"no-extra-boolean-cast": 2,
|
||||||
|
"no-extra-parens": 1,
|
||||||
|
"no-extra-semi": 2,
|
||||||
|
"no-fallthrough": 2,
|
||||||
|
"no-floating-decimal": 2,
|
||||||
|
"no-func-assign": 2,
|
||||||
|
"no-implied-eval": 2,
|
||||||
|
"no-inner-declarations": 2,
|
||||||
|
"no-irregular-whitespace": 2,
|
||||||
|
"no-label-var": 2,
|
||||||
|
"no-lone-blocks": 2,
|
||||||
|
"no-lonely-if": 2,
|
||||||
|
"no-multi-spaces": 1,
|
||||||
|
"no-multi-str": 2,
|
||||||
|
"no-native-reassign": 2,
|
||||||
|
"no-negated-in-lhs": 1,
|
||||||
|
"no-nested-ternary": 2,
|
||||||
|
"no-new-object": 2,
|
||||||
|
"no-new-wrappers": 2,
|
||||||
|
"no-obj-calls": 2,
|
||||||
|
"no-octal": 2,
|
||||||
|
"no-octal-escape": 2,
|
||||||
|
"no-proto": 2,
|
||||||
|
"no-redeclare": 2,
|
||||||
|
"no-shadow": 2,
|
||||||
|
"no-spaced-func": 2,
|
||||||
|
"no-throw-literal": 2,
|
||||||
|
"no-trailing-spaces": 2,
|
||||||
|
"no-undef": 2,
|
||||||
|
"no-undef-init": 2,
|
||||||
|
"no-undefined": 2,
|
||||||
|
"no-unneeded-ternary": 2,
|
||||||
|
"no-unreachable": 2,
|
||||||
|
"no-unused-expressions": 2,
|
||||||
|
"no-unused-vars": 2,
|
||||||
|
"no-use-before-define": [1, "nofunc"],
|
||||||
|
"no-with": 2,
|
||||||
|
"object-curly-spacing": [2, "never"],
|
||||||
|
"quote-props": [1, "as-needed"],
|
||||||
|
"quotes": [2, "single", "avoid-escape"],
|
||||||
|
"radix": 2,
|
||||||
|
"semi": 2,
|
||||||
|
"space-after-keywords": [2, "always"],
|
||||||
|
"space-before-function-paren": [2, {"anonymous": "never", "named": "never"}],
|
||||||
|
"space-infix-ops": 2,
|
||||||
|
"space-return-throw-case": 2,
|
||||||
|
"space-unary-ops": [2, { "words": true, "nonwords": false }],
|
||||||
|
"use-isnan": 2,
|
||||||
|
"valid-typeof": 2,
|
||||||
|
"wrap-iife": 2
|
||||||
|
}
|
||||||
|
}
|
5
vendor/underscore/.gitignore
vendored
5
vendor/underscore/.gitignore
vendored
|
@ -1,2 +1,7 @@
|
||||||
raw
|
raw
|
||||||
node_modules
|
node_modules
|
||||||
|
*.log
|
||||||
|
*.idea
|
||||||
|
*.swp
|
||||||
|
nyc_output
|
||||||
|
coverage
|
||||||
|
|
27
vendor/underscore/.travis.yml
vendored
27
vendor/underscore/.travis.yml
vendored
|
@ -1,5 +1,30 @@
|
||||||
language: node_js
|
language: node_js
|
||||||
|
sudo: false
|
||||||
node_js:
|
node_js:
|
||||||
- 0.8
|
- "0.8"
|
||||||
|
- "0.10"
|
||||||
|
- "0.12"
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- node_js: "4.0"
|
||||||
|
env: BROWSER=true
|
||||||
|
before_install:
|
||||||
|
- npm install -g npm@2.6
|
||||||
|
- npm install -g karma-cli
|
||||||
|
before_script:
|
||||||
|
- npm install karma-sauce-launcher
|
||||||
|
- export DISPLAY=:99.0
|
||||||
|
- sh -e /etc/init.d/xvfb start
|
||||||
|
script:
|
||||||
|
- npm test
|
||||||
|
- "[ $BROWSER == false ] || npm run test-browser"
|
||||||
|
- "[ $BROWSER == false ] || karma start karma.conf-sauce.js"
|
||||||
notifications:
|
notifications:
|
||||||
email: false
|
email: false
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
- NPM_CONFIG_PROGRESS="false"
|
||||||
|
- secure: bDZSBQfqr21hCayjcZ20IxrV6+XGhxQPFIfwWqEKLrF93Gu8LLVjZRxXE/mE8I8N4Z5WtDNb4ZHrm/TTzmcPa5MuHgIxEdknQCncobH8oimwc83SHwEPk6okeNKl39VlCjvvnmoe/V/KpnknuYn3Rqghtl/Uv9KLpCwskwjTtcw=
|
||||||
|
- secure: SRECgXuwcZTcD3GVxTS2bYNgRyye4vq6BLrV2PH9FyNenowsKQR2EwlC/dppc1Q8NWMgv79J/R96q9JOFh+mEH9L5dlBb2yhnGH8amVeM/ChAJHT/F8YktKM453uVpz5fR00QcCQDDUOx6Pvx374ID0OKNpWKAkQBWA9mPTsLnE=
|
||||||
|
matrix: BROWSER=false
|
||||||
|
after_success: npm run coveralls
|
||||||
|
|
93
vendor/underscore/CODE_OF_CONDUCT.md
vendored
Normal file
93
vendor/underscore/CODE_OF_CONDUCT.md
vendored
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
In the interest of fostering an open and welcoming environment, we as
|
||||||
|
contributors and maintainers pledge to making participation in our project and
|
||||||
|
our community a harassment-free experience for everyone, regardless of age, body
|
||||||
|
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||||
|
nationality, personal appearance, race, religion, or sexual identity and
|
||||||
|
orientation.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to creating a positive environment
|
||||||
|
include:
|
||||||
|
|
||||||
|
* Using welcoming and inclusive language
|
||||||
|
* Being respectful of differing viewpoints and experiences
|
||||||
|
* Gracefully accepting constructive criticism
|
||||||
|
* Focusing on what is best for the community
|
||||||
|
* Showing empathy towards other community members
|
||||||
|
|
||||||
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||||
|
advances
|
||||||
|
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or electronic
|
||||||
|
address, without explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
|
professional setting
|
||||||
|
|
||||||
|
## Our Responsibilities
|
||||||
|
|
||||||
|
Project maintainers are responsible for clarifying the standards of acceptable
|
||||||
|
behavior and are expected to take appropriate and fair corrective action in
|
||||||
|
response to any instances of unacceptable behavior.
|
||||||
|
|
||||||
|
Project maintainers have the right and responsibility to remove, edit, or
|
||||||
|
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||||
|
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||||
|
permanently any contributor for other behaviors that they deem inappropriate,
|
||||||
|
threatening, offensive, or harmful.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies both within project spaces and in public spaces
|
||||||
|
when an individual is representing the project or its community. Examples of
|
||||||
|
representing a project or community include using an official project e-mail
|
||||||
|
address, posting via an official social media account, or acting as an appointed
|
||||||
|
representative at an online or offline event. Representation of a project may be
|
||||||
|
further defined and clarified by project maintainers.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported by contacting the project team at jashkenas@gmail.com. The project team
|
||||||
|
will review and investigate all complaints, and will respond in a way that it deems
|
||||||
|
appropriate to the circumstances. The project team is obligated to maintain
|
||||||
|
confidentiality with regard to the reporter of an incident.
|
||||||
|
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||||
|
faith may face temporary or permanent repercussions as determined by other
|
||||||
|
members of the project's leadership.
|
||||||
|
|
||||||
|
## Moderation
|
||||||
|
|
||||||
|
Edits of another user's comment must be clearly marked with "**edit**", the
|
||||||
|
moderator's username, and a timestamp for each occurrence. The only acceptable
|
||||||
|
reasons for editing another user's comment are:
|
||||||
|
|
||||||
|
1. to edit out violations of Our Pledge. These edits must include a rationale.
|
||||||
|
2. to direct future readers to a relevant point later in the conversation
|
||||||
|
(usually the resolution). These edits must be append-only.
|
||||||
|
|
||||||
|
Deletion of another user's comment is only acceptable when the comment includes
|
||||||
|
no original value, such as "+1", ":+1:", or "me too".
|
||||||
|
|
||||||
|
## Self-Moderation
|
||||||
|
|
||||||
|
Edits of your own comment after someone has responded must be append-only and
|
||||||
|
clearly marked with "**edit**". Typographical and formatting fixes to your own
|
||||||
|
comment which do not affect its meaning are exempt from this requirement.
|
||||||
|
Deletion of your own comment is only acceptable before any later comments have
|
||||||
|
been posted.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||||
|
available at [http://contributor-covenant.org/version/1/4][version]
|
||||||
|
|
||||||
|
[homepage]: http://contributor-covenant.org
|
||||||
|
[version]: http://contributor-covenant.org/version/1/4/
|
4
vendor/underscore/CONTRIBUTING.md
vendored
4
vendor/underscore/CONTRIBUTING.md
vendored
|
@ -1,7 +1,11 @@
|
||||||
## How to contribute to Underscore.js
|
## How to contribute to Underscore.js
|
||||||
|
|
||||||
|
* This project adheres to a [code of conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code.
|
||||||
|
|
||||||
* Before you open a ticket or send a pull request, [search](https://github.com/jashkenas/underscore/issues) for previous discussions about the same feature or issue. Add to the earlier ticket if you find one.
|
* Before you open a ticket or send a pull request, [search](https://github.com/jashkenas/underscore/issues) for previous discussions about the same feature or issue. Add to the earlier ticket if you find one.
|
||||||
|
|
||||||
|
* If you're proposing a new feature, make sure it isn't already implemented in [Underscore-Contrib](https://github.com/documentcloud/underscore-contrib).
|
||||||
|
|
||||||
* Before sending a pull request for a feature, be sure to have [tests](http://underscorejs.org/test/).
|
* Before sending a pull request for a feature, be sure to have [tests](http://underscorejs.org/test/).
|
||||||
|
|
||||||
* Use the same coding style as the rest of the [codebase](https://github.com/jashkenas/underscore/blob/master/underscore.js).
|
* Use the same coding style as the rest of the [codebase](https://github.com/jashkenas/underscore/blob/master/underscore.js).
|
||||||
|
|
2
vendor/underscore/LICENSE
vendored
2
vendor/underscore/LICENSE
vendored
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative
|
Copyright (c) 2009-2017 Jeremy Ashkenas, DocumentCloud and Investigative
|
||||||
Reporters & Editors
|
Reporters & Editors
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
|
6
vendor/underscore/README.md
vendored
6
vendor/underscore/README.md
vendored
|
@ -12,9 +12,15 @@ Underscore.js is a utility-belt library for JavaScript that provides
|
||||||
support for the usual functional suspects (each, map, reduce, filter...)
|
support for the usual functional suspects (each, map, reduce, filter...)
|
||||||
without extending any core JavaScript objects.
|
without extending any core JavaScript objects.
|
||||||
|
|
||||||
|
This project adheres to a [code of conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code.
|
||||||
|
|
||||||
For Docs, License, Tests, and pre-packed downloads, see:
|
For Docs, License, Tests, and pre-packed downloads, see:
|
||||||
http://underscorejs.org
|
http://underscorejs.org
|
||||||
|
|
||||||
|
For support and questions, please use
|
||||||
|
[the gitter channel](https://gitter.im/jashkenas/underscore)
|
||||||
|
or [stackoverflow](http://stackoverflow.com/search?q=underscore.js)
|
||||||
|
|
||||||
Underscore is an open-sourced component of DocumentCloud:
|
Underscore is an open-sourced component of DocumentCloud:
|
||||||
https://github.com/documentcloud
|
https://github.com/documentcloud
|
||||||
|
|
||||||
|
|
6
vendor/underscore/bower.json
vendored
Normal file
6
vendor/underscore/bower.json
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"name": "underscore",
|
||||||
|
"main": "underscore.js",
|
||||||
|
"keywords": ["util", "functional", "server", "client", "browser"],
|
||||||
|
"ignore" : ["docs", "test", "*.yml", "CNAME", "index.html", "favicon.ico", "CONTRIBUTING.md", ".*", "package.json", "karma.*"]
|
||||||
|
}
|
5
vendor/underscore/docs/.eslintrc
vendored
Normal file
5
vendor/underscore/docs/.eslintrc
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"globals": {
|
||||||
|
"_": true
|
||||||
|
}
|
||||||
|
}
|
154
vendor/underscore/docs/docco.css
vendored
154
vendor/underscore/docs/docco.css
vendored
|
@ -21,11 +21,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'novecento-bold';
|
font-family: 'roboto-black';
|
||||||
src: url('public/fonts/novecento-bold.eot');
|
src: url('public/fonts/roboto-black.eot');
|
||||||
src: url('public/fonts/novecento-bold.eot?#iefix') format('embedded-opentype'),
|
src: url('public/fonts/roboto-black.eot?#iefix') format('embedded-opentype'),
|
||||||
url('public/fonts/novecento-bold.woff') format('woff'),
|
url('public/fonts/roboto-black.woff') format('woff'),
|
||||||
url('public/fonts/novecento-bold.ttf') format('truetype');
|
url('public/fonts/roboto-black.ttf') format('truetype');
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
@ -51,15 +51,23 @@ b, strong {
|
||||||
font-family: "aller-bold";
|
font-family: "aller-bold";
|
||||||
}
|
}
|
||||||
|
|
||||||
p, ul, ol {
|
p {
|
||||||
margin: 15px 0 0px;
|
margin: 15px 0 0px;
|
||||||
}
|
}
|
||||||
|
.annotation ul, .annotation ol {
|
||||||
|
margin: 25px 0;
|
||||||
|
}
|
||||||
|
.annotation ul li, .annotation ol li {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 18px;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
h1, h2, h3, h4, h5, h6 {
|
h1, h2, h3, h4, h5, h6 {
|
||||||
color: #112233;
|
color: #112233;
|
||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-family: "novecento-bold";
|
font-family: "roboto-black";
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
margin: 30px 0 15px 0;
|
margin: 30px 0 15px 0;
|
||||||
}
|
}
|
||||||
|
@ -67,10 +75,13 @@ h1, h2, h3, h4, h5, h6 {
|
||||||
h1 {
|
h1 {
|
||||||
margin-top: 40px;
|
margin-top: 40px;
|
||||||
}
|
}
|
||||||
|
h2 {
|
||||||
|
font-size: 1.26em;
|
||||||
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: 0;
|
border: 0;
|
||||||
background: 1px solid #ddd;
|
background: 1px #ddd;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
}
|
}
|
||||||
|
@ -172,9 +183,18 @@ ul.sections > li > div {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#jump_page_wrapper{
|
||||||
|
position: fixed;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
#jump_page {
|
#jump_page {
|
||||||
padding: 5px 0 3px;
|
padding: 5px 0 3px;
|
||||||
margin: 0 0 25px 25px;
|
margin: 0 0 25px 25px;
|
||||||
|
max-height: 100%;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
#jump_page .source {
|
#jump_page .source {
|
||||||
|
@ -205,7 +225,6 @@ ul.sections > li > div {
|
||||||
}
|
}
|
||||||
|
|
||||||
ul.sections > li > div.content {
|
ul.sections > li > div.content {
|
||||||
background: #f5f5ff;
|
|
||||||
overflow-x:auto;
|
overflow-x:auto;
|
||||||
-webkit-box-shadow: inset 0 0 5px #e5e5ee;
|
-webkit-box-shadow: inset 0 0 5px #e5e5ee;
|
||||||
box-shadow: inset 0 0 5px #e5e5ee;
|
box-shadow: inset 0 0 5px #e5e5ee;
|
||||||
|
@ -306,7 +325,6 @@ ul.sections > li > div {
|
||||||
ul.sections > li > div.content {
|
ul.sections > li > div.content {
|
||||||
padding: 13px;
|
padding: 13px;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
background: #f5f5ff;
|
|
||||||
border: none;
|
border: none;
|
||||||
-webkit-box-shadow: none;
|
-webkit-box-shadow: none;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
@ -376,125 +394,125 @@ pre code {
|
||||||
background: #f8f8ff
|
background: #f8f8ff
|
||||||
}
|
}
|
||||||
|
|
||||||
pre .comment,
|
pre .hljs-comment,
|
||||||
pre .template_comment,
|
pre .hljs-template_comment,
|
||||||
pre .diff .header,
|
pre .hljs-diff .hljs-header,
|
||||||
pre .javadoc {
|
pre .hljs-javadoc {
|
||||||
color: #408080;
|
color: #408080;
|
||||||
font-style: italic
|
font-style: italic
|
||||||
}
|
}
|
||||||
|
|
||||||
pre .keyword,
|
pre .hljs-keyword,
|
||||||
pre .assignment,
|
pre .hljs-assignment,
|
||||||
pre .literal,
|
pre .hljs-literal,
|
||||||
pre .css .rule .keyword,
|
pre .hljs-css .hljs-rule .hljs-keyword,
|
||||||
pre .winutils,
|
pre .hljs-winutils,
|
||||||
pre .javascript .title,
|
pre .hljs-javascript .hljs-title,
|
||||||
pre .lisp .title,
|
pre .hljs-lisp .hljs-title,
|
||||||
pre .subst {
|
pre .hljs-subst {
|
||||||
color: #954121;
|
color: #954121;
|
||||||
/*font-weight: bold*/
|
/*font-weight: bold*/
|
||||||
}
|
}
|
||||||
|
|
||||||
pre .number,
|
pre .hljs-number,
|
||||||
pre .hexcolor {
|
pre .hljs-hexcolor {
|
||||||
color: #40a070
|
color: #40a070
|
||||||
}
|
}
|
||||||
|
|
||||||
pre .string,
|
pre .hljs-string,
|
||||||
pre .tag .value,
|
pre .hljs-tag .hljs-value,
|
||||||
pre .phpdoc,
|
pre .hljs-phpdoc,
|
||||||
pre .tex .formula {
|
pre .hljs-tex .hljs-formula {
|
||||||
color: #219161;
|
color: #219161;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre .title,
|
pre .hljs-title,
|
||||||
pre .id {
|
pre .hljs-id {
|
||||||
color: #19469D;
|
color: #19469D;
|
||||||
}
|
}
|
||||||
pre .params {
|
pre .hljs-params {
|
||||||
color: #00F;
|
color: #00F;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre .javascript .title,
|
pre .hljs-javascript .hljs-title,
|
||||||
pre .lisp .title,
|
pre .hljs-lisp .hljs-title,
|
||||||
pre .subst {
|
pre .hljs-subst {
|
||||||
font-weight: normal
|
font-weight: normal
|
||||||
}
|
}
|
||||||
|
|
||||||
pre .class .title,
|
pre .hljs-class .hljs-title,
|
||||||
pre .haskell .label,
|
pre .hljs-haskell .hljs-label,
|
||||||
pre .tex .command {
|
pre .hljs-tex .hljs-command {
|
||||||
color: #458;
|
color: #458;
|
||||||
font-weight: bold
|
font-weight: bold
|
||||||
}
|
}
|
||||||
|
|
||||||
pre .tag,
|
pre .hljs-tag,
|
||||||
pre .tag .title,
|
pre .hljs-tag .hljs-title,
|
||||||
pre .rules .property,
|
pre .hljs-rules .hljs-property,
|
||||||
pre .django .tag .keyword {
|
pre .hljs-django .hljs-tag .hljs-keyword {
|
||||||
color: #000080;
|
color: #000080;
|
||||||
font-weight: normal
|
font-weight: normal
|
||||||
}
|
}
|
||||||
|
|
||||||
pre .attribute,
|
pre .hljs-attribute,
|
||||||
pre .variable,
|
pre .hljs-variable,
|
||||||
pre .instancevar,
|
pre .hljs-instancevar,
|
||||||
pre .lisp .body {
|
pre .hljs-lisp .hljs-body {
|
||||||
color: #008080
|
color: #008080
|
||||||
}
|
}
|
||||||
|
|
||||||
pre .regexp {
|
pre .hljs-regexp {
|
||||||
color: #B68
|
color: #B68
|
||||||
}
|
}
|
||||||
|
|
||||||
pre .class {
|
pre .hljs-class {
|
||||||
color: #458;
|
color: #458;
|
||||||
font-weight: bold
|
font-weight: bold
|
||||||
}
|
}
|
||||||
|
|
||||||
pre .symbol,
|
pre .hljs-symbol,
|
||||||
pre .ruby .symbol .string,
|
pre .hljs-ruby .hljs-symbol .hljs-string,
|
||||||
pre .ruby .symbol .keyword,
|
pre .hljs-ruby .hljs-symbol .hljs-keyword,
|
||||||
pre .ruby .symbol .keymethods,
|
pre .hljs-ruby .hljs-symbol .hljs-keymethods,
|
||||||
pre .lisp .keyword,
|
pre .hljs-lisp .hljs-keyword,
|
||||||
pre .tex .special,
|
pre .hljs-tex .hljs-special,
|
||||||
pre .input_number {
|
pre .hljs-input_number {
|
||||||
color: #990073
|
color: #990073
|
||||||
}
|
}
|
||||||
|
|
||||||
pre .builtin,
|
pre .hljs-builtin,
|
||||||
pre .constructor,
|
pre .hljs-constructor,
|
||||||
pre .built_in,
|
pre .hljs-built_in,
|
||||||
pre .lisp .title {
|
pre .hljs-lisp .hljs-title {
|
||||||
color: #0086b3
|
color: #0086b3
|
||||||
}
|
}
|
||||||
|
|
||||||
pre .preprocessor,
|
pre .hljs-preprocessor,
|
||||||
pre .pi,
|
pre .hljs-pi,
|
||||||
pre .doctype,
|
pre .hljs-doctype,
|
||||||
pre .shebang,
|
pre .hljs-shebang,
|
||||||
pre .cdata {
|
pre .hljs-cdata {
|
||||||
color: #999;
|
color: #999;
|
||||||
font-weight: bold
|
font-weight: bold
|
||||||
}
|
}
|
||||||
|
|
||||||
pre .deletion {
|
pre .hljs-deletion {
|
||||||
background: #fdd
|
background: #fdd
|
||||||
}
|
}
|
||||||
|
|
||||||
pre .addition {
|
pre .hljs-addition {
|
||||||
background: #dfd
|
background: #dfd
|
||||||
}
|
}
|
||||||
|
|
||||||
pre .diff .change {
|
pre .hljs-diff .hljs-change {
|
||||||
background: #0086b3
|
background: #0086b3
|
||||||
}
|
}
|
||||||
|
|
||||||
pre .chunk {
|
pre .hljs-chunk {
|
||||||
color: #aaa
|
color: #aaa
|
||||||
}
|
}
|
||||||
|
|
||||||
pre .tex .formula {
|
pre .hljs-tex .hljs-formula {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
63
vendor/underscore/docs/main.js
vendored
Normal file
63
vendor/underscore/docs/main.js
vendored
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
(function() {
|
||||||
|
var functions = document.querySelectorAll('[data-name]');
|
||||||
|
var sections = document.querySelectorAll('.searchable_section');
|
||||||
|
var searchInput = document.getElementById('function_filter');
|
||||||
|
|
||||||
|
function searchValue() {
|
||||||
|
return searchInput.value.trim().replace(/^_\.?/, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function strIn(a, b) {
|
||||||
|
a = a.toLowerCase();
|
||||||
|
b = b.toLowerCase();
|
||||||
|
return b.indexOf(a) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function doesMatch(element) {
|
||||||
|
var name = element.getAttribute('data-name');
|
||||||
|
var aliases = element.getAttribute('data-aliases') || '';
|
||||||
|
var value = searchValue();
|
||||||
|
return strIn(value, name) || strIn(value, aliases);
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterElement(element) {
|
||||||
|
element.style.display = doesMatch(element) ? '' : 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterToc() {
|
||||||
|
_.each(functions, filterElement);
|
||||||
|
|
||||||
|
var emptySearch = searchValue() === '';
|
||||||
|
|
||||||
|
// Hide the titles of empty sections
|
||||||
|
_.each(sections, function(section) {
|
||||||
|
var sectionFunctions = section.querySelectorAll('[data-name]');
|
||||||
|
var showSection = emptySearch || _.some(sectionFunctions, doesMatch);
|
||||||
|
section.style.display = showSection ? '' : 'none';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function gotoFirst() {
|
||||||
|
var firstFunction = _.find(functions, doesMatch);
|
||||||
|
if (firstFunction) {
|
||||||
|
window.location.hash = firstFunction.getAttribute('data-name');
|
||||||
|
searchInput.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
searchInput.addEventListener('input', filterToc, false);
|
||||||
|
|
||||||
|
// Press "Enter" to jump to the first matching function
|
||||||
|
searchInput.addEventListener('keypress', function(e) {
|
||||||
|
if (e.which === 13) {
|
||||||
|
gotoFirst();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Press "/" to search
|
||||||
|
document.body.addEventListener('keyup', function(event) {
|
||||||
|
if (191 === event.which) {
|
||||||
|
searchInput.focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}());
|
BIN
vendor/underscore/docs/public/fonts/roboto-black.eot
vendored
Normal file
BIN
vendor/underscore/docs/public/fonts/roboto-black.eot
vendored
Normal file
Binary file not shown.
BIN
vendor/underscore/docs/public/fonts/roboto-black.ttf
vendored
Normal file
BIN
vendor/underscore/docs/public/fonts/roboto-black.ttf
vendored
Normal file
Binary file not shown.
BIN
vendor/underscore/docs/public/fonts/roboto-black.woff
vendored
Normal file
BIN
vendor/underscore/docs/public/fonts/roboto-black.woff
vendored
Normal file
Binary file not shown.
2933
vendor/underscore/docs/underscore.html
vendored
2933
vendor/underscore/docs/underscore.html
vendored
File diff suppressed because it is too large
Load diff
1642
vendor/underscore/index.html
vendored
1642
vendor/underscore/index.html
vendored
File diff suppressed because it is too large
Load diff
93
vendor/underscore/karma.conf-sauce.js
vendored
Normal file
93
vendor/underscore/karma.conf-sauce.js
vendored
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
var _ = require('./');
|
||||||
|
|
||||||
|
// Browsers to run on Sauce Labs platforms
|
||||||
|
var sauceBrowsers = _.reduce([
|
||||||
|
['firefox', '35'],
|
||||||
|
['firefox', '30'],
|
||||||
|
['firefox', '21'],
|
||||||
|
['firefox', '11'],
|
||||||
|
['firefox', '4'],
|
||||||
|
|
||||||
|
['chrome', '40'],
|
||||||
|
['chrome', '39'],
|
||||||
|
['chrome', '31'],
|
||||||
|
['chrome', '26'],
|
||||||
|
|
||||||
|
['microsoftedge', '20.10240', 'Windows 10'],
|
||||||
|
['internet explorer', '11', 'Windows 10'],
|
||||||
|
['internet explorer', '10', 'Windows 8'],
|
||||||
|
['internet explorer', '9', 'Windows 7'],
|
||||||
|
// Currently disabled due to karma-sauce issues
|
||||||
|
// ['internet explorer', '8'],
|
||||||
|
// ['internet explorer', '7'],
|
||||||
|
// ['internet explorer', '6'],
|
||||||
|
|
||||||
|
['opera', '12'],
|
||||||
|
['opera', '11'],
|
||||||
|
|
||||||
|
['android', '5'],
|
||||||
|
['android', '4.4'],
|
||||||
|
['android', '4.3'],
|
||||||
|
['android', '4.0'],
|
||||||
|
|
||||||
|
['safari', '8.0', 'OS X 10.10'],
|
||||||
|
['safari', '7'],
|
||||||
|
['safari', '6'],
|
||||||
|
['safari', '5']
|
||||||
|
], function(memo, platform) {
|
||||||
|
// internet explorer -> ie
|
||||||
|
var label = platform[0].split(' ');
|
||||||
|
if (label.length > 1) {
|
||||||
|
label = _.invoke(label, 'charAt', 0)
|
||||||
|
}
|
||||||
|
label = (label.join("") + '_v' + platform[1]).replace(' ', '_').toUpperCase();
|
||||||
|
memo[label] = _.pick({
|
||||||
|
'base': 'SauceLabs',
|
||||||
|
'browserName': platform[0],
|
||||||
|
'version': platform[1],
|
||||||
|
'platform': platform[2]
|
||||||
|
}, Boolean);
|
||||||
|
return memo;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
module.exports = function(config) {
|
||||||
|
if ( !process.env.SAUCE_USERNAME || !process.env.SAUCE_ACCESS_KEY ) {
|
||||||
|
console.log('Sauce environments not set --- Skipping');
|
||||||
|
return process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
config.set({
|
||||||
|
basePath: '',
|
||||||
|
frameworks: ['qunit'],
|
||||||
|
singleRun: true,
|
||||||
|
|
||||||
|
// list of files / patterns to load in the browser
|
||||||
|
files: [
|
||||||
|
'test/vendor/qunit-extras.js',
|
||||||
|
'test/qunit-setup.js',
|
||||||
|
'underscore.js',
|
||||||
|
'test/*.js'
|
||||||
|
],
|
||||||
|
|
||||||
|
// Number of sauce tests to start in parallel
|
||||||
|
concurrency: 9,
|
||||||
|
|
||||||
|
// test results reporter to use
|
||||||
|
reporters: ['dots', 'saucelabs'],
|
||||||
|
port: 9876,
|
||||||
|
colors: true,
|
||||||
|
logLevel: config.LOG_INFO,
|
||||||
|
sauceLabs: {
|
||||||
|
build: 'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER + ' (' + process.env.TRAVIS_BUILD_ID + ')',
|
||||||
|
startConnect: true,
|
||||||
|
tunnelIdentifier: process.env.TRAVIS_JOB_NUMBER
|
||||||
|
},
|
||||||
|
|
||||||
|
captureTimeout: 120000,
|
||||||
|
customLaunchers: sauceBrowsers,
|
||||||
|
|
||||||
|
// Browsers to launch, commented out to prevent karma from starting
|
||||||
|
// too many concurrent browsers and timing sauce out.
|
||||||
|
browsers: _.keys(sauceBrowsers)
|
||||||
|
});
|
||||||
|
};
|
35
vendor/underscore/karma.conf.js
vendored
Normal file
35
vendor/underscore/karma.conf.js
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// Note some browser launchers should be installed before using karma start.
|
||||||
|
|
||||||
|
// For example:
|
||||||
|
// $ npm install karma-firefox-launcher
|
||||||
|
// $ karma start --browser=Firefox
|
||||||
|
|
||||||
|
// See http://karma-runner.github.io/0.8/config/configuration-file.html
|
||||||
|
module.exports = function(config) {
|
||||||
|
config.set({
|
||||||
|
basePath: '',
|
||||||
|
frameworks: ['qunit'],
|
||||||
|
logLevel: config.LOG_INFO,
|
||||||
|
port: 9876,
|
||||||
|
|
||||||
|
// list of files / patterns to load in the browser
|
||||||
|
files: [
|
||||||
|
'test/vendor/qunit-extras.js',
|
||||||
|
'test/qunit-setup.js',
|
||||||
|
'underscore.js',
|
||||||
|
'test/*.js'
|
||||||
|
],
|
||||||
|
|
||||||
|
// Test results reporter to use
|
||||||
|
// https://npmjs.org/browse/keyword/karma-reporter
|
||||||
|
reporters: ['progress'],
|
||||||
|
|
||||||
|
// start these browsers
|
||||||
|
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
|
||||||
|
browsers: ['PhantomJS'],
|
||||||
|
|
||||||
|
// Continuous Integration mode
|
||||||
|
// if true, Karma captures browsers, runs the tests and exits
|
||||||
|
singleRun: true
|
||||||
|
});
|
||||||
|
};
|
61
vendor/underscore/package.json
vendored
61
vendor/underscore/package.json
vendored
|
@ -1,23 +1,50 @@
|
||||||
{
|
{
|
||||||
"name" : "underscore",
|
"name": "underscore",
|
||||||
"description" : "JavaScript's functional programming helper library.",
|
"description": "JavaScript's functional programming helper library.",
|
||||||
"homepage" : "http://underscorejs.org",
|
"homepage": "http://underscorejs.org",
|
||||||
"keywords" : ["util", "functional", "server", "client", "browser"],
|
"keywords": [
|
||||||
"author" : "Jeremy Ashkenas <jeremy@documentcloud.org>",
|
"util",
|
||||||
"repository" : {"type": "git", "url": "git://github.com/jashkenas/underscore.git"},
|
"functional",
|
||||||
"main" : "underscore.js",
|
"server",
|
||||||
"version" : "1.5.2",
|
"client",
|
||||||
|
"browser"
|
||||||
|
],
|
||||||
|
"author": "Jeremy Ashkenas <jeremy@documentcloud.org>",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/jashkenas/underscore.git"
|
||||||
|
},
|
||||||
|
"main": "underscore.js",
|
||||||
|
"version": "1.8.3",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"phantomjs": "1.9.0-1"
|
"coveralls": "^2.11.2",
|
||||||
|
"docco": "*",
|
||||||
|
"eslint": "1.10.x",
|
||||||
|
"gzip-size-cli": "^1.0.0",
|
||||||
|
"karma": "^0.13.13",
|
||||||
|
"karma-qunit": "~0.1.4",
|
||||||
|
"nyc": "^2.1.3",
|
||||||
|
"pretty-bytes-cli": "^1.0.0",
|
||||||
|
"qunit-cli": "~0.2.0",
|
||||||
|
"qunitjs": "^1.18.0",
|
||||||
|
"uglify-js": "2.4.x"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "phantomjs test/vendor/runner.js test/index.html?noglobals=true"
|
"test": "npm run test-node && npm run lint",
|
||||||
|
"coverage": "nyc npm run test-node && nyc report",
|
||||||
|
"coveralls": "nyc npm run test-node && nyc report --reporter=text-lcov | coveralls",
|
||||||
|
"lint": "eslint underscore.js test/*.js",
|
||||||
|
"test-node": "qunit-cli test/*.js",
|
||||||
|
"test-browser": "npm i karma-phantomjs-launcher && karma start",
|
||||||
|
"minify": "uglifyjs underscore.js -c \"evaluate=false\" --comments \"/ .*/\" -m",
|
||||||
|
"build": "npm run minify -- --source-map underscore-min.map --source-map-url \" \" -o underscore-min.js",
|
||||||
|
"doc": "docco underscore.js",
|
||||||
|
"weight": "npm run minify | gzip-size | pretty-bytes"
|
||||||
},
|
},
|
||||||
"licenses": [
|
"license": "MIT",
|
||||||
{
|
"files": [
|
||||||
"type": "MIT",
|
"underscore.js",
|
||||||
"url": "https://raw.github.com/jashkenas/underscore/master/LICENSE"
|
"underscore-min.js",
|
||||||
}
|
"underscore-min.map"
|
||||||
],
|
]
|
||||||
"files" : ["underscore.js", "underscore-min.js", "LICENSE"]
|
|
||||||
}
|
}
|
||||||
|
|
13
vendor/underscore/test/.eslintrc
vendored
Normal file
13
vendor/underscore/test/.eslintrc
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"QUnit": false
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"brace-style": 0,
|
||||||
|
"no-new-wrappers": 0,
|
||||||
|
"no-extend-native": 0
|
||||||
|
}
|
||||||
|
}
|
607
vendor/underscore/test/arrays.js
vendored
607
vendor/underscore/test/arrays.js
vendored
|
@ -1,224 +1,563 @@
|
||||||
$(document).ready(function() {
|
(function() {
|
||||||
|
var _ = typeof require == 'function' ? require('..') : window._;
|
||||||
|
|
||||||
module("Arrays");
|
QUnit.module('Arrays');
|
||||||
|
|
||||||
test("first", function() {
|
QUnit.test('first', function(assert) {
|
||||||
equal(_.first([1,2,3]), 1, 'can pull out the first element of an array');
|
assert.strictEqual(_.first([1, 2, 3]), 1, 'can pull out the first element of an array');
|
||||||
equal(_([1, 2, 3]).first(), 1, 'can perform OO-style "first()"');
|
assert.strictEqual(_([1, 2, 3]).first(), 1, 'can perform OO-style "first()"');
|
||||||
equal(_.first([1,2,3], 0).join(', '), "", 'can pass an index to first');
|
assert.deepEqual(_.first([1, 2, 3], 0), [], 'returns an empty array when n <= 0 (0 case)');
|
||||||
equal(_.first([1,2,3], 2).join(', '), '1, 2', 'can pass an index to first');
|
assert.deepEqual(_.first([1, 2, 3], -1), [], 'returns an empty array when n <= 0 (negative case)');
|
||||||
equal(_.first([1,2,3], 5).join(', '), '1, 2, 3', 'can pass an index to first');
|
assert.deepEqual(_.first([1, 2, 3], 2), [1, 2], 'can fetch the first n elements');
|
||||||
var result = (function(){ return _.first(arguments); })(4, 3, 2, 1);
|
assert.deepEqual(_.first([1, 2, 3], 5), [1, 2, 3], 'returns the whole array if n > length');
|
||||||
equal(result, 4, 'works on an arguments object.');
|
var result = (function(){ return _.first(arguments); }(4, 3, 2, 1));
|
||||||
result = _.map([[1,2,3],[1,2,3]], _.first);
|
assert.strictEqual(result, 4, 'works on an arguments object');
|
||||||
equal(result.join(','), '1,1', 'works well with _.map');
|
result = _.map([[1, 2, 3], [1, 2, 3]], _.first);
|
||||||
result = (function() { return _.take([1,2,3], 2); })();
|
assert.deepEqual(result, [1, 1], 'works well with _.map');
|
||||||
equal(result.join(','), '1,2', 'aliased as take');
|
assert.strictEqual(_.first(null), void 0, 'returns undefined when called on null');
|
||||||
|
|
||||||
equal(_.first(null), undefined, 'handles nulls');
|
Array.prototype[0] = 'boo';
|
||||||
|
assert.strictEqual(_.first([]), void 0, 'return undefined when called on a empty array');
|
||||||
|
delete Array.prototype[0];
|
||||||
});
|
});
|
||||||
|
|
||||||
test("rest", function() {
|
QUnit.test('head', function(assert) {
|
||||||
|
assert.strictEqual(_.head, _.first, 'is an alias for first');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('take', function(assert) {
|
||||||
|
assert.strictEqual(_.take, _.first, 'is an alias for first');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('rest', function(assert) {
|
||||||
var numbers = [1, 2, 3, 4];
|
var numbers = [1, 2, 3, 4];
|
||||||
equal(_.rest(numbers).join(", "), "2, 3, 4", 'working rest()');
|
assert.deepEqual(_.rest(numbers), [2, 3, 4], 'fetches all but the first element');
|
||||||
equal(_.rest(numbers, 0).join(", "), "1, 2, 3, 4", 'working rest(0)');
|
assert.deepEqual(_.rest(numbers, 0), [1, 2, 3, 4], 'returns the whole array when index is 0');
|
||||||
equal(_.rest(numbers, 2).join(', '), '3, 4', 'rest can take an index');
|
assert.deepEqual(_.rest(numbers, 2), [3, 4], 'returns elements starting at the given index');
|
||||||
var result = (function(){ return _(arguments).tail(); })(1, 2, 3, 4);
|
var result = (function(){ return _(arguments).rest(); }(1, 2, 3, 4));
|
||||||
equal(result.join(', '), '2, 3, 4', 'aliased as tail and works on arguments object');
|
assert.deepEqual(result, [2, 3, 4], 'works on an arguments object');
|
||||||
result = _.map([[1,2,3],[1,2,3]], _.rest);
|
result = _.map([[1, 2, 3], [1, 2, 3]], _.rest);
|
||||||
equal(_.flatten(result).join(','), '2,3,2,3', 'works well with _.map');
|
assert.deepEqual(_.flatten(result), [2, 3, 2, 3], 'works well with _.map');
|
||||||
result = (function(){ return _(arguments).drop(); })(1, 2, 3, 4);
|
|
||||||
equal(result.join(', '), '2, 3, 4', 'aliased as drop and works on arguments object');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("initial", function() {
|
QUnit.test('tail', function(assert) {
|
||||||
equal(_.initial([1,2,3,4,5]).join(", "), "1, 2, 3, 4", 'working initial()');
|
assert.strictEqual(_.tail, _.rest, 'is an alias for rest');
|
||||||
equal(_.initial([1,2,3,4],2).join(", "), "1, 2", 'initial can take an index');
|
|
||||||
var result = (function(){ return _(arguments).initial(); })(1, 2, 3, 4);
|
|
||||||
equal(result.join(", "), "1, 2, 3", 'initial works on arguments object');
|
|
||||||
result = _.map([[1,2,3],[1,2,3]], _.initial);
|
|
||||||
equal(_.flatten(result).join(','), '1,2,1,2', 'initial works with _.map');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("last", function() {
|
QUnit.test('drop', function(assert) {
|
||||||
equal(_.last([1,2,3]), 3, 'can pull out the last element of an array');
|
assert.strictEqual(_.drop, _.rest, 'is an alias for rest');
|
||||||
equal(_.last([1,2,3], 0).join(', '), "", 'can pass an index to last');
|
|
||||||
equal(_.last([1,2,3], 2).join(', '), '2, 3', 'can pass an index to last');
|
|
||||||
equal(_.last([1,2,3], 5).join(', '), '1, 2, 3', 'can pass an index to last');
|
|
||||||
var result = (function(){ return _(arguments).last(); })(1, 2, 3, 4);
|
|
||||||
equal(result, 4, 'works on an arguments object');
|
|
||||||
result = _.map([[1,2,3],[1,2,3]], _.last);
|
|
||||||
equal(result.join(','), '3,3', 'works well with _.map');
|
|
||||||
|
|
||||||
equal(_.last(null), undefined, 'handles nulls');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("compact", function() {
|
QUnit.test('initial', function(assert) {
|
||||||
equal(_.compact([0, 1, false, 2, false, 3]).length, 3, 'can trim out all falsy values');
|
assert.deepEqual(_.initial([1, 2, 3, 4, 5]), [1, 2, 3, 4], 'returns all but the last element');
|
||||||
var result = (function(){ return _.compact(arguments).length; })(0, 1, false, 2, false, 3);
|
assert.deepEqual(_.initial([1, 2, 3, 4], 2), [1, 2], 'returns all but the last n elements');
|
||||||
equal(result, 3, 'works on an arguments object');
|
assert.deepEqual(_.initial([1, 2, 3, 4], 6), [], 'returns an empty array when n > length');
|
||||||
|
var result = (function(){ return _(arguments).initial(); }(1, 2, 3, 4));
|
||||||
|
assert.deepEqual(result, [1, 2, 3], 'works on an arguments object');
|
||||||
|
result = _.map([[1, 2, 3], [1, 2, 3]], _.initial);
|
||||||
|
assert.deepEqual(_.flatten(result), [1, 2, 1, 2], 'works well with _.map');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("flatten", function() {
|
QUnit.test('last', function(assert) {
|
||||||
|
assert.strictEqual(_.last([1, 2, 3]), 3, 'can pull out the last element of an array');
|
||||||
|
assert.strictEqual(_([1, 2, 3]).last(), 3, 'can perform OO-style "last()"');
|
||||||
|
assert.deepEqual(_.last([1, 2, 3], 0), [], 'returns an empty array when n <= 0 (0 case)');
|
||||||
|
assert.deepEqual(_.last([1, 2, 3], -1), [], 'returns an empty array when n <= 0 (negative case)');
|
||||||
|
assert.deepEqual(_.last([1, 2, 3], 2), [2, 3], 'can fetch the last n elements');
|
||||||
|
assert.deepEqual(_.last([1, 2, 3], 5), [1, 2, 3], 'returns the whole array if n > length');
|
||||||
|
var result = (function(){ return _(arguments).last(); }(1, 2, 3, 4));
|
||||||
|
assert.strictEqual(result, 4, 'works on an arguments object');
|
||||||
|
result = _.map([[1, 2, 3], [1, 2, 3]], _.last);
|
||||||
|
assert.deepEqual(result, [3, 3], 'works well with _.map');
|
||||||
|
assert.strictEqual(_.last(null), void 0, 'returns undefined when called on null');
|
||||||
|
|
||||||
|
var arr = [];
|
||||||
|
arr[-1] = 'boo';
|
||||||
|
assert.strictEqual(_.last(arr), void 0, 'return undefined when called on a empty array');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('compact', function(assert) {
|
||||||
|
assert.deepEqual(_.compact([1, false, null, 0, '', void 0, NaN, 2]), [1, 2], 'removes all falsy values');
|
||||||
|
var result = (function(){ return _.compact(arguments); }(0, 1, false, 2, false, 3));
|
||||||
|
assert.deepEqual(result, [1, 2, 3], 'works on an arguments object');
|
||||||
|
result = _.map([[1, false, false], [false, false, 3]], _.compact);
|
||||||
|
assert.deepEqual(result, [[1], [3]], 'works well with _.map');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('flatten', function(assert) {
|
||||||
|
assert.deepEqual(_.flatten(null), [], 'supports null');
|
||||||
|
assert.deepEqual(_.flatten(void 0), [], 'supports undefined');
|
||||||
|
|
||||||
|
assert.deepEqual(_.flatten([[], [[]], []]), [], 'supports empty arrays');
|
||||||
|
assert.deepEqual(_.flatten([[], [[]], []], true), [[]], 'can shallowly flatten empty arrays');
|
||||||
|
|
||||||
var list = [1, [2], [3, [[[4]]]]];
|
var list = [1, [2], [3, [[[4]]]]];
|
||||||
deepEqual(_.flatten(list), [1,2,3,4], 'can flatten nested arrays');
|
assert.deepEqual(_.flatten(list), [1, 2, 3, 4], 'can flatten nested arrays');
|
||||||
deepEqual(_.flatten(list, true), [1,2,3,[[[4]]]], 'can shallowly flatten nested arrays');
|
assert.deepEqual(_.flatten(list, true), [1, 2, 3, [[[4]]]], 'can shallowly flatten nested arrays');
|
||||||
var result = (function(){ return _.flatten(arguments); })(1, [2], [3, [[[4]]]]);
|
var result = (function(){ return _.flatten(arguments); }(1, [2], [3, [[[4]]]]));
|
||||||
deepEqual(result, [1,2,3,4], 'works on an arguments object');
|
assert.deepEqual(result, [1, 2, 3, 4], 'works on an arguments object');
|
||||||
list = [[1], [2], [3], [[4]]];
|
list = [[1], [2], [3], [[4]]];
|
||||||
deepEqual(_.flatten(list, true), [1, 2, 3, [4]], 'can shallowly flatten arrays containing only other arrays');
|
assert.deepEqual(_.flatten(list, true), [1, 2, 3, [4]], 'can shallowly flatten arrays containing only other arrays');
|
||||||
|
|
||||||
|
assert.strictEqual(_.flatten([_.range(10), _.range(10), 5, 1, 3], true).length, 23, 'can flatten medium length arrays');
|
||||||
|
assert.strictEqual(_.flatten([_.range(10), _.range(10), 5, 1, 3]).length, 23, 'can shallowly flatten medium length arrays');
|
||||||
|
assert.strictEqual(_.flatten([new Array(1000000), _.range(56000), 5, 1, 3]).length, 1056003, 'can handle massive arrays');
|
||||||
|
assert.strictEqual(_.flatten([new Array(1000000), _.range(56000), 5, 1, 3], true).length, 1056003, 'can handle massive arrays in shallow mode');
|
||||||
|
|
||||||
|
var x = _.range(100000);
|
||||||
|
for (var i = 0; i < 1000; i++) x = [x];
|
||||||
|
assert.deepEqual(_.flatten(x), _.range(100000), 'can handle very deep arrays');
|
||||||
|
assert.deepEqual(_.flatten(x, true), x[0], 'can handle very deep arrays in shallow mode');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("without", function() {
|
QUnit.test('without', function(assert) {
|
||||||
var list = [1, 2, 1, 0, 3, 1, 4];
|
var list = [1, 2, 1, 0, 3, 1, 4];
|
||||||
equal(_.without(list, 0, 1).join(', '), '2, 3, 4', 'can remove all instances of an object');
|
assert.deepEqual(_.without(list, 0, 1), [2, 3, 4], 'removes all instances of the given values');
|
||||||
var result = (function(){ return _.without(arguments, 0, 1); })(1, 2, 1, 0, 3, 1, 4);
|
var result = (function(){ return _.without(arguments, 0, 1); }(1, 2, 1, 0, 3, 1, 4));
|
||||||
equal(result.join(', '), '2, 3, 4', 'works on an arguments object');
|
assert.deepEqual(result, [2, 3, 4], 'works on an arguments object');
|
||||||
|
|
||||||
list = [{one : 1}, {two : 2}];
|
list = [{one: 1}, {two: 2}];
|
||||||
ok(_.without(list, {one : 1}).length == 2, 'uses real object identity for comparisons.');
|
assert.deepEqual(_.without(list, {one: 1}), list, 'compares objects by reference (value case)');
|
||||||
ok(_.without(list, list[0]).length == 1, 'ditto.');
|
assert.deepEqual(_.without(list, list[0]), [{two: 2}], 'compares objects by reference (reference case)');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("uniq", function() {
|
QUnit.test('sortedIndex', function(assert) {
|
||||||
|
var numbers = [10, 20, 30, 40, 50];
|
||||||
|
var indexFor35 = _.sortedIndex(numbers, 35);
|
||||||
|
assert.strictEqual(indexFor35, 3, 'finds the index at which a value should be inserted to retain order');
|
||||||
|
var indexFor30 = _.sortedIndex(numbers, 30);
|
||||||
|
assert.strictEqual(indexFor30, 2, 'finds the smallest index at which a value could be inserted to retain order');
|
||||||
|
|
||||||
|
var objects = [{x: 10}, {x: 20}, {x: 30}, {x: 40}];
|
||||||
|
var iterator = function(obj){ return obj.x; };
|
||||||
|
assert.strictEqual(_.sortedIndex(objects, {x: 25}, iterator), 2, 'uses the result of `iterator` for order comparisons');
|
||||||
|
assert.strictEqual(_.sortedIndex(objects, {x: 35}, 'x'), 3, 'when `iterator` is a string, uses that key for order comparisons');
|
||||||
|
|
||||||
|
var context = {1: 2, 2: 3, 3: 4};
|
||||||
|
iterator = function(obj){ return this[obj]; };
|
||||||
|
assert.strictEqual(_.sortedIndex([1, 3], 2, iterator, context), 1, 'can execute its iterator in the given context');
|
||||||
|
|
||||||
|
var values = [0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535, 131071, 262143, 524287,
|
||||||
|
1048575, 2097151, 4194303, 8388607, 16777215, 33554431, 67108863, 134217727, 268435455, 536870911, 1073741823, 2147483647];
|
||||||
|
var largeArray = Array(Math.pow(2, 32) - 1);
|
||||||
|
var length = values.length;
|
||||||
|
// Sparsely populate `array`
|
||||||
|
while (length--) {
|
||||||
|
largeArray[values[length]] = values[length];
|
||||||
|
}
|
||||||
|
assert.strictEqual(_.sortedIndex(largeArray, 2147483648), 2147483648, 'works with large indexes');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('uniq', function(assert) {
|
||||||
var list = [1, 2, 1, 3, 1, 4];
|
var list = [1, 2, 1, 3, 1, 4];
|
||||||
equal(_.uniq(list).join(', '), '1, 2, 3, 4', 'can find the unique values of an unsorted array');
|
assert.deepEqual(_.uniq(list), [1, 2, 3, 4], 'can find the unique values of an unsorted array');
|
||||||
|
|
||||||
list = [1, 1, 1, 2, 2, 3];
|
list = [1, 1, 1, 2, 2, 3];
|
||||||
equal(_.uniq(list, true).join(', '), '1, 2, 3', 'can find the unique values of a sorted array faster');
|
assert.deepEqual(_.uniq(list, true), [1, 2, 3], 'can find the unique values of a sorted array faster');
|
||||||
|
|
||||||
list = [{name:'moe'}, {name:'curly'}, {name:'larry'}, {name:'curly'}];
|
list = [{name: 'Moe'}, {name: 'Curly'}, {name: 'Larry'}, {name: 'Curly'}];
|
||||||
var iterator = function(value) { return value.name; };
|
var expected = [{name: 'Moe'}, {name: 'Curly'}, {name: 'Larry'}];
|
||||||
equal(_.map(_.uniq(list, false, iterator), iterator).join(', '), 'moe, curly, larry', 'can find the unique values of an array using a custom iterator');
|
var iterator = function(stooge) { return stooge.name; };
|
||||||
|
assert.deepEqual(_.uniq(list, false, iterator), expected, 'uses the result of `iterator` for uniqueness comparisons (unsorted case)');
|
||||||
|
assert.deepEqual(_.uniq(list, iterator), expected, '`sorted` argument defaults to false when omitted');
|
||||||
|
assert.deepEqual(_.uniq(list, 'name'), expected, 'when `iterator` is a string, uses that key for comparisons (unsorted case)');
|
||||||
|
|
||||||
equal(_.map(_.uniq(list, iterator), iterator).join(', '), 'moe, curly, larry', 'can find the unique values of an array using a custom iterator without specifying whether array is sorted');
|
list = [{score: 8}, {score: 10}, {score: 10}];
|
||||||
|
expected = [{score: 8}, {score: 10}];
|
||||||
|
iterator = function(item) { return item.score; };
|
||||||
|
assert.deepEqual(_.uniq(list, true, iterator), expected, 'uses the result of `iterator` for uniqueness comparisons (sorted case)');
|
||||||
|
assert.deepEqual(_.uniq(list, true, 'score'), expected, 'when `iterator` is a string, uses that key for comparisons (sorted case)');
|
||||||
|
|
||||||
iterator = function(value) { return value +1; };
|
assert.deepEqual(_.uniq([{0: 1}, {0: 1}, {0: 1}, {0: 2}], 0), [{0: 1}, {0: 2}], 'can use falsy pluck like iterator');
|
||||||
list = [1, 2, 2, 3, 4, 4];
|
|
||||||
equal(_.uniq(list, true, iterator).join(', '), '1, 2, 3, 4', 'iterator works with sorted array');
|
var result = (function(){ return _.uniq(arguments); }(1, 2, 1, 3, 1, 4));
|
||||||
|
assert.deepEqual(result, [1, 2, 3, 4], 'works on an arguments object');
|
||||||
|
|
||||||
|
var a = {}, b = {}, c = {};
|
||||||
|
assert.deepEqual(_.uniq([a, b, a, b, c]), [a, b, c], 'works on values that can be tested for equivalency but not ordered');
|
||||||
|
|
||||||
|
assert.deepEqual(_.uniq(null), [], 'returns an empty array when `array` is not iterable');
|
||||||
|
|
||||||
|
var context = {};
|
||||||
|
list = [3];
|
||||||
|
_.uniq(list, function(value, index, array) {
|
||||||
|
assert.strictEqual(this, context, 'executes its iterator in the given context');
|
||||||
|
assert.strictEqual(value, 3, 'passes its iterator the value');
|
||||||
|
assert.strictEqual(index, 0, 'passes its iterator the index');
|
||||||
|
assert.strictEqual(array, list, 'passes its iterator the entire array');
|
||||||
|
}, context);
|
||||||
|
|
||||||
var result = (function(){ return _.uniq(arguments); })(1, 2, 1, 3, 1, 4);
|
|
||||||
equal(result.join(', '), '1, 2, 3, 4', 'works on an arguments object');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("intersection", function() {
|
QUnit.test('unique', function(assert) {
|
||||||
|
assert.strictEqual(_.unique, _.uniq, 'is an alias for uniq');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('intersection', function(assert) {
|
||||||
var stooges = ['moe', 'curly', 'larry'], leaders = ['moe', 'groucho'];
|
var stooges = ['moe', 'curly', 'larry'], leaders = ['moe', 'groucho'];
|
||||||
equal(_.intersection(stooges, leaders).join(''), 'moe', 'can take the set intersection of two arrays');
|
assert.deepEqual(_.intersection(stooges, leaders), ['moe'], 'can find the set intersection of two arrays');
|
||||||
equal(_(stooges).intersection(leaders).join(''), 'moe', 'can perform an OO-style intersection');
|
assert.deepEqual(_(stooges).intersection(leaders), ['moe'], 'can perform an OO-style intersection');
|
||||||
var result = (function(){ return _.intersection(arguments, leaders); })('moe', 'curly', 'larry');
|
var result = (function(){ return _.intersection(arguments, leaders); }('moe', 'curly', 'larry'));
|
||||||
equal(result.join(''), 'moe', 'works on an arguments object');
|
assert.deepEqual(result, ['moe'], 'works on an arguments object');
|
||||||
var theSixStooges = ['moe', 'moe', 'curly', 'curly', 'larry', 'larry'];
|
var theSixStooges = ['moe', 'moe', 'curly', 'curly', 'larry', 'larry'];
|
||||||
equal(_.intersection(theSixStooges, leaders).join(''), 'moe', 'returns a duplicate-free array');
|
assert.deepEqual(_.intersection(theSixStooges, leaders), ['moe'], 'returns a duplicate-free array');
|
||||||
|
result = _.intersection([2, 4, 3, 1], [1, 2, 3]);
|
||||||
|
assert.deepEqual(result, [2, 3, 1], 'preserves the order of the first array');
|
||||||
|
result = _.intersection(null, [1, 2, 3]);
|
||||||
|
assert.deepEqual(result, [], 'returns an empty array when passed null as the first argument');
|
||||||
|
result = _.intersection([1, 2, 3], null);
|
||||||
|
assert.deepEqual(result, [], 'returns an empty array when passed null as an argument beyond the first');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("union", function() {
|
QUnit.test('union', function(assert) {
|
||||||
var result = _.union([1, 2, 3], [2, 30, 1], [1, 40]);
|
var result = _.union([1, 2, 3], [2, 30, 1], [1, 40]);
|
||||||
equal(result.join(' '), '1 2 3 30 40', 'takes the union of a list of arrays');
|
assert.deepEqual(result, [1, 2, 3, 30, 40], 'can find the union of a list of arrays');
|
||||||
|
|
||||||
|
result = _([1, 2, 3]).union([2, 30, 1], [1, 40]);
|
||||||
|
assert.deepEqual(result, [1, 2, 3, 30, 40], 'can perform an OO-style union');
|
||||||
|
|
||||||
result = _.union([1, 2, 3], [2, 30, 1], [1, 40, [1]]);
|
result = _.union([1, 2, 3], [2, 30, 1], [1, 40, [1]]);
|
||||||
equal(result.join(' '), '1 2 3 30 40 1', 'takes the union of a list of nested arrays');
|
assert.deepEqual(result, [1, 2, 3, 30, 40, [1]], 'can find the union of a list of nested arrays');
|
||||||
|
|
||||||
var args = null;
|
result = _.union([10, 20], [1, 30, 10], [0, 40]);
|
||||||
(function(){ args = arguments; })(1, 2, 3);
|
assert.deepEqual(result, [10, 20, 1, 30, 0, 40], 'orders values by their first encounter');
|
||||||
result = _.union(args, [2, 30, 1], [1, 40]);
|
|
||||||
equal(result.join(' '), '1 2 3 30 40', 'takes the union of a list of arrays');
|
|
||||||
|
|
||||||
result = _.union(null, [1, 2, 3]);
|
result = (function(){ return _.union(arguments, [2, 30, 1], [1, 40]); }(1, 2, 3));
|
||||||
deepEqual(result, [null, 1, 2, 3]);
|
assert.deepEqual(result, [1, 2, 3, 30, 40], 'works on an arguments object');
|
||||||
|
|
||||||
|
assert.deepEqual(_.union([1, 2, 3], 4), [1, 2, 3], 'restricts the union to arrays only');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("difference", function() {
|
QUnit.test('difference', function(assert) {
|
||||||
var result = _.difference([1, 2, 3], [2, 30, 40]);
|
var result = _.difference([1, 2, 3], [2, 30, 40]);
|
||||||
equal(result.join(' '), '1 3', 'takes the difference of two arrays');
|
assert.deepEqual(result, [1, 3], 'can find the difference of two arrays');
|
||||||
|
|
||||||
|
result = _([1, 2, 3]).difference([2, 30, 40]);
|
||||||
|
assert.deepEqual(result, [1, 3], 'can perform an OO-style difference');
|
||||||
|
|
||||||
result = _.difference([1, 2, 3, 4], [2, 30, 40], [1, 11, 111]);
|
result = _.difference([1, 2, 3, 4], [2, 30, 40], [1, 11, 111]);
|
||||||
equal(result.join(' '), '3 4', 'takes the difference of three arrays');
|
assert.deepEqual(result, [3, 4], 'can find the difference of three arrays');
|
||||||
|
|
||||||
|
result = _.difference([8, 9, 3, 1], [3, 8]);
|
||||||
|
assert.deepEqual(result, [9, 1], 'preserves the order of the first array');
|
||||||
|
|
||||||
|
result = (function(){ return _.difference(arguments, [2, 30, 40]); }(1, 2, 3));
|
||||||
|
assert.deepEqual(result, [1, 3], 'works on an arguments object');
|
||||||
|
|
||||||
|
result = _.difference([1, 2, 3], 1);
|
||||||
|
assert.deepEqual(result, [1, 2, 3], 'restrict the difference to arrays only');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('zip', function() {
|
QUnit.test('zip', function(assert) {
|
||||||
var names = ['moe', 'larry', 'curly'], ages = [30, 40, 50], leaders = [true];
|
var names = ['moe', 'larry', 'curly'], ages = [30, 40, 50], leaders = [true];
|
||||||
var stooges = _.zip(names, ages, leaders);
|
assert.deepEqual(_.zip(names, ages, leaders), [
|
||||||
equal(String(stooges), 'moe,30,true,larry,40,,curly,50,', 'zipped together arrays of different lengths');
|
['moe', 30, true],
|
||||||
|
['larry', 40, void 0],
|
||||||
|
['curly', 50, void 0]
|
||||||
|
], 'zipped together arrays of different lengths');
|
||||||
|
|
||||||
stooges = _.zip(['moe',30, 'stooge 1'],['larry',40, 'stooge 2'],['curly',50, 'stooge 3']);
|
var stooges = _.zip(['moe', 30, 'stooge 1'], ['larry', 40, 'stooge 2'], ['curly', 50, 'stooge 3']);
|
||||||
deepEqual(stooges, [['moe','larry','curly'],[30,40,50], ['stooge 1', 'stooge 2', 'stooge 3']], 'zipped pairs');
|
assert.deepEqual(stooges, [['moe', 'larry', 'curly'], [30, 40, 50], ['stooge 1', 'stooge 2', 'stooge 3']], 'zipped pairs');
|
||||||
|
|
||||||
// In the case of difference lengths of the tuples undefineds
|
// In the case of different lengths of the tuples, undefined values
|
||||||
// should be used as placeholder
|
// should be used as placeholder
|
||||||
stooges = _.zip(['moe',30],['larry',40],['curly',50, 'extra data']);
|
stooges = _.zip(['moe', 30], ['larry', 40], ['curly', 50, 'extra data']);
|
||||||
deepEqual(stooges, [['moe','larry','curly'],[30,40,50], [undefined, undefined, 'extra data']], 'zipped pairs with empties');
|
assert.deepEqual(stooges, [['moe', 'larry', 'curly'], [30, 40, 50], [void 0, void 0, 'extra data']], 'zipped pairs with empties');
|
||||||
|
|
||||||
var empty = _.zip([]);
|
var empty = _.zip([]);
|
||||||
deepEqual(empty, [], 'unzipped empty');
|
assert.deepEqual(empty, [], 'unzipped empty');
|
||||||
|
|
||||||
|
assert.deepEqual(_.zip(null), [], 'handles null');
|
||||||
|
assert.deepEqual(_.zip(), [], '_.zip() returns []');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('object', function() {
|
QUnit.test('unzip', function(assert) {
|
||||||
|
assert.deepEqual(_.unzip(null), [], 'handles null');
|
||||||
|
|
||||||
|
assert.deepEqual(_.unzip([['a', 'b'], [1, 2]]), [['a', 1], ['b', 2]]);
|
||||||
|
|
||||||
|
// complements zip
|
||||||
|
var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]);
|
||||||
|
assert.deepEqual(_.unzip(zipped), [['fred', 'barney'], [30, 40], [true, false]]);
|
||||||
|
|
||||||
|
zipped = _.zip(['moe', 30], ['larry', 40], ['curly', 50, 'extra data']);
|
||||||
|
assert.deepEqual(_.unzip(zipped), [['moe', 30, void 0], ['larry', 40, void 0], ['curly', 50, 'extra data']], 'Uses length of largest array');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('object', function(assert) {
|
||||||
var result = _.object(['moe', 'larry', 'curly'], [30, 40, 50]);
|
var result = _.object(['moe', 'larry', 'curly'], [30, 40, 50]);
|
||||||
var shouldBe = {moe: 30, larry: 40, curly: 50};
|
var shouldBe = {moe: 30, larry: 40, curly: 50};
|
||||||
ok(_.isEqual(result, shouldBe), 'two arrays zipped together into an object');
|
assert.deepEqual(result, shouldBe, 'two arrays zipped together into an object');
|
||||||
|
|
||||||
result = _.object([['one', 1], ['two', 2], ['three', 3]]);
|
result = _.object([['one', 1], ['two', 2], ['three', 3]]);
|
||||||
shouldBe = {one: 1, two: 2, three: 3};
|
shouldBe = {one: 1, two: 2, three: 3};
|
||||||
ok(_.isEqual(result, shouldBe), 'an array of pairs zipped together into an object');
|
assert.deepEqual(result, shouldBe, 'an array of pairs zipped together into an object');
|
||||||
|
|
||||||
var stooges = {moe: 30, larry: 40, curly: 50};
|
var stooges = {moe: 30, larry: 40, curly: 50};
|
||||||
ok(_.isEqual(_.object(_.pairs(stooges)), stooges), 'an object converted to pairs and back to an object');
|
assert.deepEqual(_.object(_.pairs(stooges)), stooges, 'an object converted to pairs and back to an object');
|
||||||
|
|
||||||
ok(_.isEqual(_.object(null), {}), 'handles nulls');
|
assert.deepEqual(_.object(null), {}, 'handles nulls');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("indexOf", function() {
|
QUnit.test('indexOf', function(assert) {
|
||||||
var numbers = [1, 2, 3];
|
var numbers = [1, 2, 3];
|
||||||
numbers.indexOf = null;
|
assert.strictEqual(_.indexOf(numbers, 2), 1, 'can compute indexOf');
|
||||||
equal(_.indexOf(numbers, 2), 1, 'can compute indexOf, even without the native function');
|
var result = (function(){ return _.indexOf(arguments, 2); }(1, 2, 3));
|
||||||
var result = (function(){ return _.indexOf(arguments, 2); })(1, 2, 3);
|
assert.strictEqual(result, 1, 'works on an arguments object');
|
||||||
equal(result, 1, 'works on an arguments object');
|
|
||||||
equal(_.indexOf(null, 2), -1, 'handles nulls properly');
|
_.each([null, void 0, [], false], function(val) {
|
||||||
|
var msg = 'Handles: ' + (_.isArray(val) ? '[]' : val);
|
||||||
|
assert.strictEqual(_.indexOf(val, 2), -1, msg);
|
||||||
|
assert.strictEqual(_.indexOf(val, 2, -1), -1, msg);
|
||||||
|
assert.strictEqual(_.indexOf(val, 2, -20), -1, msg);
|
||||||
|
assert.strictEqual(_.indexOf(val, 2, 15), -1, msg);
|
||||||
|
});
|
||||||
|
|
||||||
var num = 35;
|
var num = 35;
|
||||||
numbers = [10, 20, 30, 40, 50];
|
numbers = [10, 20, 30, 40, 50];
|
||||||
var index = _.indexOf(numbers, num, true);
|
var index = _.indexOf(numbers, num, true);
|
||||||
equal(index, -1, '35 is not in the list');
|
assert.strictEqual(index, -1, '35 is not in the list');
|
||||||
|
|
||||||
numbers = [10, 20, 30, 40, 50]; num = 40;
|
numbers = [10, 20, 30, 40, 50]; num = 40;
|
||||||
index = _.indexOf(numbers, num, true);
|
index = _.indexOf(numbers, num, true);
|
||||||
equal(index, 3, '40 is in the list');
|
assert.strictEqual(index, 3, '40 is in the list');
|
||||||
|
|
||||||
numbers = [1, 40, 40, 40, 40, 40, 40, 40, 50, 60, 70]; num = 40;
|
numbers = [1, 40, 40, 40, 40, 40, 40, 40, 50, 60, 70]; num = 40;
|
||||||
index = _.indexOf(numbers, num, true);
|
assert.strictEqual(_.indexOf(numbers, num, true), 1, '40 is in the list');
|
||||||
equal(index, 1, '40 is in the list');
|
assert.strictEqual(_.indexOf(numbers, 6, true), -1, '6 isnt in the list');
|
||||||
|
assert.strictEqual(_.indexOf([1, 2, 5, 4, 6, 7], 5, true), -1, 'sorted indexOf doesn\'t use binary search');
|
||||||
|
assert.ok(_.every(['1', [], {}, null], function() {
|
||||||
|
return _.indexOf(numbers, num, {}) === 1;
|
||||||
|
}), 'non-nums as fromIndex make indexOf assume sorted');
|
||||||
|
|
||||||
numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3];
|
numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3];
|
||||||
index = _.indexOf(numbers, 2, 5);
|
index = _.indexOf(numbers, 2, 5);
|
||||||
equal(index, 7, 'supports the fromIndex argument');
|
assert.strictEqual(index, 7, 'supports the fromIndex argument');
|
||||||
|
|
||||||
|
index = _.indexOf([,,, 0], void 0);
|
||||||
|
assert.strictEqual(index, 0, 'treats sparse arrays as if they were dense');
|
||||||
|
|
||||||
|
var array = [1, 2, 3, 1, 2, 3];
|
||||||
|
assert.strictEqual(_.indexOf(array, 1, -3), 3, 'neg `fromIndex` starts at the right index');
|
||||||
|
assert.strictEqual(_.indexOf(array, 1, -2), -1, 'neg `fromIndex` starts at the right index');
|
||||||
|
assert.strictEqual(_.indexOf(array, 2, -3), 4);
|
||||||
|
_.each([-6, -8, -Infinity], function(fromIndex) {
|
||||||
|
assert.strictEqual(_.indexOf(array, 1, fromIndex), 0);
|
||||||
|
});
|
||||||
|
assert.strictEqual(_.indexOf([1, 2, 3], 1, true), 0);
|
||||||
|
|
||||||
|
index = _.indexOf([], void 0, true);
|
||||||
|
assert.strictEqual(index, -1, 'empty array with truthy `isSorted` returns -1');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("lastIndexOf", function() {
|
QUnit.test('indexOf with NaN', function(assert) {
|
||||||
|
assert.strictEqual(_.indexOf([1, 2, NaN, NaN], NaN), 2, 'Expected [1, 2, NaN] to contain NaN');
|
||||||
|
assert.strictEqual(_.indexOf([1, 2, Infinity], NaN), -1, 'Expected [1, 2, NaN] to contain NaN');
|
||||||
|
|
||||||
|
assert.strictEqual(_.indexOf([1, 2, NaN, NaN], NaN, 1), 2, 'startIndex does not affect result');
|
||||||
|
assert.strictEqual(_.indexOf([1, 2, NaN, NaN], NaN, -2), 2, 'startIndex does not affect result');
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
assert.strictEqual(_.indexOf(arguments, NaN), 2, 'Expected arguments [1, 2, NaN] to contain NaN');
|
||||||
|
}(1, 2, NaN, NaN));
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('indexOf with +- 0', function(assert) {
|
||||||
|
_.each([-0, +0], function(val) {
|
||||||
|
assert.strictEqual(_.indexOf([1, 2, val, val], val), 2);
|
||||||
|
assert.strictEqual(_.indexOf([1, 2, val, val], -val), 2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('lastIndexOf', function(assert) {
|
||||||
var numbers = [1, 0, 1];
|
var numbers = [1, 0, 1];
|
||||||
equal(_.lastIndexOf(numbers, 1), 2);
|
var falsy = [void 0, '', 0, false, NaN, null, void 0];
|
||||||
|
assert.strictEqual(_.lastIndexOf(numbers, 1), 2);
|
||||||
|
|
||||||
numbers = [1, 0, 1, 0, 0, 1, 0, 0, 0];
|
numbers = [1, 0, 1, 0, 0, 1, 0, 0, 0];
|
||||||
numbers.lastIndexOf = null;
|
numbers.lastIndexOf = null;
|
||||||
equal(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function');
|
assert.strictEqual(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function');
|
||||||
equal(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element');
|
assert.strictEqual(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element');
|
||||||
var result = (function(){ return _.lastIndexOf(arguments, 1); })(1, 0, 1, 0, 0, 1, 0, 0, 0);
|
var result = (function(){ return _.lastIndexOf(arguments, 1); }(1, 0, 1, 0, 0, 1, 0, 0, 0));
|
||||||
equal(result, 5, 'works on an arguments object');
|
assert.strictEqual(result, 5, 'works on an arguments object');
|
||||||
equal(_.lastIndexOf(null, 2), -1, 'handles nulls properly');
|
|
||||||
|
_.each([null, void 0, [], false], function(val) {
|
||||||
|
var msg = 'Handles: ' + (_.isArray(val) ? '[]' : val);
|
||||||
|
assert.strictEqual(_.lastIndexOf(val, 2), -1, msg);
|
||||||
|
assert.strictEqual(_.lastIndexOf(val, 2, -1), -1, msg);
|
||||||
|
assert.strictEqual(_.lastIndexOf(val, 2, -20), -1, msg);
|
||||||
|
assert.strictEqual(_.lastIndexOf(val, 2, 15), -1, msg);
|
||||||
|
});
|
||||||
|
|
||||||
numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3];
|
numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3];
|
||||||
var index = _.lastIndexOf(numbers, 2, 2);
|
var index = _.lastIndexOf(numbers, 2, 2);
|
||||||
equal(index, 1, 'supports the fromIndex argument');
|
assert.strictEqual(index, 1, 'supports the fromIndex argument');
|
||||||
|
|
||||||
|
var array = [1, 2, 3, 1, 2, 3];
|
||||||
|
|
||||||
|
assert.strictEqual(_.lastIndexOf(array, 1, 0), 0, 'starts at the correct from idx');
|
||||||
|
assert.strictEqual(_.lastIndexOf(array, 3), 5, 'should return the index of the last matched value');
|
||||||
|
assert.strictEqual(_.lastIndexOf(array, 4), -1, 'should return `-1` for an unmatched value');
|
||||||
|
|
||||||
|
assert.strictEqual(_.lastIndexOf(array, 1, 2), 0, 'should work with a positive `fromIndex`');
|
||||||
|
|
||||||
|
_.each([6, 8, Math.pow(2, 32), Infinity], function(fromIndex) {
|
||||||
|
assert.strictEqual(_.lastIndexOf(array, void 0, fromIndex), -1);
|
||||||
|
assert.strictEqual(_.lastIndexOf(array, 1, fromIndex), 3);
|
||||||
|
assert.strictEqual(_.lastIndexOf(array, '', fromIndex), -1);
|
||||||
|
});
|
||||||
|
|
||||||
|
var expected = _.map(falsy, function(value) {
|
||||||
|
return typeof value == 'number' ? -1 : 5;
|
||||||
|
});
|
||||||
|
|
||||||
|
var actual = _.map(falsy, function(fromIndex) {
|
||||||
|
return _.lastIndexOf(array, 3, fromIndex);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.deepEqual(actual, expected, 'should treat falsy `fromIndex` values, except `0` and `NaN`, as `array.length`');
|
||||||
|
assert.strictEqual(_.lastIndexOf(array, 3, '1'), 5, 'should treat non-number `fromIndex` values as `array.length`');
|
||||||
|
assert.strictEqual(_.lastIndexOf(array, 3, true), 5, 'should treat non-number `fromIndex` values as `array.length`');
|
||||||
|
|
||||||
|
assert.strictEqual(_.lastIndexOf(array, 2, -3), 1, 'should work with a negative `fromIndex`');
|
||||||
|
assert.strictEqual(_.lastIndexOf(array, 1, -3), 3, 'neg `fromIndex` starts at the right index');
|
||||||
|
|
||||||
|
assert.deepEqual(_.map([-6, -8, -Infinity], function(fromIndex) {
|
||||||
|
return _.lastIndexOf(array, 1, fromIndex);
|
||||||
|
}), [0, -1, -1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("range", function() {
|
QUnit.test('lastIndexOf with NaN', function(assert) {
|
||||||
equal(_.range(0).join(''), '', 'range with 0 as a first argument generates an empty array');
|
assert.strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN), 3, 'Expected [1, 2, NaN] to contain NaN');
|
||||||
equal(_.range(4).join(' '), '0 1 2 3', 'range with a single positive argument generates an array of elements 0,1,2,...,n-1');
|
assert.strictEqual(_.lastIndexOf([1, 2, Infinity], NaN), -1, 'Expected [1, 2, NaN] to contain NaN');
|
||||||
equal(_.range(5, 8).join(' '), '5 6 7', 'range with two arguments a & b, a<b generates an array of elements a,a+1,a+2,...,b-2,b-1');
|
|
||||||
equal(_.range(8, 5).join(''), '', 'range with two arguments a & b, b<a generates an empty array');
|
assert.strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN, 2), 2, 'fromIndex does not affect result');
|
||||||
equal(_.range(3, 10, 3).join(' '), '3 6 9', 'range with three arguments a & b & c, c < b-a, a < b generates an array of elements a,a+c,a+2c,...,b - (multiplier of a) < c');
|
assert.strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN, -2), 2, 'fromIndex does not affect result');
|
||||||
equal(_.range(3, 10, 15).join(''), '3', 'range with three arguments a & b & c, c > b-a, a < b generates an array with a single element, equal to a');
|
|
||||||
equal(_.range(12, 7, -2).join(' '), '12 10 8', 'range with three arguments a & b & c, a > b, c < 0 generates an array of elements a,a-c,a-2c and ends with the number not less than b');
|
(function() {
|
||||||
equal(_.range(0, -10, -1).join(' '), '0 -1 -2 -3 -4 -5 -6 -7 -8 -9', 'final example in the Python docs');
|
assert.strictEqual(_.lastIndexOf(arguments, NaN), 3, 'Expected arguments [1, 2, NaN] to contain NaN');
|
||||||
|
}(1, 2, NaN, NaN));
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
QUnit.test('lastIndexOf with +- 0', function(assert) {
|
||||||
|
_.each([-0, +0], function(val) {
|
||||||
|
assert.strictEqual(_.lastIndexOf([1, 2, val, val], val), 3);
|
||||||
|
assert.strictEqual(_.lastIndexOf([1, 2, val, val], -val), 3);
|
||||||
|
assert.strictEqual(_.lastIndexOf([-1, 1, 2], -val), -1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('findIndex', function(assert) {
|
||||||
|
var objects = [
|
||||||
|
{a: 0, b: 0},
|
||||||
|
{a: 1, b: 1},
|
||||||
|
{a: 2, b: 2},
|
||||||
|
{a: 0, b: 0}
|
||||||
|
];
|
||||||
|
|
||||||
|
assert.strictEqual(_.findIndex(objects, function(obj) {
|
||||||
|
return obj.a === 0;
|
||||||
|
}), 0);
|
||||||
|
|
||||||
|
assert.strictEqual(_.findIndex(objects, function(obj) {
|
||||||
|
return obj.b * obj.a === 4;
|
||||||
|
}), 2);
|
||||||
|
|
||||||
|
assert.strictEqual(_.findIndex(objects, 'a'), 1, 'Uses lookupIterator');
|
||||||
|
|
||||||
|
assert.strictEqual(_.findIndex(objects, function(obj) {
|
||||||
|
return obj.b * obj.a === 5;
|
||||||
|
}), -1);
|
||||||
|
|
||||||
|
assert.strictEqual(_.findIndex(null, _.noop), -1);
|
||||||
|
assert.strictEqual(_.findIndex(objects, function(a) {
|
||||||
|
return a.foo === null;
|
||||||
|
}), -1);
|
||||||
|
_.findIndex([{a: 1}], function(a, key, obj) {
|
||||||
|
assert.strictEqual(key, 0);
|
||||||
|
assert.deepEqual(obj, [{a: 1}]);
|
||||||
|
assert.strictEqual(this, objects, 'called with context');
|
||||||
|
}, objects);
|
||||||
|
|
||||||
|
var sparse = [];
|
||||||
|
sparse[20] = {a: 2, b: 2};
|
||||||
|
assert.strictEqual(_.findIndex(sparse, function(obj) {
|
||||||
|
return obj && obj.b * obj.a === 4;
|
||||||
|
}), 20, 'Works with sparse arrays');
|
||||||
|
|
||||||
|
var array = [1, 2, 3, 4];
|
||||||
|
array.match = 55;
|
||||||
|
assert.strictEqual(_.findIndex(array, function(x) { return x === 55; }), -1, 'doesn\'t match array-likes keys');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('findLastIndex', function(assert) {
|
||||||
|
var objects = [
|
||||||
|
{a: 0, b: 0},
|
||||||
|
{a: 1, b: 1},
|
||||||
|
{a: 2, b: 2},
|
||||||
|
{a: 0, b: 0}
|
||||||
|
];
|
||||||
|
|
||||||
|
assert.strictEqual(_.findLastIndex(objects, function(obj) {
|
||||||
|
return obj.a === 0;
|
||||||
|
}), 3);
|
||||||
|
|
||||||
|
assert.strictEqual(_.findLastIndex(objects, function(obj) {
|
||||||
|
return obj.b * obj.a === 4;
|
||||||
|
}), 2);
|
||||||
|
|
||||||
|
assert.strictEqual(_.findLastIndex(objects, 'a'), 2, 'Uses lookupIterator');
|
||||||
|
|
||||||
|
assert.strictEqual(_.findLastIndex(objects, function(obj) {
|
||||||
|
return obj.b * obj.a === 5;
|
||||||
|
}), -1);
|
||||||
|
|
||||||
|
assert.strictEqual(_.findLastIndex(null, _.noop), -1);
|
||||||
|
assert.strictEqual(_.findLastIndex(objects, function(a) {
|
||||||
|
return a.foo === null;
|
||||||
|
}), -1);
|
||||||
|
_.findLastIndex([{a: 1}], function(a, key, obj) {
|
||||||
|
assert.strictEqual(key, 0);
|
||||||
|
assert.deepEqual(obj, [{a: 1}]);
|
||||||
|
assert.strictEqual(this, objects, 'called with context');
|
||||||
|
}, objects);
|
||||||
|
|
||||||
|
var sparse = [];
|
||||||
|
sparse[20] = {a: 2, b: 2};
|
||||||
|
assert.strictEqual(_.findLastIndex(sparse, function(obj) {
|
||||||
|
return obj && obj.b * obj.a === 4;
|
||||||
|
}), 20, 'Works with sparse arrays');
|
||||||
|
|
||||||
|
var array = [1, 2, 3, 4];
|
||||||
|
array.match = 55;
|
||||||
|
assert.strictEqual(_.findLastIndex(array, function(x) { return x === 55; }), -1, 'doesn\'t match array-likes keys');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('range', function(assert) {
|
||||||
|
assert.deepEqual(_.range(0), [], 'range with 0 as a first argument generates an empty array');
|
||||||
|
assert.deepEqual(_.range(4), [0, 1, 2, 3], 'range with a single positive argument generates an array of elements 0,1,2,...,n-1');
|
||||||
|
assert.deepEqual(_.range(5, 8), [5, 6, 7], 'range with two arguments a & b, a<b generates an array of elements a,a+1,a+2,...,b-2,b-1');
|
||||||
|
assert.deepEqual(_.range(3, 10, 3), [3, 6, 9], 'range with three arguments a & b & c, c < b-a, a < b generates an array of elements a,a+c,a+2c,...,b - (multiplier of a) < c');
|
||||||
|
assert.deepEqual(_.range(3, 10, 15), [3], 'range with three arguments a & b & c, c > b-a, a < b generates an array with a single element, equal to a');
|
||||||
|
assert.deepEqual(_.range(12, 7, -2), [12, 10, 8], 'range with three arguments a & b & c, a > b, c < 0 generates an array of elements a,a-c,a-2c and ends with the number not less than b');
|
||||||
|
assert.deepEqual(_.range(0, -10, -1), [0, -1, -2, -3, -4, -5, -6, -7, -8, -9], 'final example in the Python docs');
|
||||||
|
assert.strictEqual(1 / _.range(-0, 1)[0], -Infinity, 'should preserve -0');
|
||||||
|
assert.deepEqual(_.range(8, 5), [8, 7, 6], 'negative range generates descending array');
|
||||||
|
assert.deepEqual(_.range(-3), [0, -1, -2], 'negative range generates descending array');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('chunk', function(assert) {
|
||||||
|
assert.deepEqual(_.chunk([], 2), [], 'chunk for empty array returns an empty array');
|
||||||
|
|
||||||
|
assert.deepEqual(_.chunk([1, 2, 3], 0), [], 'chunk into parts of 0 elements returns empty array');
|
||||||
|
assert.deepEqual(_.chunk([1, 2, 3], -1), [], 'chunk into parts of negative amount of elements returns an empty array');
|
||||||
|
assert.deepEqual(_.chunk([1, 2, 3]), [], 'defaults to empty array (chunk size 0)');
|
||||||
|
|
||||||
|
assert.deepEqual(_.chunk([1, 2, 3], 1), [[1], [2], [3]], 'chunk into parts of 1 elements returns original array');
|
||||||
|
|
||||||
|
assert.deepEqual(_.chunk([1, 2, 3], 3), [[1, 2, 3]], 'chunk into parts of current array length elements returns the original array');
|
||||||
|
assert.deepEqual(_.chunk([1, 2, 3], 5), [[1, 2, 3]], 'chunk into parts of more then current array length elements returns the original array');
|
||||||
|
|
||||||
|
assert.deepEqual(_.chunk([10, 20, 30, 40, 50, 60, 70], 2), [[10, 20], [30, 40], [50, 60], [70]], 'chunk into parts of less then current array length elements');
|
||||||
|
assert.deepEqual(_.chunk([10, 20, 30, 40, 50, 60, 70], 3), [[10, 20, 30], [40, 50, 60], [70]], 'chunk into parts of less then current array length elements');
|
||||||
|
});
|
||||||
|
}());
|
||||||
|
|
78
vendor/underscore/test/chaining.js
vendored
78
vendor/underscore/test/chaining.js
vendored
|
@ -1,13 +1,14 @@
|
||||||
$(document).ready(function() {
|
(function() {
|
||||||
|
var _ = typeof require == 'function' ? require('..') : window._;
|
||||||
|
|
||||||
module("Chaining");
|
QUnit.module('Chaining');
|
||||||
|
|
||||||
test("map/flatten/reduce", function() {
|
QUnit.test('map/flatten/reduce', function(assert) {
|
||||||
var lyrics = [
|
var lyrics = [
|
||||||
"I'm a lumberjack and I'm okay",
|
'I\'m a lumberjack and I\'m okay',
|
||||||
"I sleep all night and I work all day",
|
'I sleep all night and I work all day',
|
||||||
"He's a lumberjack and he's okay",
|
'He\'s a lumberjack and he\'s okay',
|
||||||
"He sleeps all night and he works all day"
|
'He sleeps all night and he works all day'
|
||||||
];
|
];
|
||||||
var counts = _(lyrics).chain()
|
var counts = _(lyrics).chain()
|
||||||
.map(function(line) { return line.split(''); })
|
.map(function(line) { return line.split(''); })
|
||||||
|
@ -16,12 +17,14 @@ $(document).ready(function() {
|
||||||
hash[l] = hash[l] || 0;
|
hash[l] = hash[l] || 0;
|
||||||
hash[l]++;
|
hash[l]++;
|
||||||
return hash;
|
return hash;
|
||||||
}, {}).value();
|
}, {})
|
||||||
ok(counts.a == 16 && counts.e == 10, 'counted all the letters in the song');
|
.value();
|
||||||
|
assert.strictEqual(counts.a, 16, 'counted all the letters in the song');
|
||||||
|
assert.strictEqual(counts.e, 10, 'counted all the letters in the song');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("select/reject/sortBy", function() {
|
QUnit.test('select/reject/sortBy', function(assert) {
|
||||||
var numbers = [1,2,3,4,5,6,7,8,9,10];
|
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||||
numbers = _(numbers).chain().select(function(n) {
|
numbers = _(numbers).chain().select(function(n) {
|
||||||
return n % 2 === 0;
|
return n % 2 === 0;
|
||||||
}).reject(function(n) {
|
}).reject(function(n) {
|
||||||
|
@ -29,11 +32,11 @@ $(document).ready(function() {
|
||||||
}).sortBy(function(n) {
|
}).sortBy(function(n) {
|
||||||
return -n;
|
return -n;
|
||||||
}).value();
|
}).value();
|
||||||
equal(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers");
|
assert.deepEqual(numbers, [10, 6, 2], 'filtered and reversed the numbers');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("select/reject/sortBy in functional style", function() {
|
QUnit.test('select/reject/sortBy in functional style', function(assert) {
|
||||||
var numbers = [1,2,3,4,5,6,7,8,9,10];
|
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||||
numbers = _.chain(numbers).select(function(n) {
|
numbers = _.chain(numbers).select(function(n) {
|
||||||
return n % 2 === 0;
|
return n % 2 === 0;
|
||||||
}).reject(function(n) {
|
}).reject(function(n) {
|
||||||
|
@ -41,11 +44,11 @@ $(document).ready(function() {
|
||||||
}).sortBy(function(n) {
|
}).sortBy(function(n) {
|
||||||
return -n;
|
return -n;
|
||||||
}).value();
|
}).value();
|
||||||
equal(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers");
|
assert.deepEqual(numbers, [10, 6, 2], 'filtered and reversed the numbers');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("reverse/concat/unshift/pop/map", function() {
|
QUnit.test('reverse/concat/unshift/pop/map', function(assert) {
|
||||||
var numbers = [1,2,3,4,5];
|
var numbers = [1, 2, 3, 4, 5];
|
||||||
numbers = _(numbers).chain()
|
numbers = _(numbers).chain()
|
||||||
.reverse()
|
.reverse()
|
||||||
.concat([5, 5, 5])
|
.concat([5, 5, 5])
|
||||||
|
@ -53,13 +56,44 @@ $(document).ready(function() {
|
||||||
.pop()
|
.pop()
|
||||||
.map(function(n){ return n * 2; })
|
.map(function(n){ return n * 2; })
|
||||||
.value();
|
.value();
|
||||||
equal(numbers.join(', '), "34, 10, 8, 6, 4, 2, 10, 10", 'can chain together array functions.');
|
assert.deepEqual(numbers, [34, 10, 8, 6, 4, 2, 10, 10], 'can chain together array functions.');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("chaining works in small stages", function() {
|
QUnit.test('splice', function(assert) {
|
||||||
|
var instance = _([1, 2, 3, 4, 5]).chain();
|
||||||
|
assert.deepEqual(instance.splice(1, 3).value(), [1, 5]);
|
||||||
|
assert.deepEqual(instance.splice(1, 0).value(), [1, 5]);
|
||||||
|
assert.deepEqual(instance.splice(1, 1).value(), [1]);
|
||||||
|
assert.deepEqual(instance.splice(0, 1).value(), [], '#397 Can create empty array');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('shift', function(assert) {
|
||||||
|
var instance = _([1, 2, 3]).chain();
|
||||||
|
assert.deepEqual(instance.shift().value(), [2, 3]);
|
||||||
|
assert.deepEqual(instance.shift().value(), [3]);
|
||||||
|
assert.deepEqual(instance.shift().value(), [], '#397 Can create empty array');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('pop', function(assert) {
|
||||||
|
var instance = _([1, 2, 3]).chain();
|
||||||
|
assert.deepEqual(instance.pop().value(), [1, 2]);
|
||||||
|
assert.deepEqual(instance.pop().value(), [1]);
|
||||||
|
assert.deepEqual(instance.pop().value(), [], '#397 Can create empty array');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('chaining works in small stages', function(assert) {
|
||||||
var o = _([1, 2, 3, 4]).chain();
|
var o = _([1, 2, 3, 4]).chain();
|
||||||
deepEqual(o.filter(function(i) { return i < 3; }).value(), [1, 2]);
|
assert.deepEqual(o.filter(function(i) { return i < 3; }).value(), [1, 2]);
|
||||||
deepEqual(o.filter(function(i) { return i > 2; }).value(), [3, 4]);
|
assert.deepEqual(o.filter(function(i) { return i > 2; }).value(), [3, 4]);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
QUnit.test('#1562: Engine proxies for chained functions', function(assert) {
|
||||||
|
var wrapped = _(512);
|
||||||
|
assert.strictEqual(wrapped.toJSON(), 512);
|
||||||
|
assert.strictEqual(wrapped.valueOf(), 512);
|
||||||
|
assert.strictEqual(+wrapped, 512);
|
||||||
|
assert.strictEqual(wrapped.toString(), '512');
|
||||||
|
assert.strictEqual('' + wrapped, '512');
|
||||||
|
});
|
||||||
|
|
||||||
|
}());
|
||||||
|
|
1043
vendor/underscore/test/collections.js
vendored
1043
vendor/underscore/test/collections.js
vendored
File diff suppressed because it is too large
Load diff
142
vendor/underscore/test/cross-document.js
vendored
Normal file
142
vendor/underscore/test/cross-document.js
vendored
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
(function() {
|
||||||
|
if (typeof document == 'undefined') return;
|
||||||
|
|
||||||
|
var _ = typeof require == 'function' ? require('..') : window._;
|
||||||
|
|
||||||
|
QUnit.module('Cross Document');
|
||||||
|
/* global iObject, iElement, iArguments, iFunction, iArray, iError, iString, iNumber, iBoolean, iDate, iRegExp, iNaN, iNull, iUndefined, ActiveXObject */
|
||||||
|
|
||||||
|
// Setup remote variables for iFrame tests.
|
||||||
|
var iframe = document.createElement('iframe');
|
||||||
|
iframe.frameBorder = iframe.height = iframe.width = 0;
|
||||||
|
document.body.appendChild(iframe);
|
||||||
|
var iframeContent = iframe.contentDocument || iframe.contentWindow;
|
||||||
|
var iDoc = iframeContent.document || iframeContent;
|
||||||
|
iDoc.write(
|
||||||
|
[
|
||||||
|
'<script>',
|
||||||
|
'parent.iElement = document.createElement("div");',
|
||||||
|
'parent.iArguments = (function(){ return arguments; })(1, 2, 3);',
|
||||||
|
'parent.iArray = [1, 2, 3];',
|
||||||
|
'parent.iString = new String("hello");',
|
||||||
|
'parent.iNumber = new Number(100);',
|
||||||
|
'parent.iFunction = (function(){});',
|
||||||
|
'parent.iDate = new Date();',
|
||||||
|
'parent.iRegExp = /hi/;',
|
||||||
|
'parent.iNaN = NaN;',
|
||||||
|
'parent.iNull = null;',
|
||||||
|
'parent.iBoolean = new Boolean(false);',
|
||||||
|
'parent.iUndefined = undefined;',
|
||||||
|
'parent.iObject = {};',
|
||||||
|
'parent.iError = new Error();',
|
||||||
|
'</script>'
|
||||||
|
].join('\n')
|
||||||
|
);
|
||||||
|
iDoc.close();
|
||||||
|
|
||||||
|
QUnit.test('isEqual', function(assert) {
|
||||||
|
|
||||||
|
assert.notOk(_.isEqual(iNumber, 101));
|
||||||
|
assert.ok(_.isEqual(iNumber, 100));
|
||||||
|
|
||||||
|
// Objects from another frame.
|
||||||
|
assert.ok(_.isEqual({}, iObject), 'Objects with equivalent members created in different documents are equal');
|
||||||
|
|
||||||
|
// Array from another frame.
|
||||||
|
assert.ok(_.isEqual([1, 2, 3], iArray), 'Arrays with equivalent elements created in different documents are equal');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('isEmpty', function(assert) {
|
||||||
|
assert.notOk(_([iNumber]).isEmpty(), '[1] is not empty');
|
||||||
|
assert.notOk(_.isEmpty(iArray), '[] is empty');
|
||||||
|
assert.ok(_.isEmpty(iObject), '{} is empty');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('isElement', function(assert) {
|
||||||
|
assert.notOk(_.isElement('div'), 'strings are not dom elements');
|
||||||
|
assert.ok(_.isElement(document.body), 'the body tag is a DOM element');
|
||||||
|
assert.ok(_.isElement(iElement), 'even from another frame');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('isArguments', function(assert) {
|
||||||
|
assert.ok(_.isArguments(iArguments), 'even from another frame');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('isObject', function(assert) {
|
||||||
|
assert.ok(_.isObject(iElement), 'even from another frame');
|
||||||
|
assert.ok(_.isObject(iFunction), 'even from another frame');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('isArray', function(assert) {
|
||||||
|
assert.ok(_.isArray(iArray), 'even from another frame');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('isString', function(assert) {
|
||||||
|
assert.ok(_.isString(iString), 'even from another frame');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('isNumber', function(assert) {
|
||||||
|
assert.ok(_.isNumber(iNumber), 'even from another frame');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('isBoolean', function(assert) {
|
||||||
|
assert.ok(_.isBoolean(iBoolean), 'even from another frame');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('isFunction', function(assert) {
|
||||||
|
assert.ok(_.isFunction(iFunction), 'even from another frame');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('isDate', function(assert) {
|
||||||
|
assert.ok(_.isDate(iDate), 'even from another frame');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('isRegExp', function(assert) {
|
||||||
|
assert.ok(_.isRegExp(iRegExp), 'even from another frame');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('isNaN', function(assert) {
|
||||||
|
assert.ok(_.isNaN(iNaN), 'even from another frame');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('isNull', function(assert) {
|
||||||
|
assert.ok(_.isNull(iNull), 'even from another frame');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('isUndefined', function(assert) {
|
||||||
|
assert.ok(_.isUndefined(iUndefined), 'even from another frame');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('isError', function(assert) {
|
||||||
|
assert.ok(_.isError(iError), 'even from another frame');
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof ActiveXObject != 'undefined') {
|
||||||
|
QUnit.test('IE host objects', function(assert) {
|
||||||
|
var xml = new ActiveXObject('Msxml2.DOMDocument.3.0');
|
||||||
|
assert.notOk(_.isNumber(xml));
|
||||||
|
assert.notOk(_.isBoolean(xml));
|
||||||
|
assert.notOk(_.isNaN(xml));
|
||||||
|
assert.notOk(_.isFunction(xml));
|
||||||
|
assert.notOk(_.isNull(xml));
|
||||||
|
assert.notOk(_.isUndefined(xml));
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('#1621 IE 11 compat mode DOM elements are not functions', function(assert) {
|
||||||
|
var fn = function() {};
|
||||||
|
var xml = new ActiveXObject('Msxml2.DOMDocument.3.0');
|
||||||
|
var div = document.createElement('div');
|
||||||
|
|
||||||
|
// JIT the function
|
||||||
|
var count = 200;
|
||||||
|
while (count--) {
|
||||||
|
_.isFunction(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.strictEqual(_.isFunction(xml), false);
|
||||||
|
assert.strictEqual(_.isFunction(div), false);
|
||||||
|
assert.strictEqual(_.isFunction(fn), true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}());
|
667
vendor/underscore/test/functions.js
vendored
667
vendor/underscore/test/functions.js
vendored
|
@ -1,162 +1,265 @@
|
||||||
$(document).ready(function() {
|
(function() {
|
||||||
|
var _ = typeof require == 'function' ? require('..') : window._;
|
||||||
|
|
||||||
module("Functions");
|
QUnit.module('Functions');
|
||||||
|
QUnit.config.asyncRetries = 3;
|
||||||
|
|
||||||
test("bind", function() {
|
QUnit.test('bind', function(assert) {
|
||||||
var context = {name : 'moe'};
|
var context = {name: 'moe'};
|
||||||
var func = function(arg) { return "name: " + (this.name || arg); };
|
var func = function(arg) { return 'name: ' + (this.name || arg); };
|
||||||
var bound = _.bind(func, context);
|
var bound = _.bind(func, context);
|
||||||
equal(bound(), 'name: moe', 'can bind a function to a context');
|
assert.strictEqual(bound(), 'name: moe', 'can bind a function to a context');
|
||||||
|
|
||||||
bound = _(func).bind(context);
|
bound = _(func).bind(context);
|
||||||
equal(bound(), 'name: moe', 'can do OO-style binding');
|
assert.strictEqual(bound(), 'name: moe', 'can do OO-style binding');
|
||||||
|
|
||||||
bound = _.bind(func, null, 'curly');
|
bound = _.bind(func, null, 'curly');
|
||||||
equal(bound(), 'name: curly', 'can bind without specifying a context');
|
var result = bound();
|
||||||
|
// Work around a PhantomJS bug when applying a function with null|undefined.
|
||||||
|
assert.ok(result === 'name: curly' || result === 'name: ' + window.name, 'can bind without specifying a context');
|
||||||
|
|
||||||
func = function(salutation, name) { return salutation + ': ' + name; };
|
func = function(salutation, name) { return salutation + ': ' + name; };
|
||||||
func = _.bind(func, this, 'hello');
|
func = _.bind(func, this, 'hello');
|
||||||
equal(func('moe'), 'hello: moe', 'the function was partially applied in advance');
|
assert.strictEqual(func('moe'), 'hello: moe', 'the function was partially applied in advance');
|
||||||
|
|
||||||
func = _.bind(func, this, 'curly');
|
func = _.bind(func, this, 'curly');
|
||||||
equal(func(), 'hello: curly', 'the function was completely applied in advance');
|
assert.strictEqual(func(), 'hello: curly', 'the function was completely applied in advance');
|
||||||
|
|
||||||
func = function(salutation, firstname, lastname) { return salutation + ': ' + firstname + ' ' + lastname; };
|
func = function(salutation, firstname, lastname) { return salutation + ': ' + firstname + ' ' + lastname; };
|
||||||
func = _.bind(func, this, 'hello', 'moe', 'curly');
|
func = _.bind(func, this, 'hello', 'moe', 'curly');
|
||||||
equal(func(), 'hello: moe curly', 'the function was partially applied in advance and can accept multiple arguments');
|
assert.strictEqual(func(), 'hello: moe curly', 'the function was partially applied in advance and can accept multiple arguments');
|
||||||
|
|
||||||
func = function(context, message) { equal(this, context, message); };
|
func = function() { return this; };
|
||||||
_.bind(func, 0, 0, 'can bind a function to `0`')();
|
assert.strictEqual(typeof _.bind(func, 0)(), 'object', 'binding a primitive to `this` returns a wrapped primitive');
|
||||||
_.bind(func, '', '', 'can bind a function to an empty string')();
|
|
||||||
_.bind(func, false, false, 'can bind a function to `false`')();
|
assert.strictEqual(_.bind(func, 0)().valueOf(), 0, 'can bind a function to `0`');
|
||||||
|
assert.strictEqual(_.bind(func, '')().valueOf(), '', 'can bind a function to an empty string');
|
||||||
|
assert.strictEqual(_.bind(func, false)().valueOf(), false, 'can bind a function to `false`');
|
||||||
|
|
||||||
// These tests are only meaningful when using a browser without a native bind function
|
// These tests are only meaningful when using a browser without a native bind function
|
||||||
// To test this with a modern browser, set underscore's nativeBind to undefined
|
// To test this with a modern browser, set underscore's nativeBind to undefined
|
||||||
var F = function () { return this; };
|
var F = function() { return this; };
|
||||||
var Boundf = _.bind(F, {hello: "moe curly"});
|
var boundf = _.bind(F, {hello: 'moe curly'});
|
||||||
|
var Boundf = boundf; // make eslint happy.
|
||||||
var newBoundf = new Boundf();
|
var newBoundf = new Boundf();
|
||||||
equal(newBoundf.hello, undefined, "function should not be bound to the context, to comply with ECMAScript 5");
|
assert.strictEqual(newBoundf.hello, void 0, 'function should not be bound to the context, to comply with ECMAScript 5');
|
||||||
equal(Boundf().hello, "moe curly", "When called without the new operator, it's OK to be bound to the context");
|
assert.strictEqual(boundf().hello, 'moe curly', "When called without the new operator, it's OK to be bound to the context");
|
||||||
ok(newBoundf instanceof F, "a bound instance is an instance of the original function");
|
assert.ok(newBoundf instanceof F, 'a bound instance is an instance of the original function');
|
||||||
|
|
||||||
|
assert.raises(function() { _.bind('notafunction'); }, TypeError, 'throws an error when binding to a non-function');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("partial", function() {
|
QUnit.test('partial', function(assert) {
|
||||||
var obj = {name: 'moe'};
|
var obj = {name: 'moe'};
|
||||||
var func = function() { return this.name + ' ' + _.toArray(arguments).join(' '); };
|
var func = function() { return this.name + ' ' + _.toArray(arguments).join(' '); };
|
||||||
|
|
||||||
obj.func = _.partial(func, 'a', 'b');
|
obj.func = _.partial(func, 'a', 'b');
|
||||||
equal(obj.func('c', 'd'), 'moe a b c d', 'can partially apply');
|
assert.strictEqual(obj.func('c', 'd'), 'moe a b c d', 'can partially apply');
|
||||||
|
|
||||||
|
obj.func = _.partial(func, _, 'b', _, 'd');
|
||||||
|
assert.strictEqual(obj.func('a', 'c'), 'moe a b c d', 'can partially apply with placeholders');
|
||||||
|
|
||||||
|
func = _.partial(function() { return arguments.length; }, _, 'b', _, 'd');
|
||||||
|
assert.strictEqual(func('a', 'c', 'e'), 5, 'accepts more arguments than the number of placeholders');
|
||||||
|
assert.strictEqual(func('a'), 4, 'accepts fewer arguments than the number of placeholders');
|
||||||
|
|
||||||
|
func = _.partial(function() { return typeof arguments[2]; }, _, 'b', _, 'd');
|
||||||
|
assert.strictEqual(func('a'), 'undefined', 'unfilled placeholders are undefined');
|
||||||
|
|
||||||
|
// passes context
|
||||||
|
function MyWidget(name, options) {
|
||||||
|
this.name = name;
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
|
MyWidget.prototype.get = function() {
|
||||||
|
return this.name;
|
||||||
|
};
|
||||||
|
var MyWidgetWithCoolOpts = _.partial(MyWidget, _, {a: 1});
|
||||||
|
var widget = new MyWidgetWithCoolOpts('foo');
|
||||||
|
assert.ok(widget instanceof MyWidget, 'Can partially bind a constructor');
|
||||||
|
assert.strictEqual(widget.get(), 'foo', 'keeps prototype');
|
||||||
|
assert.deepEqual(widget.options, {a: 1});
|
||||||
|
|
||||||
|
_.partial.placeholder = obj;
|
||||||
|
func = _.partial(function() { return arguments.length; }, obj, 'b', obj, 'd');
|
||||||
|
assert.strictEqual(func('a'), 4, 'allows the placeholder to be swapped out');
|
||||||
|
|
||||||
|
_.partial.placeholder = {};
|
||||||
|
func = _.partial(function() { return arguments.length; }, obj, 'b', obj, 'd');
|
||||||
|
assert.strictEqual(func('a'), 5, 'swapping the placeholder preserves previously bound arguments');
|
||||||
|
|
||||||
|
_.partial.placeholder = _;
|
||||||
});
|
});
|
||||||
|
|
||||||
test("bindAll", function() {
|
QUnit.test('bindAll', function(assert) {
|
||||||
var curly = {name : 'curly'}, moe = {
|
var curly = {name: 'curly'};
|
||||||
name : 'moe',
|
var moe = {
|
||||||
getName : function() { return 'name: ' + this.name; },
|
name: 'moe',
|
||||||
sayHi : function() { return 'hi: ' + this.name; }
|
getName: function() { return 'name: ' + this.name; },
|
||||||
|
sayHi: function() { return 'hi: ' + this.name; }
|
||||||
};
|
};
|
||||||
curly.getName = moe.getName;
|
curly.getName = moe.getName;
|
||||||
_.bindAll(moe, 'getName', 'sayHi');
|
_.bindAll(moe, 'getName', 'sayHi');
|
||||||
curly.sayHi = moe.sayHi;
|
curly.sayHi = moe.sayHi;
|
||||||
equal(curly.getName(), 'name: curly', 'unbound function is bound to current object');
|
assert.strictEqual(curly.getName(), 'name: curly', 'unbound function is bound to current object');
|
||||||
equal(curly.sayHi(), 'hi: moe', 'bound function is still bound to original object');
|
assert.strictEqual(curly.sayHi(), 'hi: moe', 'bound function is still bound to original object');
|
||||||
|
|
||||||
curly = {name : 'curly'};
|
curly = {name: 'curly'};
|
||||||
moe = {
|
moe = {
|
||||||
name : 'moe',
|
name: 'moe',
|
||||||
getName : function() { return 'name: ' + this.name; },
|
getName: function() { return 'name: ' + this.name; },
|
||||||
sayHi : function() { return 'hi: ' + this.name; }
|
sayHi: function() { return 'hi: ' + this.name; },
|
||||||
|
sayLast: function() { return this.sayHi(_.last(arguments)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
raises(function() { _.bindAll(moe); }, Error, 'throws an error for bindAll with no functions named');
|
assert.raises(function() { _.bindAll(moe); }, Error, 'throws an error for bindAll with no functions named');
|
||||||
|
assert.raises(function() { _.bindAll(moe, 'sayBye'); }, TypeError, 'throws an error for bindAll if the given key is undefined');
|
||||||
|
assert.raises(function() { _.bindAll(moe, 'name'); }, TypeError, 'throws an error for bindAll if the given key is not a function');
|
||||||
|
|
||||||
_.bindAll(moe, 'sayHi');
|
_.bindAll(moe, 'sayHi', 'sayLast');
|
||||||
curly.sayHi = moe.sayHi;
|
curly.sayHi = moe.sayHi;
|
||||||
equal(curly.sayHi(), 'hi: moe');
|
assert.strictEqual(curly.sayHi(), 'hi: moe');
|
||||||
|
|
||||||
|
var sayLast = moe.sayLast;
|
||||||
|
assert.strictEqual(sayLast(1, 2, 3, 4, 5, 6, 7, 'Tom'), 'hi: moe', 'createCallback works with any number of arguments');
|
||||||
|
|
||||||
|
_.bindAll(moe, ['getName']);
|
||||||
|
var getName = moe.getName;
|
||||||
|
assert.strictEqual(getName(), 'name: moe', 'flattens arguments into a single list');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("memoize", function() {
|
QUnit.test('memoize', function(assert) {
|
||||||
var fib = function(n) {
|
var fib = function(n) {
|
||||||
return n < 2 ? n : fib(n - 1) + fib(n - 2);
|
return n < 2 ? n : fib(n - 1) + fib(n - 2);
|
||||||
};
|
};
|
||||||
equal(fib(10), 55, 'a memoized version of fibonacci produces identical results');
|
assert.strictEqual(fib(10), 55, 'a memoized version of fibonacci produces identical results');
|
||||||
fib = _.memoize(fib); // Redefine `fib` for memoization
|
fib = _.memoize(fib); // Redefine `fib` for memoization
|
||||||
equal(fib(10), 55, 'a memoized version of fibonacci produces identical results');
|
assert.strictEqual(fib(10), 55, 'a memoized version of fibonacci produces identical results');
|
||||||
|
|
||||||
var o = function(str) {
|
var o = function(str) {
|
||||||
return str;
|
return str;
|
||||||
};
|
};
|
||||||
var fastO = _.memoize(o);
|
var fastO = _.memoize(o);
|
||||||
equal(o('toString'), 'toString', 'checks hasOwnProperty');
|
assert.strictEqual(o('toString'), 'toString', 'checks hasOwnProperty');
|
||||||
equal(fastO('toString'), 'toString', 'checks hasOwnProperty');
|
assert.strictEqual(fastO('toString'), 'toString', 'checks hasOwnProperty');
|
||||||
|
|
||||||
|
// Expose the cache.
|
||||||
|
var upper = _.memoize(function(s) {
|
||||||
|
return s.toUpperCase();
|
||||||
|
});
|
||||||
|
assert.strictEqual(upper('foo'), 'FOO');
|
||||||
|
assert.strictEqual(upper('bar'), 'BAR');
|
||||||
|
assert.deepEqual(upper.cache, {foo: 'FOO', bar: 'BAR'});
|
||||||
|
upper.cache = {foo: 'BAR', bar: 'FOO'};
|
||||||
|
assert.strictEqual(upper('foo'), 'BAR');
|
||||||
|
assert.strictEqual(upper('bar'), 'FOO');
|
||||||
|
|
||||||
|
var hashed = _.memoize(function(key) {
|
||||||
|
//https://github.com/jashkenas/underscore/pull/1679#discussion_r13736209
|
||||||
|
assert.ok(/[a-z]+/.test(key), 'hasher doesn\'t change keys');
|
||||||
|
return key;
|
||||||
|
}, function(key) {
|
||||||
|
return key.toUpperCase();
|
||||||
|
});
|
||||||
|
hashed('yep');
|
||||||
|
assert.deepEqual(hashed.cache, {YEP: 'yep'}, 'takes a hasher');
|
||||||
|
|
||||||
|
// Test that the hash function can be used to swizzle the key.
|
||||||
|
var objCacher = _.memoize(function(value, key) {
|
||||||
|
return {key: key, value: value};
|
||||||
|
}, function(value, key) {
|
||||||
|
return key;
|
||||||
|
});
|
||||||
|
var myObj = objCacher('a', 'alpha');
|
||||||
|
var myObjAlias = objCacher('b', 'alpha');
|
||||||
|
assert.notStrictEqual(myObj, void 0, 'object is created if second argument used as key');
|
||||||
|
assert.strictEqual(myObj, myObjAlias, 'object is cached if second argument used as key');
|
||||||
|
assert.strictEqual(myObj.value, 'a', 'object is not modified if second argument used as key');
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("delay", 2, function() {
|
QUnit.test('delay', function(assert) {
|
||||||
|
assert.expect(2);
|
||||||
|
var done = assert.async();
|
||||||
var delayed = false;
|
var delayed = false;
|
||||||
_.delay(function(){ delayed = true; }, 100);
|
_.delay(function(){ delayed = true; }, 100);
|
||||||
setTimeout(function(){ ok(!delayed, "didn't delay the function quite yet"); }, 50);
|
setTimeout(function(){ assert.notOk(delayed, "didn't delay the function quite yet"); }, 50);
|
||||||
setTimeout(function(){ ok(delayed, 'delayed the function'); start(); }, 150);
|
setTimeout(function(){ assert.ok(delayed, 'delayed the function'); done(); }, 150);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("defer", 1, function() {
|
QUnit.test('defer', function(assert) {
|
||||||
|
assert.expect(1);
|
||||||
|
var done = assert.async();
|
||||||
var deferred = false;
|
var deferred = false;
|
||||||
_.defer(function(bool){ deferred = bool; }, true);
|
_.defer(function(bool){ deferred = bool; }, true);
|
||||||
_.delay(function(){ ok(deferred, "deferred the function"); start(); }, 50);
|
_.delay(function(){ assert.ok(deferred, 'deferred the function'); done(); }, 50);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("throttle", 2, function() {
|
QUnit.test('throttle', function(assert) {
|
||||||
|
assert.expect(2);
|
||||||
|
var done = assert.async();
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var incr = function(){ counter++; };
|
var incr = function(){ counter++; };
|
||||||
var throttledIncr = _.throttle(incr, 32);
|
var throttledIncr = _.throttle(incr, 32);
|
||||||
throttledIncr(); throttledIncr();
|
throttledIncr(); throttledIncr();
|
||||||
|
|
||||||
equal(counter, 1, "incr was called immediately");
|
assert.strictEqual(counter, 1, 'incr was called immediately');
|
||||||
_.delay(function(){ equal(counter, 2, "incr was throttled"); start(); }, 64);
|
_.delay(function(){ assert.strictEqual(counter, 2, 'incr was throttled'); done(); }, 64);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("throttle arguments", 2, function() {
|
QUnit.test('throttle arguments', function(assert) {
|
||||||
|
assert.expect(2);
|
||||||
|
var done = assert.async();
|
||||||
var value = 0;
|
var value = 0;
|
||||||
var update = function(val){ value = val; };
|
var update = function(val){ value = val; };
|
||||||
var throttledUpdate = _.throttle(update, 32);
|
var throttledUpdate = _.throttle(update, 32);
|
||||||
throttledUpdate(1); throttledUpdate(2);
|
throttledUpdate(1); throttledUpdate(2);
|
||||||
_.delay(function(){ throttledUpdate(3); }, 64);
|
_.delay(function(){ throttledUpdate(3); }, 64);
|
||||||
equal(value, 1, "updated to latest value");
|
assert.strictEqual(value, 1, 'updated to latest value');
|
||||||
_.delay(function(){ equal(value, 3, "updated to latest value"); start(); }, 96);
|
_.delay(function(){ assert.strictEqual(value, 3, 'updated to latest value'); done(); }, 96);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("throttle once", 2, function() {
|
QUnit.test('throttle once', function(assert) {
|
||||||
|
assert.expect(2);
|
||||||
|
var done = assert.async();
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var incr = function(){ return ++counter; };
|
var incr = function(){ return ++counter; };
|
||||||
var throttledIncr = _.throttle(incr, 32);
|
var throttledIncr = _.throttle(incr, 32);
|
||||||
var result = throttledIncr();
|
var result = throttledIncr();
|
||||||
_.delay(function(){
|
_.delay(function(){
|
||||||
equal(result, 1, "throttled functions return their value");
|
assert.strictEqual(result, 1, 'throttled functions return their value');
|
||||||
equal(counter, 1, "incr was called once"); start();
|
assert.strictEqual(counter, 1, 'incr was called once'); done();
|
||||||
}, 64);
|
}, 64);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("throttle twice", 1, function() {
|
QUnit.test('throttle twice', function(assert) {
|
||||||
|
assert.expect(1);
|
||||||
|
var done = assert.async();
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var incr = function(){ counter++; };
|
var incr = function(){ counter++; };
|
||||||
var throttledIncr = _.throttle(incr, 32);
|
var throttledIncr = _.throttle(incr, 32);
|
||||||
throttledIncr(); throttledIncr();
|
throttledIncr(); throttledIncr();
|
||||||
_.delay(function(){ equal(counter, 2, "incr was called twice"); start(); }, 64);
|
_.delay(function(){ assert.strictEqual(counter, 2, 'incr was called twice'); done(); }, 64);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("more throttling", 3, function() {
|
QUnit.test('more throttling', function(assert) {
|
||||||
|
assert.expect(3);
|
||||||
|
var done = assert.async();
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var incr = function(){ counter++; };
|
var incr = function(){ counter++; };
|
||||||
var throttledIncr = _.throttle(incr, 30);
|
var throttledIncr = _.throttle(incr, 30);
|
||||||
throttledIncr(); throttledIncr();
|
throttledIncr(); throttledIncr();
|
||||||
ok(counter == 1);
|
assert.strictEqual(counter, 1);
|
||||||
_.delay(function(){
|
_.delay(function(){
|
||||||
ok(counter == 2);
|
assert.strictEqual(counter, 2);
|
||||||
throttledIncr();
|
throttledIncr();
|
||||||
ok(counter == 3);
|
assert.strictEqual(counter, 3);
|
||||||
start();
|
done();
|
||||||
}, 85);
|
}, 85);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("throttle repeatedly with results", 6, function() {
|
QUnit.test('throttle repeatedly with results', function(assert) {
|
||||||
|
assert.expect(6);
|
||||||
|
var done = assert.async();
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var incr = function(){ return ++counter; };
|
var incr = function(){ return ++counter; };
|
||||||
var throttledIncr = _.throttle(incr, 100);
|
var throttledIncr = _.throttle(incr, 100);
|
||||||
|
@ -168,50 +271,56 @@ $(document).ready(function() {
|
||||||
_.delay(saveResult, 160);
|
_.delay(saveResult, 160);
|
||||||
_.delay(saveResult, 230);
|
_.delay(saveResult, 230);
|
||||||
_.delay(function() {
|
_.delay(function() {
|
||||||
equal(results[0], 1, "incr was called once");
|
assert.strictEqual(results[0], 1, 'incr was called once');
|
||||||
equal(results[1], 1, "incr was throttled");
|
assert.strictEqual(results[1], 1, 'incr was throttled');
|
||||||
equal(results[2], 1, "incr was throttled");
|
assert.strictEqual(results[2], 1, 'incr was throttled');
|
||||||
equal(results[3], 2, "incr was called twice");
|
assert.strictEqual(results[3], 2, 'incr was called twice');
|
||||||
equal(results[4], 2, "incr was throttled");
|
assert.strictEqual(results[4], 2, 'incr was throttled');
|
||||||
equal(results[5], 3, "incr was called trailing");
|
assert.strictEqual(results[5], 3, 'incr was called trailing');
|
||||||
start();
|
done();
|
||||||
}, 300);
|
}, 300);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("throttle triggers trailing call when invoked repeatedly", 2, function() {
|
QUnit.test('throttle triggers trailing call when invoked repeatedly', function(assert) {
|
||||||
|
assert.expect(2);
|
||||||
|
var done = assert.async();
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var limit = 48;
|
var limit = 48;
|
||||||
var incr = function(){ counter++; };
|
var incr = function(){ counter++; };
|
||||||
var throttledIncr = _.throttle(incr, 32);
|
var throttledIncr = _.throttle(incr, 32);
|
||||||
|
|
||||||
var stamp = new Date;
|
var stamp = new Date;
|
||||||
while ((new Date - stamp) < limit) {
|
while (new Date - stamp < limit) {
|
||||||
throttledIncr();
|
throttledIncr();
|
||||||
}
|
}
|
||||||
var lastCount = counter;
|
var lastCount = counter;
|
||||||
ok(counter > 1);
|
assert.ok(counter > 1);
|
||||||
|
|
||||||
_.delay(function() {
|
_.delay(function() {
|
||||||
ok(counter > lastCount);
|
assert.ok(counter > lastCount);
|
||||||
start();
|
done();
|
||||||
}, 96);
|
}, 96);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("throttle does not trigger leading call when leading is set to false", 2, function() {
|
QUnit.test('throttle does not trigger leading call when leading is set to false', function(assert) {
|
||||||
|
assert.expect(2);
|
||||||
|
var done = assert.async();
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var incr = function(){ counter++; };
|
var incr = function(){ counter++; };
|
||||||
var throttledIncr = _.throttle(incr, 60, {leading: false});
|
var throttledIncr = _.throttle(incr, 60, {leading: false});
|
||||||
|
|
||||||
throttledIncr(); throttledIncr();
|
throttledIncr(); throttledIncr();
|
||||||
ok(counter === 0);
|
assert.strictEqual(counter, 0);
|
||||||
|
|
||||||
_.delay(function() {
|
_.delay(function() {
|
||||||
ok(counter == 1);
|
assert.strictEqual(counter, 1);
|
||||||
start();
|
done();
|
||||||
}, 96);
|
}, 96);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("more throttle does not trigger leading call when leading is set to false", 3, function() {
|
QUnit.test('more throttle does not trigger leading call when leading is set to false', function(assert) {
|
||||||
|
assert.expect(3);
|
||||||
|
var done = assert.async();
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var incr = function(){ counter++; };
|
var incr = function(){ counter++; };
|
||||||
var throttledIncr = _.throttle(incr, 100, {leading: false});
|
var throttledIncr = _.throttle(incr, 100, {leading: false});
|
||||||
|
@ -220,133 +329,325 @@ $(document).ready(function() {
|
||||||
_.delay(throttledIncr, 50);
|
_.delay(throttledIncr, 50);
|
||||||
_.delay(throttledIncr, 60);
|
_.delay(throttledIncr, 60);
|
||||||
_.delay(throttledIncr, 200);
|
_.delay(throttledIncr, 200);
|
||||||
ok(counter === 0);
|
assert.strictEqual(counter, 0);
|
||||||
|
|
||||||
_.delay(function() {
|
_.delay(function() {
|
||||||
ok(counter == 1);
|
assert.strictEqual(counter, 1);
|
||||||
}, 250);
|
}, 250);
|
||||||
|
|
||||||
_.delay(function() {
|
_.delay(function() {
|
||||||
ok(counter == 2);
|
assert.strictEqual(counter, 2);
|
||||||
start();
|
done();
|
||||||
}, 350);
|
}, 350);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("one more throttle with leading: false test", 2, function() {
|
QUnit.test('one more throttle with leading: false test', function(assert) {
|
||||||
|
assert.expect(2);
|
||||||
|
var done = assert.async();
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var incr = function(){ counter++; };
|
var incr = function(){ counter++; };
|
||||||
var throttledIncr = _.throttle(incr, 100, {leading: false});
|
var throttledIncr = _.throttle(incr, 100, {leading: false});
|
||||||
|
|
||||||
var time = new Date;
|
var time = new Date;
|
||||||
while (new Date - time < 350) throttledIncr();
|
while (new Date - time < 350) throttledIncr();
|
||||||
ok(counter <= 3);
|
assert.ok(counter <= 3);
|
||||||
|
|
||||||
_.delay(function() {
|
_.delay(function() {
|
||||||
ok(counter <= 4);
|
assert.ok(counter <= 4);
|
||||||
start();
|
done();
|
||||||
}, 200);
|
}, 200);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("throttle does not trigger trailing call when trailing is set to false", 4, function() {
|
QUnit.test('throttle does not trigger trailing call when trailing is set to false', function(assert) {
|
||||||
|
assert.expect(4);
|
||||||
|
var done = assert.async();
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var incr = function(){ counter++; };
|
var incr = function(){ counter++; };
|
||||||
var throttledIncr = _.throttle(incr, 60, {trailing: false});
|
var throttledIncr = _.throttle(incr, 60, {trailing: false});
|
||||||
|
|
||||||
throttledIncr(); throttledIncr(); throttledIncr();
|
throttledIncr(); throttledIncr(); throttledIncr();
|
||||||
ok(counter === 1);
|
assert.strictEqual(counter, 1);
|
||||||
|
|
||||||
_.delay(function() {
|
_.delay(function() {
|
||||||
ok(counter == 1);
|
assert.strictEqual(counter, 1);
|
||||||
|
|
||||||
throttledIncr(); throttledIncr();
|
throttledIncr(); throttledIncr();
|
||||||
ok(counter == 2);
|
assert.strictEqual(counter, 2);
|
||||||
|
|
||||||
_.delay(function() {
|
_.delay(function() {
|
||||||
ok(counter == 2);
|
assert.strictEqual(counter, 2);
|
||||||
start();
|
done();
|
||||||
}, 96);
|
}, 96);
|
||||||
}, 96);
|
}, 96);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("debounce", 1, function() {
|
QUnit.test('throttle continues to function after system time is set backwards', function(assert) {
|
||||||
|
assert.expect(2);
|
||||||
|
var done = assert.async();
|
||||||
|
var counter = 0;
|
||||||
|
var incr = function(){ counter++; };
|
||||||
|
var throttledIncr = _.throttle(incr, 100);
|
||||||
|
var origNowFunc = _.now;
|
||||||
|
|
||||||
|
throttledIncr();
|
||||||
|
assert.strictEqual(counter, 1);
|
||||||
|
_.now = function() {
|
||||||
|
return new Date(2013, 0, 1, 1, 1, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
_.delay(function() {
|
||||||
|
throttledIncr();
|
||||||
|
assert.strictEqual(counter, 2);
|
||||||
|
done();
|
||||||
|
_.now = origNowFunc;
|
||||||
|
}, 200);
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('throttle re-entrant', function(assert) {
|
||||||
|
assert.expect(2);
|
||||||
|
var done = assert.async();
|
||||||
|
var sequence = [
|
||||||
|
['b1', 'b2'],
|
||||||
|
['c1', 'c2']
|
||||||
|
];
|
||||||
|
var value = '';
|
||||||
|
var throttledAppend;
|
||||||
|
var append = function(arg){
|
||||||
|
value += this + arg;
|
||||||
|
var args = sequence.pop();
|
||||||
|
if (args) {
|
||||||
|
throttledAppend.call(args[0], args[1]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
throttledAppend = _.throttle(append, 32);
|
||||||
|
throttledAppend.call('a1', 'a2');
|
||||||
|
assert.strictEqual(value, 'a1a2');
|
||||||
|
_.delay(function(){
|
||||||
|
assert.strictEqual(value, 'a1a2c1c2b1b2', 'append was throttled successfully');
|
||||||
|
done();
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('throttle cancel', function(assert) {
|
||||||
|
var done = assert.async();
|
||||||
|
var counter = 0;
|
||||||
|
var incr = function(){ counter++; };
|
||||||
|
var throttledIncr = _.throttle(incr, 32);
|
||||||
|
throttledIncr();
|
||||||
|
throttledIncr.cancel();
|
||||||
|
throttledIncr();
|
||||||
|
throttledIncr();
|
||||||
|
|
||||||
|
assert.strictEqual(counter, 2, 'incr was called immediately');
|
||||||
|
_.delay(function(){ assert.strictEqual(counter, 3, 'incr was throttled'); done(); }, 64);
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('throttle cancel with leading: false', function(assert) {
|
||||||
|
var done = assert.async();
|
||||||
|
var counter = 0;
|
||||||
|
var incr = function(){ counter++; };
|
||||||
|
var throttledIncr = _.throttle(incr, 32, {leading: false});
|
||||||
|
throttledIncr();
|
||||||
|
throttledIncr.cancel();
|
||||||
|
|
||||||
|
assert.strictEqual(counter, 0, 'incr was throttled');
|
||||||
|
_.delay(function(){ assert.strictEqual(counter, 0, 'incr was throttled'); done(); }, 64);
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('debounce', function(assert) {
|
||||||
|
assert.expect(1);
|
||||||
|
var done = assert.async();
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var incr = function(){ counter++; };
|
var incr = function(){ counter++; };
|
||||||
var debouncedIncr = _.debounce(incr, 32);
|
var debouncedIncr = _.debounce(incr, 32);
|
||||||
debouncedIncr(); debouncedIncr();
|
debouncedIncr(); debouncedIncr();
|
||||||
_.delay(debouncedIncr, 16);
|
_.delay(debouncedIncr, 16);
|
||||||
_.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 96);
|
_.delay(function(){ assert.strictEqual(counter, 1, 'incr was debounced'); done(); }, 96);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("debounce asap", 4, function() {
|
QUnit.test('debounce cancel', function(assert) {
|
||||||
var a, b;
|
assert.expect(1);
|
||||||
|
var done = assert.async();
|
||||||
|
var counter = 0;
|
||||||
|
var incr = function(){ counter++; };
|
||||||
|
var debouncedIncr = _.debounce(incr, 32);
|
||||||
|
debouncedIncr();
|
||||||
|
debouncedIncr.cancel();
|
||||||
|
_.delay(function(){ assert.strictEqual(counter, 0, 'incr was not called'); done(); }, 96);
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('debounce asap', function(assert) {
|
||||||
|
assert.expect(6);
|
||||||
|
var done = assert.async();
|
||||||
|
var a, b, c;
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var incr = function(){ return ++counter; };
|
var incr = function(){ return ++counter; };
|
||||||
var debouncedIncr = _.debounce(incr, 64, true);
|
var debouncedIncr = _.debounce(incr, 64, true);
|
||||||
a = debouncedIncr();
|
a = debouncedIncr();
|
||||||
b = debouncedIncr();
|
b = debouncedIncr();
|
||||||
equal(a, 1);
|
assert.strictEqual(a, 1);
|
||||||
equal(b, 1);
|
assert.strictEqual(b, 1);
|
||||||
equal(counter, 1, 'incr was called immediately');
|
assert.strictEqual(counter, 1, 'incr was called immediately');
|
||||||
_.delay(debouncedIncr, 16);
|
_.delay(debouncedIncr, 16);
|
||||||
_.delay(debouncedIncr, 32);
|
_.delay(debouncedIncr, 32);
|
||||||
_.delay(debouncedIncr, 48);
|
_.delay(debouncedIncr, 48);
|
||||||
_.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 128);
|
_.delay(function(){
|
||||||
|
assert.strictEqual(counter, 1, 'incr was debounced');
|
||||||
|
c = debouncedIncr();
|
||||||
|
assert.strictEqual(c, 2);
|
||||||
|
assert.strictEqual(counter, 2, 'incr was called again');
|
||||||
|
done();
|
||||||
|
}, 128);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("debounce asap recursively", 2, function() {
|
QUnit.test('debounce asap cancel', function(assert) {
|
||||||
|
assert.expect(4);
|
||||||
|
var done = assert.async();
|
||||||
|
var a, b;
|
||||||
|
var counter = 0;
|
||||||
|
var incr = function(){ return ++counter; };
|
||||||
|
var debouncedIncr = _.debounce(incr, 64, true);
|
||||||
|
a = debouncedIncr();
|
||||||
|
debouncedIncr.cancel();
|
||||||
|
b = debouncedIncr();
|
||||||
|
assert.strictEqual(a, 1);
|
||||||
|
assert.strictEqual(b, 2);
|
||||||
|
assert.strictEqual(counter, 2, 'incr was called immediately');
|
||||||
|
_.delay(debouncedIncr, 16);
|
||||||
|
_.delay(debouncedIncr, 32);
|
||||||
|
_.delay(debouncedIncr, 48);
|
||||||
|
_.delay(function(){ assert.strictEqual(counter, 2, 'incr was debounced'); done(); }, 128);
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('debounce asap recursively', function(assert) {
|
||||||
|
assert.expect(2);
|
||||||
|
var done = assert.async();
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var debouncedIncr = _.debounce(function(){
|
var debouncedIncr = _.debounce(function(){
|
||||||
counter++;
|
counter++;
|
||||||
if (counter < 10) debouncedIncr();
|
if (counter < 10) debouncedIncr();
|
||||||
}, 32, true);
|
}, 32, true);
|
||||||
debouncedIncr();
|
debouncedIncr();
|
||||||
equal(counter, 1, "incr was called immediately");
|
assert.strictEqual(counter, 1, 'incr was called immediately');
|
||||||
_.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 96);
|
_.delay(function(){ assert.strictEqual(counter, 1, 'incr was debounced'); done(); }, 96);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("once", function() {
|
QUnit.test('debounce after system time is set backwards', function(assert) {
|
||||||
|
assert.expect(2);
|
||||||
|
var done = assert.async();
|
||||||
|
var counter = 0;
|
||||||
|
var origNowFunc = _.now;
|
||||||
|
var debouncedIncr = _.debounce(function(){
|
||||||
|
counter++;
|
||||||
|
}, 100, true);
|
||||||
|
|
||||||
|
debouncedIncr();
|
||||||
|
assert.strictEqual(counter, 1, 'incr was called immediately');
|
||||||
|
|
||||||
|
_.now = function() {
|
||||||
|
return new Date(2013, 0, 1, 1, 1, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
_.delay(function() {
|
||||||
|
debouncedIncr();
|
||||||
|
assert.strictEqual(counter, 2, 'incr was debounced successfully');
|
||||||
|
done();
|
||||||
|
_.now = origNowFunc;
|
||||||
|
}, 200);
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('debounce re-entrant', function(assert) {
|
||||||
|
assert.expect(2);
|
||||||
|
var done = assert.async();
|
||||||
|
var sequence = [
|
||||||
|
['b1', 'b2']
|
||||||
|
];
|
||||||
|
var value = '';
|
||||||
|
var debouncedAppend;
|
||||||
|
var append = function(arg){
|
||||||
|
value += this + arg;
|
||||||
|
var args = sequence.pop();
|
||||||
|
if (args) {
|
||||||
|
debouncedAppend.call(args[0], args[1]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
debouncedAppend = _.debounce(append, 32);
|
||||||
|
debouncedAppend.call('a1', 'a2');
|
||||||
|
assert.strictEqual(value, '');
|
||||||
|
_.delay(function(){
|
||||||
|
assert.strictEqual(value, 'a1a2b1b2', 'append was debounced successfully');
|
||||||
|
done();
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('once', function(assert) {
|
||||||
var num = 0;
|
var num = 0;
|
||||||
var increment = _.once(function(){ num++; });
|
var increment = _.once(function(){ return ++num; });
|
||||||
increment();
|
increment();
|
||||||
increment();
|
increment();
|
||||||
equal(num, 1);
|
assert.strictEqual(num, 1);
|
||||||
|
|
||||||
|
assert.strictEqual(increment(), 1, 'stores a memo to the last value');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Recursive onced function.", 1, function() {
|
QUnit.test('Recursive onced function.', function(assert) {
|
||||||
|
assert.expect(1);
|
||||||
var f = _.once(function(){
|
var f = _.once(function(){
|
||||||
ok(true);
|
assert.ok(true);
|
||||||
f();
|
f();
|
||||||
});
|
});
|
||||||
f();
|
f();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("wrap", function() {
|
QUnit.test('wrap', function(assert) {
|
||||||
var greet = function(name){ return "hi: " + name; };
|
var greet = function(name){ return 'hi: ' + name; };
|
||||||
var backwards = _.wrap(greet, function(func, name){ return func(name) + ' ' + name.split('').reverse().join(''); });
|
var backwards = _.wrap(greet, function(func, name){ return func(name) + ' ' + name.split('').reverse().join(''); });
|
||||||
equal(backwards('moe'), 'hi: moe eom', 'wrapped the salutation function');
|
assert.strictEqual(backwards('moe'), 'hi: moe eom', 'wrapped the salutation function');
|
||||||
|
|
||||||
var inner = function(){ return "Hello "; };
|
var inner = function(){ return 'Hello '; };
|
||||||
var obj = {name : "Moe"};
|
var obj = {name: 'Moe'};
|
||||||
obj.hi = _.wrap(inner, function(fn){ return fn() + this.name; });
|
obj.hi = _.wrap(inner, function(fn){ return fn() + this.name; });
|
||||||
equal(obj.hi(), "Hello Moe");
|
assert.strictEqual(obj.hi(), 'Hello Moe');
|
||||||
|
|
||||||
var noop = function(){};
|
var noop = function(){};
|
||||||
var wrapped = _.wrap(noop, function(fn){ return Array.prototype.slice.call(arguments, 0); });
|
var wrapped = _.wrap(noop, function(){ return Array.prototype.slice.call(arguments, 0); });
|
||||||
var ret = wrapped(['whats', 'your'], 'vector', 'victor');
|
var ret = wrapped(['whats', 'your'], 'vector', 'victor');
|
||||||
deepEqual(ret, [noop, ['whats', 'your'], 'vector', 'victor']);
|
assert.deepEqual(ret, [noop, ['whats', 'your'], 'vector', 'victor']);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("compose", function() {
|
QUnit.test('negate', function(assert) {
|
||||||
var greet = function(name){ return "hi: " + name; };
|
var isOdd = function(n){ return n & 1; };
|
||||||
|
assert.strictEqual(_.negate(isOdd)(2), true, 'should return the complement of the given function');
|
||||||
|
assert.strictEqual(_.negate(isOdd)(3), false, 'should return the complement of the given function');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('compose', function(assert) {
|
||||||
|
var greet = function(name){ return 'hi: ' + name; };
|
||||||
var exclaim = function(sentence){ return sentence + '!'; };
|
var exclaim = function(sentence){ return sentence + '!'; };
|
||||||
var composed = _.compose(exclaim, greet);
|
var composed = _.compose(exclaim, greet);
|
||||||
equal(composed('moe'), 'hi: moe!', 'can compose a function that takes another');
|
assert.strictEqual(composed('moe'), 'hi: moe!', 'can compose a function that takes another');
|
||||||
|
|
||||||
composed = _.compose(greet, exclaim);
|
composed = _.compose(greet, exclaim);
|
||||||
equal(composed('moe'), 'hi: moe!', 'in this case, the functions are also commutative');
|
assert.strictEqual(composed('moe'), 'hi: moe!', 'in this case, the functions are also commutative');
|
||||||
|
|
||||||
|
// f(g(h(x, y, z)))
|
||||||
|
function h(x, y, z) {
|
||||||
|
assert.strictEqual(arguments.length, 3, 'First function called with multiple args');
|
||||||
|
return z * y;
|
||||||
|
}
|
||||||
|
function g(x) {
|
||||||
|
assert.strictEqual(arguments.length, 1, 'Composed function is called with 1 argument');
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
function f(x) {
|
||||||
|
assert.strictEqual(arguments.length, 1, 'Composed function is called with 1 argument');
|
||||||
|
return x * 2;
|
||||||
|
}
|
||||||
|
composed = _.compose(f, g, h);
|
||||||
|
assert.strictEqual(composed(1, 2, 3), 12);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("after", function() {
|
QUnit.test('after', function(assert) {
|
||||||
var testAfter = function(afterAmount, timesCalled) {
|
var testAfter = function(afterAmount, timesCalled) {
|
||||||
var afterCalled = 0;
|
var afterCalled = 0;
|
||||||
var after = _.after(afterAmount, function() {
|
var after = _.after(afterAmount, function() {
|
||||||
|
@ -356,10 +657,114 @@ $(document).ready(function() {
|
||||||
return afterCalled;
|
return afterCalled;
|
||||||
};
|
};
|
||||||
|
|
||||||
equal(testAfter(5, 5), 1, "after(N) should fire after being called N times");
|
assert.strictEqual(testAfter(5, 5), 1, 'after(N) should fire after being called N times');
|
||||||
equal(testAfter(5, 4), 0, "after(N) should not fire unless called N times");
|
assert.strictEqual(testAfter(5, 4), 0, 'after(N) should not fire unless called N times');
|
||||||
equal(testAfter(0, 0), 0, "after(0) should not fire immediately");
|
assert.strictEqual(testAfter(0, 0), 0, 'after(0) should not fire immediately');
|
||||||
equal(testAfter(0, 1), 1, "after(0) should fire when first invoked");
|
assert.strictEqual(testAfter(0, 1), 1, 'after(0) should fire when first invoked');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
QUnit.test('before', function(assert) {
|
||||||
|
var testBefore = function(beforeAmount, timesCalled) {
|
||||||
|
var beforeCalled = 0;
|
||||||
|
var before = _.before(beforeAmount, function() { beforeCalled++; });
|
||||||
|
while (timesCalled--) before();
|
||||||
|
return beforeCalled;
|
||||||
|
};
|
||||||
|
|
||||||
|
assert.strictEqual(testBefore(5, 5), 4, 'before(N) should not fire after being called N times');
|
||||||
|
assert.strictEqual(testBefore(5, 4), 4, 'before(N) should fire before being called N times');
|
||||||
|
assert.strictEqual(testBefore(0, 0), 0, 'before(0) should not fire immediately');
|
||||||
|
assert.strictEqual(testBefore(0, 1), 0, 'before(0) should not fire when first invoked');
|
||||||
|
|
||||||
|
var context = {num: 0};
|
||||||
|
var increment = _.before(3, function(){ return ++this.num; });
|
||||||
|
_.times(10, increment, context);
|
||||||
|
assert.strictEqual(increment(), 2, 'stores a memo to the last value');
|
||||||
|
assert.strictEqual(context.num, 2, 'provides context');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('iteratee', function(assert) {
|
||||||
|
var identity = _.iteratee();
|
||||||
|
assert.strictEqual(identity, _.identity, '_.iteratee is exposed as an external function.');
|
||||||
|
|
||||||
|
function fn() {
|
||||||
|
return arguments;
|
||||||
|
}
|
||||||
|
_.each([_.iteratee(fn), _.iteratee(fn, {})], function(cb) {
|
||||||
|
assert.strictEqual(cb().length, 0);
|
||||||
|
assert.deepEqual(_.toArray(cb(1, 2, 3)), _.range(1, 4));
|
||||||
|
assert.deepEqual(_.toArray(cb(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)), _.range(1, 11));
|
||||||
|
});
|
||||||
|
|
||||||
|
var deepProperty = _.iteratee(['a', 'b']);
|
||||||
|
assert.strictEqual(deepProperty({a: {b: 2}}), 2, 'treats an array as a deep property accessor');
|
||||||
|
|
||||||
|
// Test custom iteratee
|
||||||
|
var builtinIteratee = _.iteratee;
|
||||||
|
_.iteratee = function(value) {
|
||||||
|
// RegEx values return a function that returns the number of matches
|
||||||
|
if (_.isRegExp(value)) return function(obj) {
|
||||||
|
return (obj.match(value) || []).length;
|
||||||
|
};
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
var collection = ['foo', 'bar', 'bbiz'];
|
||||||
|
|
||||||
|
// Test all methods that claim to be transformed through `_.iteratee`
|
||||||
|
assert.deepEqual(_.countBy(collection, /b/g), {0: 1, 1: 1, 2: 1});
|
||||||
|
assert.strictEqual(_.every(collection, /b/g), false);
|
||||||
|
assert.deepEqual(_.filter(collection, /b/g), ['bar', 'bbiz']);
|
||||||
|
assert.strictEqual(_.find(collection, /b/g), 'bar');
|
||||||
|
assert.strictEqual(_.findIndex(collection, /b/g), 1);
|
||||||
|
assert.strictEqual(_.findKey(collection, /b/g), '1');
|
||||||
|
assert.strictEqual(_.findLastIndex(collection, /b/g), 2);
|
||||||
|
assert.deepEqual(_.groupBy(collection, /b/g), {0: ['foo'], 1: ['bar'], 2: ['bbiz']});
|
||||||
|
assert.deepEqual(_.indexBy(collection, /b/g), {0: 'foo', 1: 'bar', 2: 'bbiz'});
|
||||||
|
assert.deepEqual(_.map(collection, /b/g), [0, 1, 2]);
|
||||||
|
assert.strictEqual(_.max(collection, /b/g), 'bbiz');
|
||||||
|
assert.strictEqual(_.min(collection, /b/g), 'foo');
|
||||||
|
assert.deepEqual(_.partition(collection, /b/g), [['bar', 'bbiz'], ['foo']]);
|
||||||
|
assert.deepEqual(_.reject(collection, /b/g), ['foo']);
|
||||||
|
assert.strictEqual(_.some(collection, /b/g), true);
|
||||||
|
assert.deepEqual(_.sortBy(collection, /b/g), ['foo', 'bar', 'bbiz']);
|
||||||
|
assert.strictEqual(_.sortedIndex(collection, 'blah', /b/g), 1);
|
||||||
|
assert.deepEqual(_.uniq(collection, /b/g), ['foo', 'bar', 'bbiz']);
|
||||||
|
|
||||||
|
var objCollection = {a: 'foo', b: 'bar', c: 'bbiz'};
|
||||||
|
assert.deepEqual(_.mapObject(objCollection, /b/g), {a: 0, b: 1, c: 2});
|
||||||
|
|
||||||
|
// Restore the builtin iteratee
|
||||||
|
_.iteratee = builtinIteratee;
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('restArgs', function(assert) {
|
||||||
|
assert.expect(10);
|
||||||
|
_.restArgs(function(a, args) {
|
||||||
|
assert.strictEqual(a, 1);
|
||||||
|
assert.deepEqual(args, [2, 3], 'collects rest arguments into an array');
|
||||||
|
})(1, 2, 3);
|
||||||
|
|
||||||
|
_.restArgs(function(a, args) {
|
||||||
|
assert.strictEqual(a, void 0);
|
||||||
|
assert.deepEqual(args, [], 'passes empty array if there are not enough arguments');
|
||||||
|
})();
|
||||||
|
|
||||||
|
_.restArgs(function(a, b, c, args) {
|
||||||
|
assert.strictEqual(arguments.length, 4);
|
||||||
|
assert.deepEqual(args, [4, 5], 'works on functions with many named parameters');
|
||||||
|
})(1, 2, 3, 4, 5);
|
||||||
|
|
||||||
|
var obj = {};
|
||||||
|
_.restArgs(function() {
|
||||||
|
assert.strictEqual(this, obj, 'invokes function with this context');
|
||||||
|
}).call(obj);
|
||||||
|
|
||||||
|
_.restArgs(function(array, iteratee, context) {
|
||||||
|
assert.deepEqual(array, [1, 2, 3, 4], 'startIndex can be used manually specify index of rest parameter');
|
||||||
|
assert.strictEqual(iteratee, void 0);
|
||||||
|
assert.strictEqual(context, void 0);
|
||||||
|
}, 0)(1, 2, 3, 4);
|
||||||
|
});
|
||||||
|
|
||||||
|
}());
|
||||||
|
|
37
vendor/underscore/test/index.html
vendored
37
vendor/underscore/test/index.html
vendored
|
@ -3,42 +3,21 @@
|
||||||
<head>
|
<head>
|
||||||
<title>Underscore Test Suite</title>
|
<title>Underscore Test Suite</title>
|
||||||
<link rel="stylesheet" href="vendor/qunit.css" type="text/css" media="screen">
|
<link rel="stylesheet" href="vendor/qunit.css" type="text/css" media="screen">
|
||||||
<script src="vendor/jquery.js"></script>
|
<link rel="icon" href="../favicon.ico">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="qunit"></div>
|
||||||
|
<div id="exports" style="display: none"></div>
|
||||||
<script src="vendor/qunit.js"></script>
|
<script src="vendor/qunit.js"></script>
|
||||||
<script src="vendor/jslitmus.js"></script>
|
<script src="vendor/qunit-extras.js"></script>
|
||||||
<script src="../underscore.js"></script>
|
<script src="../underscore.js"></script>
|
||||||
|
<script src="qunit-setup.js"></script>
|
||||||
<script src="collections.js"></script>
|
<script src="collections.js"></script>
|
||||||
<script src="arrays.js"></script>
|
<script src="arrays.js"></script>
|
||||||
<script src="functions.js"></script>
|
<script src="functions.js"></script>
|
||||||
<script src="objects.js"></script>
|
<script src="objects.js"></script>
|
||||||
|
<script src="cross-document.js"></script>
|
||||||
<script src="utility.js"></script>
|
<script src="utility.js"></script>
|
||||||
<script src="chaining.js"></script>
|
<script src="chaining.js"></script>
|
||||||
<script src="speed.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="qunit"></div>
|
|
||||||
<div id="qunit-fixture">
|
|
||||||
<div id="map-test">
|
|
||||||
<div id="id1"></div>
|
|
||||||
<div id="id2"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<h1 class="qunit-header">Underscore Speed Suite</h1>
|
|
||||||
<p>
|
|
||||||
A representative sample of the functions are benchmarked here, to provide
|
|
||||||
a sense of how fast they might run in different browsers.
|
|
||||||
Each iteration runs on an array of 1000 elements.<br /><br />
|
|
||||||
For example, the 'intersection' test measures the number of times you can
|
|
||||||
find the intersection of two thousand-element arrays in one second.
|
|
||||||
</p>
|
|
||||||
<br>
|
|
||||||
<script type="text/html" id="template">
|
|
||||||
<%
|
|
||||||
// a comment
|
|
||||||
if (data) { data += 12345; }; %>
|
|
||||||
<li><%= data %></li>
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
1357
vendor/underscore/test/objects.js
vendored
1357
vendor/underscore/test/objects.js
vendored
File diff suppressed because it is too large
Load diff
3
vendor/underscore/test/qunit-setup.js
vendored
Normal file
3
vendor/underscore/test/qunit-setup.js
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
(function() {
|
||||||
|
QUnit.config.noglobals = true;
|
||||||
|
}());
|
452
vendor/underscore/test/utility.js
vendored
452
vendor/underscore/test/utility.js
vendored
|
@ -1,272 +1,452 @@
|
||||||
$(document).ready(function() {
|
(function() {
|
||||||
|
var _ = typeof require == 'function' ? require('..') : window._;
|
||||||
var templateSettings;
|
var templateSettings;
|
||||||
|
|
||||||
module("Utility", {
|
QUnit.module('Utility', {
|
||||||
|
|
||||||
setup: function() {
|
beforeEach: function() {
|
||||||
templateSettings = _.clone(_.templateSettings);
|
templateSettings = _.clone(_.templateSettings);
|
||||||
},
|
},
|
||||||
|
|
||||||
teardown: function() {
|
afterEach: function() {
|
||||||
_.templateSettings = templateSettings;
|
_.templateSettings = templateSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("#750 - Return _ instance.", 2, function() {
|
if (typeof this == 'object') {
|
||||||
|
QUnit.test('noConflict', function(assert) {
|
||||||
|
var underscore = _.noConflict();
|
||||||
|
assert.strictEqual(underscore.identity(1), 1);
|
||||||
|
if (typeof require != 'function') {
|
||||||
|
assert.strictEqual(this._, void 0, 'global underscore is removed');
|
||||||
|
this._ = underscore;
|
||||||
|
} else if (typeof global !== 'undefined') {
|
||||||
|
delete global._;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof require == 'function') {
|
||||||
|
QUnit.test('noConflict (node vm)', function(assert) {
|
||||||
|
assert.expect(2);
|
||||||
|
var done = assert.async();
|
||||||
|
var fs = require('fs');
|
||||||
|
var vm = require('vm');
|
||||||
|
var filename = __dirname + '/../underscore.js';
|
||||||
|
fs.readFile(filename, function(err, content){
|
||||||
|
var sandbox = vm.createScript(
|
||||||
|
content + 'this.underscore = this._.noConflict();',
|
||||||
|
filename
|
||||||
|
);
|
||||||
|
var context = {_: 'oldvalue'};
|
||||||
|
sandbox.runInNewContext(context);
|
||||||
|
assert.strictEqual(context._, 'oldvalue');
|
||||||
|
assert.strictEqual(context.underscore.VERSION, _.VERSION);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QUnit.test('#750 - Return _ instance.', function(assert) {
|
||||||
|
assert.expect(2);
|
||||||
var instance = _([]);
|
var instance = _([]);
|
||||||
ok(_(instance) === instance);
|
assert.strictEqual(_(instance), instance);
|
||||||
ok(new _(instance) === instance);
|
assert.strictEqual(new _(instance), instance);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("identity", function() {
|
QUnit.test('identity', function(assert) {
|
||||||
var moe = {name : 'moe'};
|
var stooge = {name: 'moe'};
|
||||||
equal(_.identity(moe), moe, 'moe is the same as his identity');
|
assert.strictEqual(_.identity(stooge), stooge, 'stooge is the same as his identity');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("random", function() {
|
QUnit.test('constant', function(assert) {
|
||||||
|
var stooge = {name: 'moe'};
|
||||||
|
assert.strictEqual(_.constant(stooge)(), stooge, 'should create a function that returns stooge');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('noop', function(assert) {
|
||||||
|
assert.strictEqual(_.noop('curly', 'larry', 'moe'), void 0, 'should always return undefined');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('random', function(assert) {
|
||||||
var array = _.range(1000);
|
var array = _.range(1000);
|
||||||
var min = Math.pow(2, 31);
|
var min = Math.pow(2, 31);
|
||||||
var max = Math.pow(2, 62);
|
var max = Math.pow(2, 62);
|
||||||
|
|
||||||
ok(_.every(array, function() {
|
assert.ok(_.every(array, function() {
|
||||||
return _.random(min, max) >= min;
|
return _.random(min, max) >= min;
|
||||||
}), "should produce a random number greater than or equal to the minimum number");
|
}), 'should produce a random number greater than or equal to the minimum number');
|
||||||
|
|
||||||
ok(_.some(array, function() {
|
assert.ok(_.some(array, function() {
|
||||||
return _.random(Number.MAX_VALUE) > 0;
|
return _.random(Number.MAX_VALUE) > 0;
|
||||||
}), "should produce a random number when passed `Number.MAX_VALUE`");
|
}), 'should produce a random number when passed `Number.MAX_VALUE`');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("uniqueId", function() {
|
QUnit.test('now', function(assert) {
|
||||||
|
var diff = _.now() - new Date().getTime();
|
||||||
|
assert.ok(diff <= 0 && diff > -5, 'Produces the correct time in milliseconds');//within 5ms
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('uniqueId', function(assert) {
|
||||||
var ids = [], i = 0;
|
var ids = [], i = 0;
|
||||||
while(i++ < 100) ids.push(_.uniqueId());
|
while (i++ < 100) ids.push(_.uniqueId());
|
||||||
equal(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids');
|
assert.strictEqual(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("times", function() {
|
QUnit.test('times', function(assert) {
|
||||||
var vals = [];
|
var vals = [];
|
||||||
_.times(3, function (i) { vals.push(i); });
|
_.times(3, function(i) { vals.push(i); });
|
||||||
ok(_.isEqual(vals, [0,1,2]), "is 0 indexed");
|
assert.deepEqual(vals, [0, 1, 2], 'is 0 indexed');
|
||||||
//
|
//
|
||||||
vals = [];
|
vals = [];
|
||||||
_(3).times(function(i) { vals.push(i); });
|
_(3).times(function(i) { vals.push(i); });
|
||||||
ok(_.isEqual(vals, [0,1,2]), "works as a wrapper");
|
assert.deepEqual(vals, [0, 1, 2], 'works as a wrapper');
|
||||||
// collects return values
|
// collects return values
|
||||||
ok(_.isEqual([0, 1, 2], _.times(3, function(i) { return i; })), "collects return values");
|
assert.deepEqual([0, 1, 2], _.times(3, function(i) { return i; }), 'collects return values');
|
||||||
|
|
||||||
deepEqual(_.times(0, _.identity), []);
|
assert.deepEqual(_.times(0, _.identity), []);
|
||||||
deepEqual(_.times(-1, _.identity), []);
|
assert.deepEqual(_.times(-1, _.identity), []);
|
||||||
deepEqual(_.times(parseFloat('-Infinity'), _.identity), []);
|
assert.deepEqual(_.times(parseFloat('-Infinity'), _.identity), []);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("mixin", function() {
|
QUnit.test('mixin', function(assert) {
|
||||||
_.mixin({
|
var ret = _.mixin({
|
||||||
myReverse: function(string) {
|
myReverse: function(string) {
|
||||||
return string.split('').reverse().join('');
|
return string.split('').reverse().join('');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
equal(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _');
|
assert.strictEqual(ret, _, 'returns the _ object to facilitate chaining');
|
||||||
equal(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper');
|
assert.strictEqual(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _');
|
||||||
|
assert.strictEqual(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("_.escape", function() {
|
QUnit.test('_.escape', function(assert) {
|
||||||
equal(_.escape("Curly & Moe"), "Curly & Moe");
|
assert.strictEqual(_.escape(null), '');
|
||||||
equal(_.escape('<a href="http://moe.com">Curly & Moe\'s</a>'), '<a href="http://moe.com">Curly & Moe's</a>');
|
|
||||||
equal(_.escape("Curly & Moe"), "Curly &amp; Moe");
|
|
||||||
equal(_.escape(null), '');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("_.unescape", function() {
|
QUnit.test('_.unescape', function(assert) {
|
||||||
var string = "Curly & Moe";
|
var string = 'Curly & Moe';
|
||||||
equal(_.unescape("Curly & Moe"), string);
|
assert.strictEqual(_.unescape(null), '');
|
||||||
equal(_.unescape('<a href="http://moe.com">Curly & Moe's</a>'), '<a href="http://moe.com">Curly & Moe\'s</a>');
|
assert.strictEqual(_.unescape(_.escape(string)), string);
|
||||||
equal(_.unescape("Curly &amp; Moe"), "Curly & Moe");
|
assert.strictEqual(_.unescape(string), string, 'don\'t unescape unnecessarily');
|
||||||
equal(_.unescape(null), '');
|
|
||||||
equal(_.unescape(_.escape(string)), string);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("template", function() {
|
// Don't care what they escape them to just that they're escaped and can be unescaped
|
||||||
|
QUnit.test('_.escape & unescape', function(assert) {
|
||||||
|
// test & (&) separately obviously
|
||||||
|
var escapeCharacters = ['<', '>', '"', '\'', '`'];
|
||||||
|
|
||||||
|
_.each(escapeCharacters, function(escapeChar) {
|
||||||
|
var s = 'a ' + escapeChar + ' string escaped';
|
||||||
|
var e = _.escape(s);
|
||||||
|
assert.notEqual(s, e, escapeChar + ' is escaped');
|
||||||
|
assert.strictEqual(s, _.unescape(e), escapeChar + ' can be unescaped');
|
||||||
|
|
||||||
|
s = 'a ' + escapeChar + escapeChar + escapeChar + 'some more string' + escapeChar;
|
||||||
|
e = _.escape(s);
|
||||||
|
|
||||||
|
assert.strictEqual(e.indexOf(escapeChar), -1, 'can escape multiple occurrences of ' + escapeChar);
|
||||||
|
assert.strictEqual(_.unescape(e), s, 'multiple occurrences of ' + escapeChar + ' can be unescaped');
|
||||||
|
});
|
||||||
|
|
||||||
|
// handles multiple escape characters at once
|
||||||
|
var joiner = ' other stuff ';
|
||||||
|
var allEscaped = escapeCharacters.join(joiner);
|
||||||
|
allEscaped += allEscaped;
|
||||||
|
assert.ok(_.every(escapeCharacters, function(escapeChar) {
|
||||||
|
return allEscaped.indexOf(escapeChar) !== -1;
|
||||||
|
}), 'handles multiple characters');
|
||||||
|
assert.ok(allEscaped.indexOf(joiner) >= 0, 'can escape multiple escape characters at the same time');
|
||||||
|
|
||||||
|
// test & -> &
|
||||||
|
var str = 'some string & another string & yet another';
|
||||||
|
var escaped = _.escape(str);
|
||||||
|
|
||||||
|
assert.notStrictEqual(escaped.indexOf('&'), -1, 'handles & aka &');
|
||||||
|
assert.strictEqual(_.unescape(str), str, 'can unescape &');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('template', function(assert) {
|
||||||
var basicTemplate = _.template("<%= thing %> is gettin' on my noives!");
|
var basicTemplate = _.template("<%= thing %> is gettin' on my noives!");
|
||||||
var result = basicTemplate({thing : 'This'});
|
var result = basicTemplate({thing: 'This'});
|
||||||
equal(result, "This is gettin' on my noives!", 'can do basic attribute interpolation');
|
assert.strictEqual(result, "This is gettin' on my noives!", 'can do basic attribute interpolation');
|
||||||
|
|
||||||
var sansSemicolonTemplate = _.template("A <% this %> B");
|
var sansSemicolonTemplate = _.template('A <% this %> B');
|
||||||
equal(sansSemicolonTemplate(), "A B");
|
assert.strictEqual(sansSemicolonTemplate(), 'A B');
|
||||||
|
|
||||||
var backslashTemplate = _.template("<%= thing %> is \\ridanculous");
|
var backslashTemplate = _.template('<%= thing %> is \\ridanculous');
|
||||||
equal(backslashTemplate({thing: 'This'}), "This is \\ridanculous");
|
assert.strictEqual(backslashTemplate({thing: 'This'}), 'This is \\ridanculous');
|
||||||
|
|
||||||
var escapeTemplate = _.template('<%= a ? "checked=\\"checked\\"" : "" %>');
|
var escapeTemplate = _.template('<%= a ? "checked=\\"checked\\"" : "" %>');
|
||||||
equal(escapeTemplate({a: true}), 'checked="checked"', 'can handle slash escapes in interpolations.');
|
assert.strictEqual(escapeTemplate({a: true}), 'checked="checked"', 'can handle slash escapes in interpolations.');
|
||||||
|
|
||||||
var fancyTemplate = _.template("<ul><% \
|
var fancyTemplate = _.template('<ul><% ' +
|
||||||
for (var key in people) { \
|
' for (var key in people) { ' +
|
||||||
%><li><%= people[key] %></li><% } %></ul>");
|
'%><li><%= people[key] %></li><% } %></ul>');
|
||||||
result = fancyTemplate({people : {moe : "Moe", larry : "Larry", curly : "Curly"}});
|
result = fancyTemplate({people: {moe: 'Moe', larry: 'Larry', curly: 'Curly'}});
|
||||||
equal(result, "<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>", 'can run arbitrary javascript in templates');
|
assert.strictEqual(result, '<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>', 'can run arbitrary javascript in templates');
|
||||||
|
|
||||||
var escapedCharsInJavascriptTemplate = _.template("<ul><% _.each(numbers.split('\\n'), function(item) { %><li><%= item %></li><% }) %></ul>");
|
var escapedCharsInJavaScriptTemplate = _.template('<ul><% _.each(numbers.split("\\n"), function(item) { %><li><%= item %></li><% }) %></ul>');
|
||||||
result = escapedCharsInJavascriptTemplate({numbers: "one\ntwo\nthree\nfour"});
|
result = escapedCharsInJavaScriptTemplate({numbers: 'one\ntwo\nthree\nfour'});
|
||||||
equal(result, "<ul><li>one</li><li>two</li><li>three</li><li>four</li></ul>", 'Can use escaped characters (e.g. \\n) in Javascript');
|
assert.strictEqual(result, '<ul><li>one</li><li>two</li><li>three</li><li>four</li></ul>', 'Can use escaped characters (e.g. \\n) in JavaScript');
|
||||||
|
|
||||||
var namespaceCollisionTemplate = _.template("<%= pageCount %> <%= thumbnails[pageCount] %> <% _.each(thumbnails, function(p) { %><div class=\"thumbnail\" rel=\"<%= p %>\"></div><% }); %>");
|
var namespaceCollisionTemplate = _.template('<%= pageCount %> <%= thumbnails[pageCount] %> <% _.each(thumbnails, function(p) { %><div class="thumbnail" rel="<%= p %>"></div><% }); %>');
|
||||||
result = namespaceCollisionTemplate({
|
result = namespaceCollisionTemplate({
|
||||||
pageCount: 3,
|
pageCount: 3,
|
||||||
thumbnails: {
|
thumbnails: {
|
||||||
1: "p1-thumbnail.gif",
|
1: 'p1-thumbnail.gif',
|
||||||
2: "p2-thumbnail.gif",
|
2: 'p2-thumbnail.gif',
|
||||||
3: "p3-thumbnail.gif"
|
3: 'p3-thumbnail.gif'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
equal(result, "3 p3-thumbnail.gif <div class=\"thumbnail\" rel=\"p1-thumbnail.gif\"></div><div class=\"thumbnail\" rel=\"p2-thumbnail.gif\"></div><div class=\"thumbnail\" rel=\"p3-thumbnail.gif\"></div>");
|
assert.strictEqual(result, '3 p3-thumbnail.gif <div class="thumbnail" rel="p1-thumbnail.gif"></div><div class="thumbnail" rel="p2-thumbnail.gif"></div><div class="thumbnail" rel="p3-thumbnail.gif"></div>');
|
||||||
|
|
||||||
var noInterpolateTemplate = _.template("<div><p>Just some text. Hey, I know this is silly but it aids consistency.</p></div>");
|
var noInterpolateTemplate = _.template('<div><p>Just some text. Hey, I know this is silly but it aids consistency.</p></div>');
|
||||||
result = noInterpolateTemplate();
|
result = noInterpolateTemplate();
|
||||||
equal(result, "<div><p>Just some text. Hey, I know this is silly but it aids consistency.</p></div>");
|
assert.strictEqual(result, '<div><p>Just some text. Hey, I know this is silly but it aids consistency.</p></div>');
|
||||||
|
|
||||||
var quoteTemplate = _.template("It's its, not it's");
|
var quoteTemplate = _.template("It's its, not it's");
|
||||||
equal(quoteTemplate({}), "It's its, not it's");
|
assert.strictEqual(quoteTemplate({}), "It's its, not it's");
|
||||||
|
|
||||||
var quoteInStatementAndBody = _.template("<%\
|
var quoteInStatementAndBody = _.template('<% ' +
|
||||||
if(foo == 'bar'){ \
|
" if(foo == 'bar'){ " +
|
||||||
%>Statement quotes and 'quotes'.<% } %>");
|
"%>Statement quotes and 'quotes'.<% } %>");
|
||||||
equal(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'.");
|
assert.strictEqual(quoteInStatementAndBody({foo: 'bar'}), "Statement quotes and 'quotes'.");
|
||||||
|
|
||||||
var withNewlinesAndTabs = _.template('This\n\t\tis: <%= x %>.\n\tok.\nend.');
|
var withNewlinesAndTabs = _.template('This\n\t\tis: <%= x %>.\n\tok.\nend.');
|
||||||
equal(withNewlinesAndTabs({x: 'that'}), 'This\n\t\tis: that.\n\tok.\nend.');
|
assert.strictEqual(withNewlinesAndTabs({x: 'that'}), 'This\n\t\tis: that.\n\tok.\nend.');
|
||||||
|
|
||||||
var template = _.template("<i><%- value %></i>");
|
var template = _.template('<i><%- value %></i>');
|
||||||
var result = template({value: "<script>"});
|
result = template({value: '<script>'});
|
||||||
equal(result, '<i><script></i>');
|
assert.strictEqual(result, '<i><script></i>');
|
||||||
|
|
||||||
var stooge = {
|
var stooge = {
|
||||||
name: "Moe",
|
name: 'Moe',
|
||||||
template: _.template("I'm <%= this.name %>")
|
template: _.template("I'm <%= this.name %>")
|
||||||
};
|
};
|
||||||
equal(stooge.template(), "I'm Moe");
|
assert.strictEqual(stooge.template(), "I'm Moe");
|
||||||
|
|
||||||
if (!$.browser.msie) {
|
template = _.template('\n ' +
|
||||||
var fromHTML = _.template($('#template').html());
|
' <%\n ' +
|
||||||
equal(fromHTML({data : 12345}).replace(/\s/g, ''), '<li>24690</li>');
|
' // a comment\n ' +
|
||||||
}
|
' if (data) { data += 12345; }; %>\n ' +
|
||||||
|
' <li><%= data %></li>\n '
|
||||||
|
);
|
||||||
|
assert.strictEqual(template({data: 12345}).replace(/\s/g, ''), '<li>24690</li>');
|
||||||
|
|
||||||
_.templateSettings = {
|
_.templateSettings = {
|
||||||
evaluate : /\{\{([\s\S]+?)\}\}/g,
|
evaluate: /\{\{([\s\S]+?)\}\}/g,
|
||||||
interpolate : /\{\{=([\s\S]+?)\}\}/g
|
interpolate: /\{\{=([\s\S]+?)\}\}/g
|
||||||
};
|
};
|
||||||
|
|
||||||
var custom = _.template("<ul>{{ for (var key in people) { }}<li>{{= people[key] }}</li>{{ } }}</ul>");
|
var custom = _.template('<ul>{{ for (var key in people) { }}<li>{{= people[key] }}</li>{{ } }}</ul>');
|
||||||
result = custom({people : {moe : "Moe", larry : "Larry", curly : "Curly"}});
|
result = custom({people: {moe: 'Moe', larry: 'Larry', curly: 'Curly'}});
|
||||||
equal(result, "<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>", 'can run arbitrary javascript in templates');
|
assert.strictEqual(result, '<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>', 'can run arbitrary javascript in templates');
|
||||||
|
|
||||||
var customQuote = _.template("It's its, not it's");
|
var customQuote = _.template("It's its, not it's");
|
||||||
equal(customQuote({}), "It's its, not it's");
|
assert.strictEqual(customQuote({}), "It's its, not it's");
|
||||||
|
|
||||||
var quoteInStatementAndBody = _.template("{{ if(foo == 'bar'){ }}Statement quotes and 'quotes'.{{ } }}");
|
quoteInStatementAndBody = _.template("{{ if(foo == 'bar'){ }}Statement quotes and 'quotes'.{{ } }}");
|
||||||
equal(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'.");
|
assert.strictEqual(quoteInStatementAndBody({foo: 'bar'}), "Statement quotes and 'quotes'.");
|
||||||
|
|
||||||
_.templateSettings = {
|
_.templateSettings = {
|
||||||
evaluate : /<\?([\s\S]+?)\?>/g,
|
evaluate: /<\?([\s\S]+?)\?>/g,
|
||||||
interpolate : /<\?=([\s\S]+?)\?>/g
|
interpolate: /<\?=([\s\S]+?)\?>/g
|
||||||
};
|
};
|
||||||
|
|
||||||
var customWithSpecialChars = _.template("<ul><? for (var key in people) { ?><li><?= people[key] ?></li><? } ?></ul>");
|
var customWithSpecialChars = _.template('<ul><? for (var key in people) { ?><li><?= people[key] ?></li><? } ?></ul>');
|
||||||
result = customWithSpecialChars({people : {moe : "Moe", larry : "Larry", curly : "Curly"}});
|
result = customWithSpecialChars({people: {moe: 'Moe', larry: 'Larry', curly: 'Curly'}});
|
||||||
equal(result, "<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>", 'can run arbitrary javascript in templates');
|
assert.strictEqual(result, '<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>', 'can run arbitrary javascript in templates');
|
||||||
|
|
||||||
var customWithSpecialCharsQuote = _.template("It's its, not it's");
|
var customWithSpecialCharsQuote = _.template("It's its, not it's");
|
||||||
equal(customWithSpecialCharsQuote({}), "It's its, not it's");
|
assert.strictEqual(customWithSpecialCharsQuote({}), "It's its, not it's");
|
||||||
|
|
||||||
var quoteInStatementAndBody = _.template("<? if(foo == 'bar'){ ?>Statement quotes and 'quotes'.<? } ?>");
|
quoteInStatementAndBody = _.template("<? if(foo == 'bar'){ ?>Statement quotes and 'quotes'.<? } ?>");
|
||||||
equal(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'.");
|
assert.strictEqual(quoteInStatementAndBody({foo: 'bar'}), "Statement quotes and 'quotes'.");
|
||||||
|
|
||||||
_.templateSettings = {
|
_.templateSettings = {
|
||||||
interpolate : /\{\{(.+?)\}\}/g
|
interpolate: /\{\{(.+?)\}\}/g
|
||||||
};
|
};
|
||||||
|
|
||||||
var mustache = _.template("Hello {{planet}}!");
|
var mustache = _.template('Hello {{planet}}!');
|
||||||
equal(mustache({planet : "World"}), "Hello World!", "can mimic mustache.js");
|
assert.strictEqual(mustache({planet: 'World'}), 'Hello World!', 'can mimic mustache.js');
|
||||||
|
|
||||||
var templateWithNull = _.template("a null undefined {{planet}}");
|
var templateWithNull = _.template('a null undefined {{planet}}');
|
||||||
equal(templateWithNull({planet : "world"}), "a null undefined world", "can handle missing escape and evaluate settings");
|
assert.strictEqual(templateWithNull({planet: 'world'}), 'a null undefined world', 'can handle missing escape and evaluate settings');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('_.template provides the generated function source, when a SyntaxError occurs', function() {
|
QUnit.test('_.template provides the generated function source, when a SyntaxError occurs', function(assert) {
|
||||||
|
var source;
|
||||||
try {
|
try {
|
||||||
_.template('<b><%= if x %></b>');
|
_.template('<b><%= if x %></b>');
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
var source = ex.source;
|
source = ex.source;
|
||||||
}
|
}
|
||||||
ok(/__p/.test(source));
|
assert.ok(/__p/.test(source));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('_.template handles \\u2028 & \\u2029', function() {
|
QUnit.test('_.template handles \\u2028 & \\u2029', function(assert) {
|
||||||
var tmpl = _.template('<p>\u2028<%= "\\u2028\\u2029" %>\u2029</p>');
|
var tmpl = _.template('<p>\u2028<%= "\\u2028\\u2029" %>\u2029</p>');
|
||||||
strictEqual(tmpl(), '<p>\u2028\u2028\u2029\u2029</p>');
|
assert.strictEqual(tmpl(), '<p>\u2028\u2028\u2029\u2029</p>');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('result calls functions and returns primitives', function() {
|
QUnit.test('result calls functions and returns primitives', function(assert) {
|
||||||
var obj = {w: '', x: 'x', y: function(){ return this.x; }};
|
var obj = {w: '', x: 'x', y: function(){ return this.x; }};
|
||||||
strictEqual(_.result(obj, 'w'), '');
|
assert.strictEqual(_.result(obj, 'w'), '');
|
||||||
strictEqual(_.result(obj, 'x'), 'x');
|
assert.strictEqual(_.result(obj, 'x'), 'x');
|
||||||
strictEqual(_.result(obj, 'y'), 'x');
|
assert.strictEqual(_.result(obj, 'y'), 'x');
|
||||||
strictEqual(_.result(obj, 'z'), undefined);
|
assert.strictEqual(_.result(obj, 'z'), void 0);
|
||||||
strictEqual(_.result(null, 'x'), undefined);
|
assert.strictEqual(_.result(null, 'x'), void 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('_.templateSettings.variable', function() {
|
QUnit.test('result returns a default value if object is null or undefined', function(assert) {
|
||||||
|
assert.strictEqual(_.result(null, 'b', 'default'), 'default');
|
||||||
|
assert.strictEqual(_.result(void 0, 'c', 'default'), 'default');
|
||||||
|
assert.strictEqual(_.result(''.match('missing'), 1, 'default'), 'default');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('result returns a default value if property of object is missing', function(assert) {
|
||||||
|
assert.strictEqual(_.result({d: null}, 'd', 'default'), null);
|
||||||
|
assert.strictEqual(_.result({e: false}, 'e', 'default'), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('result only returns the default value if the object does not have the property or is undefined', function(assert) {
|
||||||
|
assert.strictEqual(_.result({}, 'b', 'default'), 'default');
|
||||||
|
assert.strictEqual(_.result({d: void 0}, 'd', 'default'), 'default');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('result does not return the default if the property of an object is found in the prototype', function(assert) {
|
||||||
|
var Foo = function(){};
|
||||||
|
Foo.prototype.bar = 1;
|
||||||
|
assert.strictEqual(_.result(new Foo, 'bar', 2), 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('result does use the fallback when the result of invoking the property is undefined', function(assert) {
|
||||||
|
var obj = {a: function() {}};
|
||||||
|
assert.strictEqual(_.result(obj, 'a', 'failed'), void 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('result fallback can use a function', function(assert) {
|
||||||
|
var obj = {a: [1, 2, 3]};
|
||||||
|
assert.strictEqual(_.result(obj, 'b', _.constant(5)), 5);
|
||||||
|
assert.strictEqual(_.result(obj, 'b', function() {
|
||||||
|
return this.a;
|
||||||
|
}), obj.a, 'called with context');
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('result can accept an array of properties for deep access', function(assert) {
|
||||||
|
var func = function() { return 'f'; };
|
||||||
|
var context = function() { return this; };
|
||||||
|
|
||||||
|
assert.strictEqual(_.result({a: 1}, 'a'), 1, 'can get a direct property');
|
||||||
|
assert.strictEqual(_.result({a: {b: 2}}, ['a', 'b']), 2, 'can get a nested property');
|
||||||
|
assert.strictEqual(_.result({a: 1}, 'b', 2), 2, 'uses the fallback value when property is missing');
|
||||||
|
assert.strictEqual(_.result({a: 1}, ['b', 'c'], 2), 2, 'uses the fallback value when any property is missing');
|
||||||
|
assert.strictEqual(_.result({a: void 0}, ['a'], 1), 1, 'uses the fallback when value is undefined');
|
||||||
|
assert.strictEqual(_.result({a: false}, ['a'], 'foo'), false, 'can fetch falsy values');
|
||||||
|
|
||||||
|
assert.strictEqual(_.result({a: func}, 'a'), 'f', 'can get a direct method');
|
||||||
|
assert.strictEqual(_.result({a: {b: func}}, ['a', 'b']), 'f', 'can get a nested method');
|
||||||
|
assert.strictEqual(_.result(), void 0, 'returns undefined if obj is not passed');
|
||||||
|
assert.strictEqual(_.result(void 1, 'a', 2), 2, 'returns default if obj is not passed');
|
||||||
|
assert.strictEqual(_.result(void 1, 'a', func), 'f', 'executes default if obj is not passed');
|
||||||
|
assert.strictEqual(_.result({}, void 0, 2), 2, 'returns default if prop is not passed');
|
||||||
|
assert.strictEqual(_.result({}, void 0, func), 'f', 'executes default if prop is not passed');
|
||||||
|
|
||||||
|
var childObj = {c: context};
|
||||||
|
var obj = {a: context, b: childObj};
|
||||||
|
assert.strictEqual(_.result(obj, 'a'), obj, 'uses the parent object as context');
|
||||||
|
assert.strictEqual(_.result(obj, 'e', context), obj, 'uses the object as context when executing the fallback');
|
||||||
|
assert.strictEqual(_.result(obj, ['a', 'x'], context), obj, 'uses the object as context when executing the fallback');
|
||||||
|
assert.strictEqual(_.result(obj, ['b', 'c']), childObj, 'uses the parent as context when accessing deep methods');
|
||||||
|
|
||||||
|
assert.strictEqual(_.result({}, [], 'a'), 'a', 'returns the default when prop is empty');
|
||||||
|
assert.strictEqual(_.result(obj, [], context), obj, 'uses the object as context when path is empty');
|
||||||
|
|
||||||
|
var nested = {
|
||||||
|
d: function() {
|
||||||
|
return {
|
||||||
|
e: function() {
|
||||||
|
return obj;
|
||||||
|
},
|
||||||
|
f: context
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
assert.strictEqual(_.result(nested, ['d', 'e']), obj, 'can unpack nested function calls');
|
||||||
|
assert.strictEqual(_.result(nested, ['d', 'f']).e(), obj, 'uses parent as context for nested function calls');
|
||||||
|
assert.strictEqual(_.result(nested, ['d', 'x'], context).e(), obj, 'uses last valid child as context for fallback');
|
||||||
|
|
||||||
|
if (typeof Symbol !== 'undefined') {
|
||||||
|
var x = Symbol('x');
|
||||||
|
var symbolObject = {};
|
||||||
|
symbolObject[x] = 'foo';
|
||||||
|
assert.strictEqual(_.result(symbolObject, x), 'foo', 'can use symbols as keys');
|
||||||
|
|
||||||
|
var y = Symbol('y');
|
||||||
|
symbolObject[y] = {};
|
||||||
|
symbolObject[y][x] = 'bar';
|
||||||
|
assert.strictEqual(_.result(symbolObject, [y, x]), 'bar', 'can use symbols as keys for deep matching');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('_.templateSettings.variable', function(assert) {
|
||||||
var s = '<%=data.x%>';
|
var s = '<%=data.x%>';
|
||||||
var data = {x: 'x'};
|
var data = {x: 'x'};
|
||||||
strictEqual(_.template(s, data, {variable: 'data'}), 'x');
|
var tmp = _.template(s, {variable: 'data'});
|
||||||
|
assert.strictEqual(tmp(data), 'x');
|
||||||
_.templateSettings.variable = 'data';
|
_.templateSettings.variable = 'data';
|
||||||
strictEqual(_.template(s)(data), 'x');
|
assert.strictEqual(_.template(s)(data), 'x');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('#547 - _.templateSettings is unchanged by custom settings.', function() {
|
QUnit.test('#547 - _.templateSettings is unchanged by custom settings.', function(assert) {
|
||||||
ok(!_.templateSettings.variable);
|
assert.notOk(_.templateSettings.variable);
|
||||||
_.template('', {}, {variable: 'x'});
|
_.template('', {}, {variable: 'x'});
|
||||||
ok(!_.templateSettings.variable);
|
assert.notOk(_.templateSettings.variable);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('#556 - undefined template variables.', function() {
|
QUnit.test('#556 - undefined template variables.', function(assert) {
|
||||||
var template = _.template('<%=x%>');
|
var template = _.template('<%=x%>');
|
||||||
strictEqual(template({x: null}), '');
|
assert.strictEqual(template({x: null}), '');
|
||||||
strictEqual(template({x: undefined}), '');
|
assert.strictEqual(template({x: void 0}), '');
|
||||||
|
|
||||||
var templateEscaped = _.template('<%-x%>');
|
var templateEscaped = _.template('<%-x%>');
|
||||||
strictEqual(templateEscaped({x: null}), '');
|
assert.strictEqual(templateEscaped({x: null}), '');
|
||||||
strictEqual(templateEscaped({x: undefined}), '');
|
assert.strictEqual(templateEscaped({x: void 0}), '');
|
||||||
|
|
||||||
var templateWithProperty = _.template('<%=x.foo%>');
|
var templateWithProperty = _.template('<%=x.foo%>');
|
||||||
strictEqual(templateWithProperty({x: {} }), '');
|
assert.strictEqual(templateWithProperty({x: {}}), '');
|
||||||
strictEqual(templateWithProperty({x: {} }), '');
|
assert.strictEqual(templateWithProperty({x: {}}), '');
|
||||||
|
|
||||||
var templateWithPropertyEscaped = _.template('<%-x.foo%>');
|
var templateWithPropertyEscaped = _.template('<%-x.foo%>');
|
||||||
strictEqual(templateWithPropertyEscaped({x: {} }), '');
|
assert.strictEqual(templateWithPropertyEscaped({x: {}}), '');
|
||||||
strictEqual(templateWithPropertyEscaped({x: {} }), '');
|
assert.strictEqual(templateWithPropertyEscaped({x: {}}), '');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('interpolate evaluates code only once.', 2, function() {
|
QUnit.test('interpolate evaluates code only once.', function(assert) {
|
||||||
|
assert.expect(2);
|
||||||
var count = 0;
|
var count = 0;
|
||||||
var template = _.template('<%= f() %>');
|
var template = _.template('<%= f() %>');
|
||||||
template({f: function(){ ok(!(count++)); }});
|
template({f: function(){ assert.notOk(count++); }});
|
||||||
|
|
||||||
var countEscaped = 0;
|
var countEscaped = 0;
|
||||||
var templateEscaped = _.template('<%- f() %>');
|
var templateEscaped = _.template('<%- f() %>');
|
||||||
templateEscaped({f: function(){ ok(!(countEscaped++)); }});
|
templateEscaped({f: function(){ assert.notOk(countEscaped++); }});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('#746 - _.template settings are not modified.', 1, function() {
|
QUnit.test('#746 - _.template settings are not modified.', function(assert) {
|
||||||
|
assert.expect(1);
|
||||||
var settings = {};
|
var settings = {};
|
||||||
_.template('', null, settings);
|
_.template('', null, settings);
|
||||||
deepEqual(settings, {});
|
assert.deepEqual(settings, {});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('#779 - delimeters are applied to unescaped text.', 1, function() {
|
QUnit.test('#779 - delimiters are applied to unescaped text.', function(assert) {
|
||||||
|
assert.expect(1);
|
||||||
var template = _.template('<<\nx\n>>', null, {evaluate: /<<(.*?)>>/g});
|
var template = _.template('<<\nx\n>>', null, {evaluate: /<<(.*?)>>/g});
|
||||||
strictEqual(template(), '<<\nx\n>>');
|
assert.strictEqual(template(), '<<\nx\n>>');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
}());
|
||||||
|
|
9404
vendor/underscore/test/vendor/jquery.js
vendored
9404
vendor/underscore/test/vendor/jquery.js
vendored
File diff suppressed because it is too large
Load diff
670
vendor/underscore/test/vendor/jslitmus.js
vendored
670
vendor/underscore/test/vendor/jslitmus.js
vendored
|
@ -1,670 +0,0 @@
|
||||||
// JSLitmus.js
|
|
||||||
//
|
|
||||||
// History:
|
|
||||||
// 2008-10-27: Initial release
|
|
||||||
// 2008-11-09: Account for iteration loop overhead
|
|
||||||
// 2008-11-13: Added OS detection
|
|
||||||
// 2009-02-25: Create tinyURL automatically, shift-click runs tests in reverse
|
|
||||||
//
|
|
||||||
// Copyright (c) 2008-2009, Robert Kieffer
|
|
||||||
// All Rights Reserved
|
|
||||||
//
|
|
||||||
// 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 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 OR COPYRIGHT HOLDERS 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() {
|
|
||||||
// Private methods and state
|
|
||||||
|
|
||||||
// Get platform info but don't go crazy trying to recognize everything
|
|
||||||
// that's out there. This is just for the major platforms and OSes.
|
|
||||||
var platform = 'unknown platform', ua = navigator.userAgent;
|
|
||||||
|
|
||||||
// Detect OS
|
|
||||||
var oses = ['Windows','iPhone OS','(Intel |PPC )?Mac OS X','Linux'].join('|');
|
|
||||||
var pOS = new RegExp('((' + oses + ') [^ \);]*)').test(ua) ? RegExp.$1 : null;
|
|
||||||
if (!pOS) pOS = new RegExp('((' + oses + ')[^ \);]*)').test(ua) ? RegExp.$1 : null;
|
|
||||||
|
|
||||||
// Detect browser
|
|
||||||
var pName = /(Chrome|MSIE|Safari|Opera|Firefox)/.test(ua) ? RegExp.$1 : null;
|
|
||||||
|
|
||||||
// Detect version
|
|
||||||
var vre = new RegExp('(Version|' + pName + ')[ \/]([^ ;]*)');
|
|
||||||
var pVersion = (pName && vre.test(ua)) ? RegExp.$2 : null;
|
|
||||||
var platform = (pOS && pName && pVersion) ? pName + ' ' + pVersion + ' on ' + pOS : 'unknown platform';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A smattering of methods that are needed to implement the JSLitmus testbed.
|
|
||||||
*/
|
|
||||||
var jsl = {
|
|
||||||
/**
|
|
||||||
* Enhanced version of escape()
|
|
||||||
*/
|
|
||||||
escape: function(s) {
|
|
||||||
s = s.replace(/,/g, '\\,');
|
|
||||||
s = escape(s);
|
|
||||||
s = s.replace(/\+/g, '%2b');
|
|
||||||
s = s.replace(/ /g, '+');
|
|
||||||
return s;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an element by ID.
|
|
||||||
*/
|
|
||||||
$: function(id) {
|
|
||||||
return document.getElementById(id);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Null function
|
|
||||||
*/
|
|
||||||
F: function() {},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the status shown in the UI
|
|
||||||
*/
|
|
||||||
status: function(msg) {
|
|
||||||
var el = jsl.$('jsl_status');
|
|
||||||
if (el) el.innerHTML = msg || '';
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a number to an abbreviated string like, "15K" or "10M"
|
|
||||||
*/
|
|
||||||
toLabel: function(n) {
|
|
||||||
if (n == Infinity) {
|
|
||||||
return 'Infinity';
|
|
||||||
} else if (n > 1e9) {
|
|
||||||
n = Math.round(n/1e8);
|
|
||||||
return n/10 + 'B';
|
|
||||||
} else if (n > 1e6) {
|
|
||||||
n = Math.round(n/1e5);
|
|
||||||
return n/10 + 'M';
|
|
||||||
} else if (n > 1e3) {
|
|
||||||
n = Math.round(n/1e2);
|
|
||||||
return n/10 + 'K';
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy properties from src to dst
|
|
||||||
*/
|
|
||||||
extend: function(dst, src) {
|
|
||||||
for (var k in src) dst[k] = src[k]; return dst;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Like Array.join(), but for the key-value pairs in an object
|
|
||||||
*/
|
|
||||||
join: function(o, delimit1, delimit2) {
|
|
||||||
if (o.join) return o.join(delimit1); // If it's an array
|
|
||||||
var pairs = [];
|
|
||||||
for (var k in o) pairs.push(k + delimit1 + o[k]);
|
|
||||||
return pairs.join(delimit2);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Array#indexOf isn't supported in IE, so we use this as a cross-browser solution
|
|
||||||
*/
|
|
||||||
indexOf: function(arr, o) {
|
|
||||||
if (arr.indexOf) return arr.indexOf(o);
|
|
||||||
for (var i = 0; i < this.length; i++) if (arr[i] === o) return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test manages a single test (created with
|
|
||||||
* JSLitmus.test())
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
var Test = function (name, f) {
|
|
||||||
if (!f) throw new Error('Undefined test function');
|
|
||||||
if (!(/function[^\(]*\(([^,\)]*)/).test(f.toString())) {
|
|
||||||
throw new Error('"' + name + '" test: Test is not a valid Function object');
|
|
||||||
}
|
|
||||||
this.loopArg = RegExp.$1;
|
|
||||||
this.name = name;
|
|
||||||
this.f = f;
|
|
||||||
};
|
|
||||||
|
|
||||||
jsl.extend(Test, /** @lends Test */ {
|
|
||||||
/** Calibration tests for establishing iteration loop overhead */
|
|
||||||
CALIBRATIONS: [
|
|
||||||
new Test('calibrating loop', function(count) {while (count--);}),
|
|
||||||
new Test('calibrating function', jsl.F)
|
|
||||||
],
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run calibration tests. Returns true if calibrations are not yet
|
|
||||||
* complete (in which case calling code should run the tests yet again).
|
|
||||||
* onCalibrated - Callback to invoke when calibrations have finished
|
|
||||||
*/
|
|
||||||
calibrate: function(onCalibrated) {
|
|
||||||
for (var i = 0; i < Test.CALIBRATIONS.length; i++) {
|
|
||||||
var cal = Test.CALIBRATIONS[i];
|
|
||||||
if (cal.running) return true;
|
|
||||||
if (!cal.count) {
|
|
||||||
cal.isCalibration = true;
|
|
||||||
cal.onStop = onCalibrated;
|
|
||||||
//cal.MIN_TIME = .1; // Do calibrations quickly
|
|
||||||
cal.run(2e4);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
jsl.extend(Test.prototype, {/** @lends Test.prototype */
|
|
||||||
/** Initial number of iterations */
|
|
||||||
INIT_COUNT: 10,
|
|
||||||
/** Max iterations allowed (i.e. used to detect bad looping functions) */
|
|
||||||
MAX_COUNT: 1e9,
|
|
||||||
/** Minimum time a test should take to get valid results (secs) */
|
|
||||||
MIN_TIME: .5,
|
|
||||||
|
|
||||||
/** Callback invoked when test state changes */
|
|
||||||
onChange: jsl.F,
|
|
||||||
|
|
||||||
/** Callback invoked when test is finished */
|
|
||||||
onStop: jsl.F,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset test state
|
|
||||||
*/
|
|
||||||
reset: function() {
|
|
||||||
delete this.count;
|
|
||||||
delete this.time;
|
|
||||||
delete this.running;
|
|
||||||
delete this.error;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run the test (in a timeout). We use a timeout to make sure the browser
|
|
||||||
* has a chance to finish rendering any UI changes we've made, like
|
|
||||||
* updating the status message.
|
|
||||||
*/
|
|
||||||
run: function(count) {
|
|
||||||
count = count || this.INIT_COUNT;
|
|
||||||
jsl.status(this.name + ' x ' + count);
|
|
||||||
this.running = true;
|
|
||||||
var me = this;
|
|
||||||
setTimeout(function() {me._run(count);}, 200);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The nuts and bolts code that actually runs a test
|
|
||||||
*/
|
|
||||||
_run: function(count) {
|
|
||||||
var me = this;
|
|
||||||
|
|
||||||
// Make sure calibration tests have run
|
|
||||||
if (!me.isCalibration && Test.calibrate(function() {me.run(count);})) return;
|
|
||||||
this.error = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
var start, f = this.f, now, i = count;
|
|
||||||
|
|
||||||
// Start the timer
|
|
||||||
start = new Date();
|
|
||||||
|
|
||||||
// Now for the money shot. If this is a looping function ...
|
|
||||||
if (this.loopArg) {
|
|
||||||
// ... let it do the iteration itself
|
|
||||||
f(count);
|
|
||||||
} else {
|
|
||||||
// ... otherwise do the iteration for it
|
|
||||||
while (i--) f();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get time test took (in secs)
|
|
||||||
this.time = Math.max(1,new Date() - start)/1000;
|
|
||||||
|
|
||||||
// Store iteration count and per-operation time taken
|
|
||||||
this.count = count;
|
|
||||||
this.period = this.time/count;
|
|
||||||
|
|
||||||
// Do we need to do another run?
|
|
||||||
this.running = this.time <= this.MIN_TIME;
|
|
||||||
|
|
||||||
// ... if so, compute how many times we should iterate
|
|
||||||
if (this.running) {
|
|
||||||
// Bump the count to the nearest power of 2
|
|
||||||
var x = this.MIN_TIME/this.time;
|
|
||||||
var pow = Math.pow(2, Math.max(1, Math.ceil(Math.log(x)/Math.log(2))));
|
|
||||||
count *= pow;
|
|
||||||
if (count > this.MAX_COUNT) {
|
|
||||||
throw new Error('Max count exceeded. If this test uses a looping function, make sure the iteration loop is working properly.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// Exceptions are caught and displayed in the test UI
|
|
||||||
this.reset();
|
|
||||||
this.error = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Figure out what to do next
|
|
||||||
if (this.running) {
|
|
||||||
me.run(count);
|
|
||||||
} else {
|
|
||||||
jsl.status('');
|
|
||||||
me.onStop(me);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finish up
|
|
||||||
this.onChange(this);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the number of operations per second for this test.
|
|
||||||
*
|
|
||||||
* @param normalize if true, iteration loop overhead taken into account
|
|
||||||
*/
|
|
||||||
getHz: function(/**Boolean*/ normalize) {
|
|
||||||
var p = this.period;
|
|
||||||
|
|
||||||
// Adjust period based on the calibration test time
|
|
||||||
if (normalize && !this.isCalibration) {
|
|
||||||
var cal = Test.CALIBRATIONS[this.loopArg ? 0 : 1];
|
|
||||||
|
|
||||||
// If the period is within 20% of the calibration time, then zero the
|
|
||||||
// it out
|
|
||||||
p = p < cal.period*1.2 ? 0 : p - cal.period;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Math.round(1/p);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a friendly string describing the test
|
|
||||||
*/
|
|
||||||
toString: function() {
|
|
||||||
return this.name + ' - ' + this.time/this.count + ' secs';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// CSS we need for the UI
|
|
||||||
var STYLESHEET = '<style> \
|
|
||||||
#jslitmus {font-family:sans-serif; font-size: 12px;} \
|
|
||||||
#jslitmus a {text-decoration: none;} \
|
|
||||||
#jslitmus a:hover {text-decoration: underline;} \
|
|
||||||
#jsl_status { \
|
|
||||||
margin-top: 10px; \
|
|
||||||
font-size: 10px; \
|
|
||||||
color: #888; \
|
|
||||||
} \
|
|
||||||
A IMG {border:none} \
|
|
||||||
#test_results { \
|
|
||||||
margin-top: 10px; \
|
|
||||||
font-size: 12px; \
|
|
||||||
font-family: sans-serif; \
|
|
||||||
border-collapse: collapse; \
|
|
||||||
border-spacing: 0px; \
|
|
||||||
} \
|
|
||||||
#test_results th, #test_results td { \
|
|
||||||
border: solid 1px #ccc; \
|
|
||||||
vertical-align: top; \
|
|
||||||
padding: 3px; \
|
|
||||||
} \
|
|
||||||
#test_results th { \
|
|
||||||
vertical-align: bottom; \
|
|
||||||
background-color: #ccc; \
|
|
||||||
padding: 1px; \
|
|
||||||
font-size: 10px; \
|
|
||||||
} \
|
|
||||||
#test_results #test_platform { \
|
|
||||||
color: #444; \
|
|
||||||
text-align:center; \
|
|
||||||
} \
|
|
||||||
#test_results .test_row { \
|
|
||||||
color: #006; \
|
|
||||||
cursor: pointer; \
|
|
||||||
} \
|
|
||||||
#test_results .test_nonlooping { \
|
|
||||||
border-left-style: dotted; \
|
|
||||||
border-left-width: 2px; \
|
|
||||||
} \
|
|
||||||
#test_results .test_looping { \
|
|
||||||
border-left-style: solid; \
|
|
||||||
border-left-width: 2px; \
|
|
||||||
} \
|
|
||||||
#test_results .test_name {white-space: nowrap;} \
|
|
||||||
#test_results .test_pending { \
|
|
||||||
} \
|
|
||||||
#test_results .test_running { \
|
|
||||||
font-style: italic; \
|
|
||||||
} \
|
|
||||||
#test_results .test_done {} \
|
|
||||||
#test_results .test_done { \
|
|
||||||
text-align: right; \
|
|
||||||
font-family: monospace; \
|
|
||||||
} \
|
|
||||||
#test_results .test_error {color: #600;} \
|
|
||||||
#test_results .test_error .error_head {font-weight:bold;} \
|
|
||||||
#test_results .test_error .error_body {font-size:85%;} \
|
|
||||||
#test_results .test_row:hover td { \
|
|
||||||
background-color: #ffc; \
|
|
||||||
text-decoration: underline; \
|
|
||||||
} \
|
|
||||||
#chart { \
|
|
||||||
margin: 10px 0px; \
|
|
||||||
width: 250px; \
|
|
||||||
} \
|
|
||||||
#chart img { \
|
|
||||||
border: solid 1px #ccc; \
|
|
||||||
margin-bottom: 5px; \
|
|
||||||
} \
|
|
||||||
#chart #tiny_url { \
|
|
||||||
height: 40px; \
|
|
||||||
width: 250px; \
|
|
||||||
} \
|
|
||||||
#jslitmus_credit { \
|
|
||||||
font-size: 10px; \
|
|
||||||
color: #888; \
|
|
||||||
margin-top: 8px; \
|
|
||||||
} \
|
|
||||||
</style>';
|
|
||||||
|
|
||||||
// HTML markup for the UI
|
|
||||||
var MARKUP = '<div id="jslitmus"> \
|
|
||||||
<button onclick="JSLitmus.runAll(event)">Run Tests</button> \
|
|
||||||
<button id="stop_button" disabled="disabled" onclick="JSLitmus.stop()">Stop Tests</button> \
|
|
||||||
<br \> \
|
|
||||||
<br \> \
|
|
||||||
<input type="checkbox" style="vertical-align: middle" id="test_normalize" checked="checked" onchange="JSLitmus.renderAll()""> Normalize results \
|
|
||||||
<table id="test_results"> \
|
|
||||||
<colgroup> \
|
|
||||||
<col /> \
|
|
||||||
<col width="100" /> \
|
|
||||||
</colgroup> \
|
|
||||||
<tr><th id="test_platform" colspan="2">' + platform + '</th></tr> \
|
|
||||||
<tr><th>Test</th><th>Ops/sec</th></tr> \
|
|
||||||
<tr id="test_row_template" class="test_row" style="display:none"> \
|
|
||||||
<td class="test_name"></td> \
|
|
||||||
<td class="test_result">Ready</td> \
|
|
||||||
</tr> \
|
|
||||||
</table> \
|
|
||||||
<div id="jsl_status"></div> \
|
|
||||||
<div id="chart" style="display:none"> \
|
|
||||||
<a id="chart_link" target="_blank"><img id="chart_image"></a> \
|
|
||||||
TinyURL (for chart): \
|
|
||||||
<iframe id="tiny_url" frameBorder="0" scrolling="no" src=""></iframe> \
|
|
||||||
</div> \
|
|
||||||
<a id="jslitmus_credit" title="JSLitmus home page" href="http://code.google.com/p/jslitmus" target="_blank">Powered by JSLitmus</a> \
|
|
||||||
</div>';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The public API for creating and running tests
|
|
||||||
*/
|
|
||||||
window.JSLitmus = {
|
|
||||||
/** The list of all tests that have been registered with JSLitmus.test */
|
|
||||||
_tests: [],
|
|
||||||
/** The queue of tests that need to be run */
|
|
||||||
_queue: [],
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The parsed query parameters the current page URL. This is provided as a
|
|
||||||
* convenience for test functions - it's not used by JSLitmus proper
|
|
||||||
*/
|
|
||||||
params: {},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize
|
|
||||||
*/
|
|
||||||
_init: function() {
|
|
||||||
// Parse query params into JSLitmus.params[] hash
|
|
||||||
var match = (location + '').match(/([^?#]*)(#.*)?$/);
|
|
||||||
if (match) {
|
|
||||||
var pairs = match[1].split('&');
|
|
||||||
for (var i = 0; i < pairs.length; i++) {
|
|
||||||
var pair = pairs[i].split('=');
|
|
||||||
if (pair.length > 1) {
|
|
||||||
var key = pair.shift();
|
|
||||||
var value = pair.length > 1 ? pair.join('=') : pair[0];
|
|
||||||
this.params[key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write out the stylesheet. We have to do this here because IE
|
|
||||||
// doesn't honor sheets written after the document has loaded.
|
|
||||||
document.write(STYLESHEET);
|
|
||||||
|
|
||||||
// Setup the rest of the UI once the document is loaded
|
|
||||||
if (window.addEventListener) {
|
|
||||||
window.addEventListener('load', this._setup, false);
|
|
||||||
} else if (document.addEventListener) {
|
|
||||||
document.addEventListener('load', this._setup, false);
|
|
||||||
} else if (window.attachEvent) {
|
|
||||||
window.attachEvent('onload', this._setup);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set up the UI
|
|
||||||
*/
|
|
||||||
_setup: function() {
|
|
||||||
var el = jsl.$('jslitmus_container');
|
|
||||||
if (!el) document.body.appendChild(el = document.createElement('div'));
|
|
||||||
|
|
||||||
el.innerHTML = MARKUP;
|
|
||||||
|
|
||||||
// Render the UI for all our tests
|
|
||||||
for (var i=0; i < JSLitmus._tests.length; i++)
|
|
||||||
JSLitmus.renderTest(JSLitmus._tests[i]);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Re)render all the test results
|
|
||||||
*/
|
|
||||||
renderAll: function() {
|
|
||||||
for (var i = 0; i < JSLitmus._tests.length; i++)
|
|
||||||
JSLitmus.renderTest(JSLitmus._tests[i]);
|
|
||||||
JSLitmus.renderChart();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Re)render the chart graphics
|
|
||||||
*/
|
|
||||||
renderChart: function() {
|
|
||||||
var url = JSLitmus.chartUrl();
|
|
||||||
jsl.$('chart_link').href = url;
|
|
||||||
jsl.$('chart_image').src = url;
|
|
||||||
jsl.$('chart').style.display = '';
|
|
||||||
|
|
||||||
// Update the tiny URL
|
|
||||||
jsl.$('tiny_url').src = 'http://tinyurl.com/api-create.php?url='+escape(url);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Re)render the results for a specific test
|
|
||||||
*/
|
|
||||||
renderTest: function(test) {
|
|
||||||
// Make a new row if needed
|
|
||||||
if (!test._row) {
|
|
||||||
var trow = jsl.$('test_row_template');
|
|
||||||
if (!trow) return;
|
|
||||||
|
|
||||||
test._row = trow.cloneNode(true);
|
|
||||||
test._row.style.display = '';
|
|
||||||
test._row.id = '';
|
|
||||||
test._row.onclick = function() {JSLitmus._queueTest(test);};
|
|
||||||
test._row.title = 'Run ' + test.name + ' test';
|
|
||||||
trow.parentNode.appendChild(test._row);
|
|
||||||
test._row.cells[0].innerHTML = test.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
var cell = test._row.cells[1];
|
|
||||||
var cns = [test.loopArg ? 'test_looping' : 'test_nonlooping'];
|
|
||||||
|
|
||||||
if (test.error) {
|
|
||||||
cns.push('test_error');
|
|
||||||
cell.innerHTML =
|
|
||||||
'<div class="error_head">' + test.error + '</div>' +
|
|
||||||
'<ul class="error_body"><li>' +
|
|
||||||
jsl.join(test.error, ': ', '</li><li>') +
|
|
||||||
'</li></ul>';
|
|
||||||
} else {
|
|
||||||
if (test.running) {
|
|
||||||
cns.push('test_running');
|
|
||||||
cell.innerHTML = 'running';
|
|
||||||
} else if (jsl.indexOf(JSLitmus._queue, test) >= 0) {
|
|
||||||
cns.push('test_pending');
|
|
||||||
cell.innerHTML = 'pending';
|
|
||||||
} else if (test.count) {
|
|
||||||
cns.push('test_done');
|
|
||||||
var hz = test.getHz(jsl.$('test_normalize').checked);
|
|
||||||
cell.innerHTML = hz != Infinity ? hz : '∞';
|
|
||||||
} else {
|
|
||||||
cell.innerHTML = 'ready';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cell.className = cns.join(' ');
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new test
|
|
||||||
*/
|
|
||||||
test: function(name, f) {
|
|
||||||
// Create the Test object
|
|
||||||
var test = new Test(name, f);
|
|
||||||
JSLitmus._tests.push(test);
|
|
||||||
|
|
||||||
// Re-render if the test state changes
|
|
||||||
test.onChange = JSLitmus.renderTest;
|
|
||||||
|
|
||||||
// Run the next test if this one finished
|
|
||||||
test.onStop = function(test) {
|
|
||||||
if (JSLitmus.onTestFinish) JSLitmus.onTestFinish(test);
|
|
||||||
JSLitmus.currentTest = null;
|
|
||||||
JSLitmus._nextTest();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Render the new test
|
|
||||||
this.renderTest(test);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add all tests to the run queue
|
|
||||||
*/
|
|
||||||
runAll: function(e) {
|
|
||||||
e = e || window.event;
|
|
||||||
var reverse = e && e.shiftKey, len = JSLitmus._tests.length;
|
|
||||||
for (var i = 0; i < len; i++) {
|
|
||||||
JSLitmus._queueTest(JSLitmus._tests[!reverse ? i : (len - i - 1)]);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove all tests from the run queue. The current test has to finish on
|
|
||||||
* it's own though
|
|
||||||
*/
|
|
||||||
stop: function() {
|
|
||||||
while (JSLitmus._queue.length) {
|
|
||||||
var test = JSLitmus._queue.shift();
|
|
||||||
JSLitmus.renderTest(test);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run the next test in the run queue
|
|
||||||
*/
|
|
||||||
_nextTest: function() {
|
|
||||||
if (!JSLitmus.currentTest) {
|
|
||||||
var test = JSLitmus._queue.shift();
|
|
||||||
if (test) {
|
|
||||||
jsl.$('stop_button').disabled = false;
|
|
||||||
JSLitmus.currentTest = test;
|
|
||||||
test.run();
|
|
||||||
JSLitmus.renderTest(test);
|
|
||||||
if (JSLitmus.onTestStart) JSLitmus.onTestStart(test);
|
|
||||||
} else {
|
|
||||||
jsl.$('stop_button').disabled = true;
|
|
||||||
JSLitmus.renderChart();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a test to the run queue
|
|
||||||
*/
|
|
||||||
_queueTest: function(test) {
|
|
||||||
if (jsl.indexOf(JSLitmus._queue, test) >= 0) return;
|
|
||||||
JSLitmus._queue.push(test);
|
|
||||||
JSLitmus.renderTest(test);
|
|
||||||
JSLitmus._nextTest();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a Google Chart URL that shows the data for all tests
|
|
||||||
*/
|
|
||||||
chartUrl: function() {
|
|
||||||
var n = JSLitmus._tests.length, markers = [], data = [];
|
|
||||||
var d, min = 0, max = -1e10;
|
|
||||||
var normalize = jsl.$('test_normalize').checked;
|
|
||||||
|
|
||||||
// Gather test data
|
|
||||||
for (var i=0; i < JSLitmus._tests.length; i++) {
|
|
||||||
var test = JSLitmus._tests[i];
|
|
||||||
if (test.count) {
|
|
||||||
var hz = test.getHz(normalize);
|
|
||||||
var v = hz != Infinity ? hz : 0;
|
|
||||||
data.push(v);
|
|
||||||
markers.push('t' + jsl.escape(test.name + '(' + jsl.toLabel(hz)+ ')') + ',000000,0,' +
|
|
||||||
markers.length + ',10');
|
|
||||||
max = Math.max(v, max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (markers.length <= 0) return null;
|
|
||||||
|
|
||||||
// Build chart title
|
|
||||||
var title = document.getElementsByTagName('title');
|
|
||||||
title = (title && title.length) ? title[0].innerHTML : null;
|
|
||||||
var chart_title = [];
|
|
||||||
if (title) chart_title.push(title);
|
|
||||||
chart_title.push('Ops/sec (' + platform + ')');
|
|
||||||
|
|
||||||
// Build labels
|
|
||||||
var labels = [jsl.toLabel(min), jsl.toLabel(max)];
|
|
||||||
|
|
||||||
var w = 250, bw = 15;
|
|
||||||
var bs = 5;
|
|
||||||
var h = markers.length*(bw + bs) + 30 + chart_title.length*20;
|
|
||||||
|
|
||||||
var params = {
|
|
||||||
chtt: escape(chart_title.join('|')),
|
|
||||||
chts: '000000,10',
|
|
||||||
cht: 'bhg', // chart type
|
|
||||||
chd: 't:' + data.join(','), // data set
|
|
||||||
chds: min + ',' + max, // max/min of data
|
|
||||||
chxt: 'x', // label axes
|
|
||||||
chxl: '0:|' + labels.join('|'), // labels
|
|
||||||
chsp: '0,1',
|
|
||||||
chm: markers.join('|'), // test names
|
|
||||||
chbh: [bw, 0, bs].join(','), // bar widths
|
|
||||||
// chf: 'bg,lg,0,eeeeee,0,eeeeee,.5,ffffff,1', // gradient
|
|
||||||
chs: w + 'x' + h
|
|
||||||
};
|
|
||||||
return 'http://chart.apis.google.com/chart?' + jsl.join(params, '=', '&');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
JSLitmus._init();
|
|
||||||
})();
|
|
776
vendor/underscore/test/vendor/qunit-extras.js
vendored
Normal file
776
vendor/underscore/test/vendor/qunit-extras.js
vendored
Normal file
|
@ -0,0 +1,776 @@
|
||||||
|
/*!
|
||||||
|
* QUnit Extras v1.4.1
|
||||||
|
* Copyright 2011-2015 John-David Dalton <http://allyoucanleet.com/>
|
||||||
|
* Based on a gist by Jörn Zaefferer <https://gist.github.com/722381>
|
||||||
|
* Available under MIT license <http://mths.be/mit>
|
||||||
|
*/
|
||||||
|
;(function() {
|
||||||
|
|
||||||
|
/** Used as a safe reference for `undefined` in pre ES5 environments. */
|
||||||
|
var undefined;
|
||||||
|
|
||||||
|
/** Used as a horizontal rule in console output. */
|
||||||
|
var hr = '----------------------------------------';
|
||||||
|
|
||||||
|
/** Used for native method references. */
|
||||||
|
var arrayProto = Array.prototype;
|
||||||
|
|
||||||
|
/** Native method shortcut. */
|
||||||
|
var push = arrayProto.push,
|
||||||
|
unshift = arrayProto.unshift;
|
||||||
|
|
||||||
|
/** Used to match HTML entities. */
|
||||||
|
var reEscapedHtml = /(&|<|>|"|')/g;
|
||||||
|
|
||||||
|
/** Used to match parts of the assert message. */
|
||||||
|
var reDied = /^Died on test #\d+/,
|
||||||
|
reMessage = /^<span class='test-message'>([\s\S]*?)<\/span>/;
|
||||||
|
|
||||||
|
/** Used to associate color names with their corresponding codes. */
|
||||||
|
var ansiCodes = {
|
||||||
|
'bold': 1,
|
||||||
|
'green': 32,
|
||||||
|
'magenta': 35,
|
||||||
|
'red': 31
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Used to convert HTML entities to characters. */
|
||||||
|
var htmlUnescapes = {
|
||||||
|
'&': '&',
|
||||||
|
'<': '<',
|
||||||
|
'>': '>',
|
||||||
|
'"': '"',
|
||||||
|
''': "'"
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Used to determine if values are of the language type Object. */
|
||||||
|
var objectTypes = {
|
||||||
|
'function': true,
|
||||||
|
'object': true
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Used as a reference to the global object. */
|
||||||
|
var root = (objectTypes[typeof window] && window) || this;
|
||||||
|
|
||||||
|
/** Detect free variable `exports`. */
|
||||||
|
var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
|
||||||
|
|
||||||
|
/** Detect free variable `module`. */
|
||||||
|
var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
|
||||||
|
|
||||||
|
/** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */
|
||||||
|
var freeGlobal = freeExports && freeModule && typeof global == 'object' && global;
|
||||||
|
if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) {
|
||||||
|
root = freeGlobal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a given value is present in an array using strict equality
|
||||||
|
* for comparisons, i.e. `===`.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Array} array The array to iterate over.
|
||||||
|
* @param {*} value The value to check for.
|
||||||
|
* @returns {boolean} Returns `true` if the `value` is found, else `false`.
|
||||||
|
*/
|
||||||
|
function contains(array, value) {
|
||||||
|
var index = -1,
|
||||||
|
length = array ? array.length : 0;
|
||||||
|
|
||||||
|
while (++index < length) {
|
||||||
|
if (array[index] === value) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if `value` is the language type of `Object`.
|
||||||
|
* (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {*} value The value to check.
|
||||||
|
* @returns {boolean} Returns `true` if `value` is an object, else `false`.
|
||||||
|
*/
|
||||||
|
function isObject(value) {
|
||||||
|
var type = typeof value;
|
||||||
|
return type == 'function' || (value && type == 'object') || false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a string with `text` repeated `n` number of times.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {string} text The text to repeat.
|
||||||
|
* @param {number} n The number of times to repeat `text`.
|
||||||
|
* @returns {string} The created string.
|
||||||
|
*/
|
||||||
|
function repeat(text, n) {
|
||||||
|
return Array(n + 1).join(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the value of property `key` on `object`.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Object} object The object to inspect.
|
||||||
|
* @param {string} key The name of the property to resolve.
|
||||||
|
* @returns {*} Returns the resolved value.
|
||||||
|
*/
|
||||||
|
function result(object, key) {
|
||||||
|
return object == null ? undefined : object[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the HTML entities `&`, `<`, `>`, `"`, and `'`
|
||||||
|
* in `string` to their corresponding characters.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {string} string The string to unescape.
|
||||||
|
* @returns {string} Returns the unescaped string.
|
||||||
|
*/
|
||||||
|
function unescape(string) {
|
||||||
|
return string == null ? '' : String(string).replace(reEscapedHtml, unescapeHtmlChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by `unescape` to convert HTML entities to characters.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {string} match The matched character to unescape.
|
||||||
|
* @returns {string} Returns the unescaped character.
|
||||||
|
*/
|
||||||
|
function unescapeHtmlChar(match) {
|
||||||
|
return htmlUnescapes[match];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a function that provides `value` to the wrapper function as its
|
||||||
|
* first argument. Additional arguments provided to the function are appended
|
||||||
|
* to those provided to the wrapper function. The wrapper is executed with
|
||||||
|
* the `this` binding of the created function.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {*} value The value to wrap.
|
||||||
|
* @param {Function} wrapper The wrapper function.
|
||||||
|
* @returns {Function} Returns the new function.
|
||||||
|
*/
|
||||||
|
function wrap(value, wrapper) {
|
||||||
|
return function() {
|
||||||
|
var args = [value];
|
||||||
|
push.apply(args, arguments);
|
||||||
|
return wrapper.apply(this, args);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Installs the QUnit additions on the given `context` object.
|
||||||
|
*
|
||||||
|
* @memberOf exports
|
||||||
|
* @param {Object} context The context object.
|
||||||
|
*/
|
||||||
|
function runInContext(context) {
|
||||||
|
|
||||||
|
/** Object references. */
|
||||||
|
var phantom = context.phantom,
|
||||||
|
define = context.define,
|
||||||
|
document = !phantom && context.document,
|
||||||
|
process = phantom || context.process,
|
||||||
|
amd = define && define.amd,
|
||||||
|
console = context.console,
|
||||||
|
java = !document && context.java,
|
||||||
|
print = context.print,
|
||||||
|
require = context.require;
|
||||||
|
|
||||||
|
/** Detects if running on Node.js. */
|
||||||
|
var isNode = isObject(process) && typeof process.on == 'function';
|
||||||
|
|
||||||
|
/** Detects if running in a PhantomJS web page. */
|
||||||
|
var isPhantomPage = typeof context.callPhantom == 'function';
|
||||||
|
|
||||||
|
/** Detects if QUnit Extras should log to the console. */
|
||||||
|
var isSilent = document && !isPhantomPage;
|
||||||
|
|
||||||
|
/** Used to indicate if running in Windows. */
|
||||||
|
var isWindows = isNode && process.platform == 'win32';
|
||||||
|
|
||||||
|
/** Used to indicate if ANSI escape codes are supported. */
|
||||||
|
var isAnsiSupported = (function() {
|
||||||
|
if (isNode && process.stdout && !process.stdout.isTTY) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (isWindows || getEnv('COLORTERM')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return /^(?:ansi|cygwin|linux|screen|xterm|vt100)$|color/i.test(getEnv('TERM'));
|
||||||
|
}());
|
||||||
|
|
||||||
|
/** Used to display the wait throbber. */
|
||||||
|
var throbberDelay = 500,
|
||||||
|
waitCount = -1;
|
||||||
|
|
||||||
|
/** Shorten `context.QUnit.QUnit` to `context.QUnit`. */
|
||||||
|
var QUnit = context.QUnit = context.QUnit.QUnit || context.QUnit;
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules timer-based callbacks.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Function|string} fn The function to call.
|
||||||
|
* @param {number} delay The number of milliseconds to delay the `fn` call.
|
||||||
|
* @param {Array} args Arguments to invoke `fn` with.
|
||||||
|
* @param {boolean} repeated A flag to specify whether `fn` is called repeatedly.
|
||||||
|
* @returns {number} The ID of the timeout.
|
||||||
|
*/
|
||||||
|
function schedule(fn, delay, args, repeated) {
|
||||||
|
// Rhino 1.7RC4 will error assigning `task` below.
|
||||||
|
// See https://bugzilla.mozilla.org/show_bug.cgi?id=775566.
|
||||||
|
var task = ids[++counter] = new JavaAdapter(java.util.TimerTask, {
|
||||||
|
'run': function() {
|
||||||
|
fn.apply(context, args);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Support non-functions.
|
||||||
|
if (typeof fn != 'function') {
|
||||||
|
fn = (function(code) {
|
||||||
|
code = String(code);
|
||||||
|
return function() { eval(code); };
|
||||||
|
}(fn));
|
||||||
|
}
|
||||||
|
// Used by `setInterval`.
|
||||||
|
if (repeated) {
|
||||||
|
timer.schedule(task, delay, delay);
|
||||||
|
}
|
||||||
|
// Used by `setTimeout`.
|
||||||
|
else {
|
||||||
|
timer.schedule(task, delay);
|
||||||
|
}
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the delay set by `setInterval` or `setTimeout`.
|
||||||
|
*
|
||||||
|
* @memberOf context
|
||||||
|
* @param {number} id The ID of the timeout to be cleared.
|
||||||
|
*/
|
||||||
|
function clearTimer(id) {
|
||||||
|
if (ids[id]) {
|
||||||
|
ids[id].cancel();
|
||||||
|
timer.purge();
|
||||||
|
delete ids[id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes a code snippet or function repeatedly, with a delay between each call.
|
||||||
|
*
|
||||||
|
* @memberOf context
|
||||||
|
* @param {Function|string} fn The function to call or string to evaluate.
|
||||||
|
* @param {number} delay The number of milliseconds to delay each `fn` call.
|
||||||
|
* @param {...*} [args] Arguments to invoke `fn` with.
|
||||||
|
* @returns {number} The ID of the timeout.
|
||||||
|
*/
|
||||||
|
function setInterval(fn, delay) {
|
||||||
|
return schedule(fn, delay, slice.call(arguments, 2), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes a code snippet or a function after specified delay.
|
||||||
|
*
|
||||||
|
* @memberOf context
|
||||||
|
* @param {Function|string} fn The function to call or string to evaluate.
|
||||||
|
* @param {number} delay The number of milliseconds to delay the `fn` call.
|
||||||
|
* @param {...*} [args] Arguments to invoke `fn` with.
|
||||||
|
* @returns {number} The ID of the timeout.
|
||||||
|
*/
|
||||||
|
function setTimeout(fn, delay) {
|
||||||
|
return schedule(fn, delay, slice.call(arguments, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the environment variable value by a given name.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {string} name The name of the environment variable to get.
|
||||||
|
* @returns {*} Returns the environment variable value.
|
||||||
|
*/
|
||||||
|
function getEnv(name) {
|
||||||
|
if (isNode) {
|
||||||
|
return process.env[name];
|
||||||
|
}
|
||||||
|
if (java) {
|
||||||
|
return java.lang.System.getenv(name);
|
||||||
|
}
|
||||||
|
if (!amd && typeof require == 'function') {
|
||||||
|
try {
|
||||||
|
return require('system').env[name];
|
||||||
|
} catch(e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds text color to the terminal output of `string`.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {string} colorName The name of the color to add.
|
||||||
|
* @param {string} string The string to add colors to.
|
||||||
|
* @returns {string} Returns the colored string.
|
||||||
|
*/
|
||||||
|
function color(colorName, string) {
|
||||||
|
return isAnsiSupported
|
||||||
|
? ('\x1B[' + ansiCodes[colorName] + 'm' + string + '\x1B[0m')
|
||||||
|
: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes an inline message to standard output.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {string} [text=''] The text to log.
|
||||||
|
*/
|
||||||
|
var logInline = (function() {
|
||||||
|
if (!isNode || isWindows) {
|
||||||
|
return function() {};
|
||||||
|
}
|
||||||
|
// Cleanup any inline logs when exited via `ctrl+c`.
|
||||||
|
process.on('SIGINT', function() {
|
||||||
|
logInline();
|
||||||
|
process.exit();
|
||||||
|
});
|
||||||
|
|
||||||
|
var prevLine = '';
|
||||||
|
return function(text) {
|
||||||
|
var blankLine = repeat(' ', prevLine.length);
|
||||||
|
if (text == null) {
|
||||||
|
text = '';
|
||||||
|
}
|
||||||
|
if (text.length > hr.length) {
|
||||||
|
text = text.slice(0, hr.length - 3) + '...';
|
||||||
|
}
|
||||||
|
prevLine = text;
|
||||||
|
process.stdout.write(text + blankLine.slice(text.length) + '\r');
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the wait throbber to standard output.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function logThrobber() {
|
||||||
|
logInline('Please wait' + repeat('.', (++waitCount % 3) + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of retries async tests have to succeed.
|
||||||
|
*
|
||||||
|
* @memberOf QUnit.config
|
||||||
|
* @type number
|
||||||
|
*/
|
||||||
|
QUnit.config.asyncRetries = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object of excused tests and assertions.
|
||||||
|
*
|
||||||
|
* @memberOf QUnit.config
|
||||||
|
* @type Object
|
||||||
|
*/
|
||||||
|
QUnit.config.excused = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object used to hold "extras" information about the current running test.
|
||||||
|
*
|
||||||
|
* @memberOf QUnit.config
|
||||||
|
* @type Object
|
||||||
|
*/
|
||||||
|
QUnit.config.extrasData = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data object for the active test module.
|
||||||
|
*
|
||||||
|
* @memberOf QUnit.config.extrasData
|
||||||
|
* @type Object
|
||||||
|
*/
|
||||||
|
'module': {},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data object for Sauce Labs.
|
||||||
|
*
|
||||||
|
* @memberOf QUnit.config.extrasData
|
||||||
|
* @type Object
|
||||||
|
*/
|
||||||
|
'sauce': {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of failed test details.
|
||||||
|
*
|
||||||
|
* @memberOf QUnit.config.extrasData.sauce
|
||||||
|
* @type Array
|
||||||
|
*/
|
||||||
|
'tests': []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an object into a string representation.
|
||||||
|
*
|
||||||
|
* @memberOf QUnit
|
||||||
|
* @type Function
|
||||||
|
* @param {Object} object The object to stringify.
|
||||||
|
* @returns {string} The result string.
|
||||||
|
*/
|
||||||
|
QUnit.jsDump.parsers.object = (function() {
|
||||||
|
var func = QUnit.jsDump.parsers.object;
|
||||||
|
if (isSilent) {
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
return function(object) {
|
||||||
|
if (typeof object.rhinoException != 'object') {
|
||||||
|
return func(object);
|
||||||
|
}
|
||||||
|
return object.name +
|
||||||
|
' { message: "' + object.message +
|
||||||
|
'", fileName: "' + object.fileName +
|
||||||
|
'", lineNumber: ' + object.lineNumber + ' }';
|
||||||
|
};
|
||||||
|
}());
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// Add a callback to be triggered after every assertion.
|
||||||
|
QUnit.log(function(details) {
|
||||||
|
QUnit.config.extrasData.module.logs.push(details);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add a callback to be triggered at the start of every test module.
|
||||||
|
QUnit.moduleStart(function(details) {
|
||||||
|
var module = QUnit.config.extrasData.module;
|
||||||
|
module.name = details.name;
|
||||||
|
module.logs = [];
|
||||||
|
module.printed = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wrap old API to intercept `expected` and `message`.
|
||||||
|
if (QUnit.push) {
|
||||||
|
QUnit.push = wrap(QUnit.push, function(push, result, actual, expected, message) {
|
||||||
|
push.call(this, result, actual, expected, message);
|
||||||
|
|
||||||
|
var asserts = QUnit.config.current.assertions,
|
||||||
|
item = asserts[asserts.length - 1];
|
||||||
|
|
||||||
|
item.expected = QUnit.jsDump.parse(expected);
|
||||||
|
item.text = message;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Wrap old API to intercept `message`.
|
||||||
|
if (QUnit.pushFailure) {
|
||||||
|
QUnit.pushFailure = wrap(QUnit.pushFailure, function(pushFailure, message, source, actual) {
|
||||||
|
pushFailure.call(this, message, source, actual);
|
||||||
|
|
||||||
|
var asserts = QUnit.config.current.assertions,
|
||||||
|
item = asserts[asserts.length - 1];
|
||||||
|
|
||||||
|
item.expected = '';
|
||||||
|
item.text = message;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Wrap to flag tests using `assert.async`.
|
||||||
|
if (QUnit.assert.async) {
|
||||||
|
QUnit.assert.async = wrap(QUnit.assert.async, function(async) {
|
||||||
|
this.test.usesAsync = true;
|
||||||
|
return async.call(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Add a callback to be triggered at the start of every test.
|
||||||
|
QUnit.testStart(function(details) {
|
||||||
|
var config = QUnit.config,
|
||||||
|
test = config.current;
|
||||||
|
|
||||||
|
var excused = config.excused || {},
|
||||||
|
excusedTests = excused[details.module],
|
||||||
|
excusedAsserts = excusedTests && excusedTests[details.name];
|
||||||
|
|
||||||
|
// Allow async tests to retry.
|
||||||
|
if (!test.retries) {
|
||||||
|
test.retries = 0;
|
||||||
|
test.finish = wrap(test.finish, function(finish) {
|
||||||
|
if (this.async || this.usesAsync) {
|
||||||
|
var asserts = this.assertions,
|
||||||
|
config = QUnit.config,
|
||||||
|
index = -1,
|
||||||
|
length = asserts.length,
|
||||||
|
logs = config.extrasData.module.logs,
|
||||||
|
queue = config.queue;
|
||||||
|
|
||||||
|
while (++index < length) {
|
||||||
|
var assert = asserts[index];
|
||||||
|
if (!assert.result && this.retries < config.asyncRetries) {
|
||||||
|
var oldLength = queue.length;
|
||||||
|
logs.length -= asserts.length;
|
||||||
|
asserts.length = 0;
|
||||||
|
|
||||||
|
this.retries++;
|
||||||
|
this.queue();
|
||||||
|
|
||||||
|
unshift.apply(queue, queue.splice(oldLength, queue.length - oldLength));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finish.call(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Exit early when there is nothing to excuse.
|
||||||
|
if (!excusedAsserts) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Excuse the entire test.
|
||||||
|
if (excusedAsserts === true) {
|
||||||
|
test.async = test.usesAsync = false;
|
||||||
|
test.callback = function() {};
|
||||||
|
test.expected = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Wrap to intercept `expected` and `message`.
|
||||||
|
if (test.push) {
|
||||||
|
test.push = wrap(test.push, function(push, result, actual, expected, message) {
|
||||||
|
push.call(this, result, actual, expected, message);
|
||||||
|
|
||||||
|
var item = this.assertions[this.assertions.length - 1];
|
||||||
|
item.expected = QUnit.jsDump.parse(expected);
|
||||||
|
item.text = message;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Wrap to intercept `message`.
|
||||||
|
if (test.pushFailure) {
|
||||||
|
test.pushFailure = wrap(test.pushFailure, function(pushFailure, message, source, actual) {
|
||||||
|
pushFailure.call(this, message, source, actual);
|
||||||
|
|
||||||
|
var item = this.assertions[this.assertions.length - 1];
|
||||||
|
item.expected = '';
|
||||||
|
item.text = message;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Wrap to excuse specific assertions.
|
||||||
|
test.finish = wrap(test.finish, function(finish) {
|
||||||
|
var asserts = this.assertions,
|
||||||
|
config = QUnit.config,
|
||||||
|
expected = this.expected,
|
||||||
|
items = asserts.slice(),
|
||||||
|
length = items.length;
|
||||||
|
|
||||||
|
if (expected == null) {
|
||||||
|
if (config.requireExpects) {
|
||||||
|
expected = length;
|
||||||
|
items.push('Expected number of assertions to be defined, but expect() was not called.');
|
||||||
|
} else if (!length) {
|
||||||
|
expected = 1;
|
||||||
|
items.push('Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.');
|
||||||
|
}
|
||||||
|
} else if (expected != length) {
|
||||||
|
items.push('Expected ' + expected + ' assertions, but ' + length + ' were run');
|
||||||
|
}
|
||||||
|
var index = -1;
|
||||||
|
length = items.length;
|
||||||
|
|
||||||
|
while (++index < length) {
|
||||||
|
var assert = items[index],
|
||||||
|
isStr = typeof assert == 'string';
|
||||||
|
|
||||||
|
var assertMessage = isStr ? assert : assert.text || unescape(result(reMessage.exec(assert.message), 1)),
|
||||||
|
assertValue = isStr ? assert : assert.expected,
|
||||||
|
assertDied = result(reDied.exec(assertMessage), 0);
|
||||||
|
|
||||||
|
if ((assertMessage && contains(excusedAsserts, assertMessage)) ||
|
||||||
|
(assertDied && contains(excusedAsserts, assertDied)) ||
|
||||||
|
(assertValue && (
|
||||||
|
contains(excusedAsserts, assertValue) ||
|
||||||
|
contains(excusedAsserts, assertValue.replace(/\s+/g, ''))
|
||||||
|
))) {
|
||||||
|
if (isStr) {
|
||||||
|
while (asserts.length < expected) {
|
||||||
|
asserts.push({ 'result': true });
|
||||||
|
}
|
||||||
|
asserts.length = expected;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert.result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finish.call(this);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add a callback to be triggered after a test is completed.
|
||||||
|
QUnit.testDone(function(details) {
|
||||||
|
var config = QUnit.config,
|
||||||
|
data = config.extrasData,
|
||||||
|
failures = details.failed,
|
||||||
|
hidepassed = config.hidepassed,
|
||||||
|
module = data.module,
|
||||||
|
moduleLogs = module.logs,
|
||||||
|
sauceTests = data.sauce.tests;
|
||||||
|
|
||||||
|
if (hidepassed && !failures) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isSilent) {
|
||||||
|
logInline();
|
||||||
|
if (!module.printed) {
|
||||||
|
module.printed = true;
|
||||||
|
console.log(hr);
|
||||||
|
console.log(color('bold', module.name));
|
||||||
|
console.log(hr);
|
||||||
|
}
|
||||||
|
console.log(' ' + (failures ? color('red', 'FAIL') : color('green', 'PASS')) + ' - ' + details.name);
|
||||||
|
}
|
||||||
|
if (!failures) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var index = -1,
|
||||||
|
length = moduleLogs.length;
|
||||||
|
|
||||||
|
while(++index < length) {
|
||||||
|
var entry = moduleLogs[index];
|
||||||
|
if (hidepassed && entry.result) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var expected = entry.expected,
|
||||||
|
result = entry.result,
|
||||||
|
type = typeof expected != 'undefined' ? 'EQ' : 'OK';
|
||||||
|
|
||||||
|
var message = [
|
||||||
|
result ? color('green', 'PASS') : color('red', 'FAIL'),
|
||||||
|
type,
|
||||||
|
entry.message || 'ok'
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!result && type == 'EQ') {
|
||||||
|
message.push(color('magenta', 'Expected: ' + expected + ', Actual: ' + entry.actual));
|
||||||
|
}
|
||||||
|
if (!isSilent) {
|
||||||
|
console.log(' ' + message.join(' | '));
|
||||||
|
}
|
||||||
|
if (!entry.result) {
|
||||||
|
sauceTests.push(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add a callback to be triggered when all testing has completed.
|
||||||
|
QUnit.done(function(details) {
|
||||||
|
var failures = details.failed,
|
||||||
|
statusColor = failures ? 'magenta' : 'green';
|
||||||
|
|
||||||
|
if (!isSilent) {
|
||||||
|
logInline();
|
||||||
|
console.log(hr);
|
||||||
|
console.log(color(statusColor, ' PASS: ' + details.passed + ' FAIL: ' + failures + ' TOTAL: ' + details.total));
|
||||||
|
console.log(color(statusColor, ' Finished in ' + details.runtime + ' milliseconds.'));
|
||||||
|
console.log(hr);
|
||||||
|
}
|
||||||
|
// Exit out of Node.js or PhantomJS.
|
||||||
|
try {
|
||||||
|
if (failures) {
|
||||||
|
process.exit(1);
|
||||||
|
} else {
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
} catch(e) {}
|
||||||
|
|
||||||
|
// Exit out of Narwhal, Rhino, or RingoJS.
|
||||||
|
try {
|
||||||
|
if (failures) {
|
||||||
|
java.lang.System.exit(1);
|
||||||
|
} else {
|
||||||
|
quit();
|
||||||
|
}
|
||||||
|
} catch(e) {}
|
||||||
|
|
||||||
|
// Assign results to `global_test_results` for Sauce Labs.
|
||||||
|
details.tests = QUnit.config.extrasData.sauce.tests;
|
||||||
|
context.global_test_results = details;
|
||||||
|
});
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// Replace poisoned `raises` method.
|
||||||
|
context.raises = QUnit.raises = QUnit['throws'] || QUnit.raises;
|
||||||
|
|
||||||
|
// Add CLI extras.
|
||||||
|
if (!document) {
|
||||||
|
// Timeout fallbacks based on the work of Andrea Giammarchi and Weston C.
|
||||||
|
// See https://github.com/WebReflection/wru/blob/master/src/rhinoTimers.js
|
||||||
|
// and http://stackoverflow.com/questions/2261705/how-to-run-a-javascript-function-asynchronously-without-using-settimeout.
|
||||||
|
try {
|
||||||
|
var counter = 0,
|
||||||
|
ids = {},
|
||||||
|
slice = Array.prototype.slice,
|
||||||
|
timer = new java.util.Timer;
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
var getDescriptor = Object.getOwnPropertyDescriptor || function() {
|
||||||
|
return { 'writable': true };
|
||||||
|
};
|
||||||
|
|
||||||
|
var descriptor;
|
||||||
|
if ((!context.clearInterval || ((descriptor = getDescriptor(context, 'clearInterval')) && (descriptor.writable || descriptor.set))) &&
|
||||||
|
(!context.setInterval || ((descriptor = getDescriptor(context, 'setInterval')) && (descriptor.writable || descriptor.set)))) {
|
||||||
|
context.clearInterval = clearTimer;
|
||||||
|
context.setInterval = setInterval;
|
||||||
|
}
|
||||||
|
if ((!context.clearTimeout || ((descriptor = getDescriptor(context, 'clearTimeout')) && (descriptor.writable || descriptor.set))) &&
|
||||||
|
(!context.setTimeout || ((descriptor = getDescriptor(context, 'setTimeout')) && (descriptor.writable || descriptor.set)))) {
|
||||||
|
context.clearTimeout = clearTimer;
|
||||||
|
context.setTimeout = setTimeout;
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
} catch(e) {}
|
||||||
|
|
||||||
|
// Expose QUnit API on `context`.
|
||||||
|
// Exclude `module` because some environments have it as a built-in object.
|
||||||
|
('asyncTest deepEqual equal equals expect notDeepEqual notEqual notStrictEqual ' +
|
||||||
|
'ok raises same start stop strictEqual test throws').replace(/\S+/g, function(methodName) {
|
||||||
|
context[methodName] = QUnit[methodName];
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add `console.log` support to Narwhal, Rhino, and RingoJS.
|
||||||
|
if (!console) {
|
||||||
|
console = context.console = { 'log': function() {} };
|
||||||
|
}
|
||||||
|
// RingoJS removes ANSI escape codes in `console.log`, but not in `print`.
|
||||||
|
if (java && typeof print == 'function') {
|
||||||
|
console.log = print;
|
||||||
|
}
|
||||||
|
// Start log throbber.
|
||||||
|
if (!isSilent) {
|
||||||
|
context.setInterval(logThrobber, throbberDelay);
|
||||||
|
}
|
||||||
|
// Must call `QUnit.start` in the test file if not loaded in a browser.
|
||||||
|
QUnit.config.autostart = false;
|
||||||
|
QUnit.init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// Export QUnit Extras.
|
||||||
|
if (freeExports) {
|
||||||
|
freeExports.runInContext = runInContext;
|
||||||
|
} else {
|
||||||
|
runInContext(root);
|
||||||
|
}
|
||||||
|
}.call(this));
|
143
vendor/underscore/test/vendor/qunit.css
vendored
143
vendor/underscore/test/vendor/qunit.css
vendored
|
@ -1,11 +1,12 @@
|
||||||
/**
|
/*!
|
||||||
* QUnit v1.12.0 - A JavaScript Unit Testing Framework
|
* QUnit 1.18.0
|
||||||
|
* http://qunitjs.com/
|
||||||
*
|
*
|
||||||
* http://qunitjs.com
|
* Copyright jQuery Foundation and other contributors
|
||||||
*
|
* Released under the MIT license
|
||||||
* Copyright 2012 jQuery Foundation and other contributors
|
|
||||||
* Released under the MIT license.
|
|
||||||
* http://jquery.org/license
|
* http://jquery.org/license
|
||||||
|
*
|
||||||
|
* Date: 2015-04-03T10:23Z
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** Font Family and Sizes */
|
/** Font Family and Sizes */
|
||||||
|
@ -31,32 +32,29 @@
|
||||||
#qunit-header {
|
#qunit-header {
|
||||||
padding: 0.5em 0 0.5em 1em;
|
padding: 0.5em 0 0.5em 1em;
|
||||||
|
|
||||||
color: #8699a4;
|
color: #8699A4;
|
||||||
background-color: #0d3349;
|
background-color: #0D3349;
|
||||||
|
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
font-weight: normal;
|
font-weight: 400;
|
||||||
|
|
||||||
border-radius: 5px 5px 0 0;
|
border-radius: 5px 5px 0 0;
|
||||||
-moz-border-radius: 5px 5px 0 0;
|
|
||||||
-webkit-border-top-right-radius: 5px;
|
|
||||||
-webkit-border-top-left-radius: 5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-header a {
|
#qunit-header a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #c2ccd1;
|
color: #C2CCD1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-header a:hover,
|
#qunit-header a:hover,
|
||||||
#qunit-header a:focus {
|
#qunit-header a:focus {
|
||||||
color: #fff;
|
color: #FFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-testrunner-toolbar label {
|
#qunit-testrunner-toolbar label {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0 .5em 0 .1em;
|
padding: 0 0.5em 0 0.1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-banner {
|
#qunit-banner {
|
||||||
|
@ -64,21 +62,33 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-testrunner-toolbar {
|
#qunit-testrunner-toolbar {
|
||||||
padding: 0.5em 0 0.5em 2em;
|
padding: 0.5em 1em 0.5em 1em;
|
||||||
color: #5E740B;
|
color: #5E740B;
|
||||||
background-color: #eee;
|
background-color: #EEE;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-userAgent {
|
#qunit-userAgent {
|
||||||
padding: 0.5em 0 0.5em 2.5em;
|
padding: 0.5em 1em 0.5em 1em;
|
||||||
background-color: #2b81af;
|
background-color: #2B81AF;
|
||||||
color: #fff;
|
color: #FFF;
|
||||||
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
|
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-modulefilter-container {
|
#qunit-modulefilter-container {
|
||||||
float: right;
|
float: right;
|
||||||
|
padding: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qunit-url-config {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qunit-filter {
|
||||||
|
display: block;
|
||||||
|
float: right;
|
||||||
|
margin-left: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Tests: Pass/Fail */
|
/** Tests: Pass/Fail */
|
||||||
|
@ -88,24 +98,51 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-tests li {
|
#qunit-tests li {
|
||||||
padding: 0.4em 0.5em 0.4em 2.5em;
|
padding: 0.4em 1em 0.4em 1em;
|
||||||
border-bottom: 1px solid #fff;
|
border-bottom: 1px solid #FFF;
|
||||||
list-style-position: inside;
|
list-style-position: inside;
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
|
#qunit-tests > li {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#qunit-tests li.running,
|
||||||
|
#qunit-tests li.pass,
|
||||||
|
#qunit-tests li.fail,
|
||||||
|
#qunit-tests li.skipped {
|
||||||
|
display: list-item;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests.hidepass li.running,
|
||||||
|
#qunit-tests.hidepass li.pass {
|
||||||
|
visibility: hidden;
|
||||||
|
position: absolute;
|
||||||
|
width: 0px;
|
||||||
|
height: 0px;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
#qunit-tests li strong {
|
#qunit-tests li strong {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#qunit-tests li.skipped strong {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
#qunit-tests li a {
|
#qunit-tests li a {
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
color: #c2ccd1;
|
color: #C2CCD1;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#qunit-tests li p a {
|
||||||
|
padding: 0.25em;
|
||||||
|
color: #6B6464;
|
||||||
|
}
|
||||||
#qunit-tests li a:hover,
|
#qunit-tests li a:hover,
|
||||||
#qunit-tests li a:focus {
|
#qunit-tests li a:focus {
|
||||||
color: #000;
|
color: #000;
|
||||||
|
@ -120,11 +157,9 @@
|
||||||
margin-top: 0.5em;
|
margin-top: 0.5em;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
|
|
||||||
background-color: #fff;
|
background-color: #FFF;
|
||||||
|
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
-moz-border-radius: 5px;
|
|
||||||
-webkit-border-radius: 5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.qunit-collapsed {
|
.qunit-collapsed {
|
||||||
|
@ -133,13 +168,13 @@
|
||||||
|
|
||||||
#qunit-tests table {
|
#qunit-tests table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
margin-top: .2em;
|
margin-top: 0.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-tests th {
|
#qunit-tests th {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
padding: 0 .5em 0 0;
|
padding: 0 0.5em 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-tests td {
|
#qunit-tests td {
|
||||||
|
@ -153,26 +188,26 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-tests del {
|
#qunit-tests del {
|
||||||
background-color: #e0f2be;
|
background-color: #E0F2BE;
|
||||||
color: #374e0c;
|
color: #374E0C;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-tests ins {
|
#qunit-tests ins {
|
||||||
background-color: #ffcaca;
|
background-color: #FFCACA;
|
||||||
color: #500;
|
color: #500;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** Test Counts */
|
/*** Test Counts */
|
||||||
|
|
||||||
#qunit-tests b.counts { color: black; }
|
#qunit-tests b.counts { color: #000; }
|
||||||
#qunit-tests b.passed { color: #5E740B; }
|
#qunit-tests b.passed { color: #5E740B; }
|
||||||
#qunit-tests b.failed { color: #710909; }
|
#qunit-tests b.failed { color: #710909; }
|
||||||
|
|
||||||
#qunit-tests li li {
|
#qunit-tests li li {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
background-color: #fff;
|
background-color: #FFF;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
list-style-position: inside;
|
list-style-position: inside;
|
||||||
}
|
}
|
||||||
|
@ -180,8 +215,8 @@
|
||||||
/*** Passing Styles */
|
/*** Passing Styles */
|
||||||
|
|
||||||
#qunit-tests li li.pass {
|
#qunit-tests li li.pass {
|
||||||
color: #3c510c;
|
color: #3C510C;
|
||||||
background-color: #fff;
|
background-color: #FFF;
|
||||||
border-left: 10px solid #C6E746;
|
border-left: 10px solid #C6E746;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +224,7 @@
|
||||||
#qunit-tests .pass .test-name { color: #366097; }
|
#qunit-tests .pass .test-name { color: #366097; }
|
||||||
|
|
||||||
#qunit-tests .pass .test-actual,
|
#qunit-tests .pass .test-actual,
|
||||||
#qunit-tests .pass .test-expected { color: #999999; }
|
#qunit-tests .pass .test-expected { color: #999; }
|
||||||
|
|
||||||
#qunit-banner.qunit-pass { background-color: #C6E746; }
|
#qunit-banner.qunit-pass { background-color: #C6E746; }
|
||||||
|
|
||||||
|
@ -197,40 +232,52 @@
|
||||||
|
|
||||||
#qunit-tests li li.fail {
|
#qunit-tests li li.fail {
|
||||||
color: #710909;
|
color: #710909;
|
||||||
background-color: #fff;
|
background-color: #FFF;
|
||||||
border-left: 10px solid #EE5757;
|
border-left: 10px solid #EE5757;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-tests > li:last-child {
|
#qunit-tests > li:last-child {
|
||||||
border-radius: 0 0 5px 5px;
|
border-radius: 0 0 5px 5px;
|
||||||
-moz-border-radius: 0 0 5px 5px;
|
|
||||||
-webkit-border-bottom-right-radius: 5px;
|
|
||||||
-webkit-border-bottom-left-radius: 5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-tests .fail { color: #000000; background-color: #EE5757; }
|
#qunit-tests .fail { color: #000; background-color: #EE5757; }
|
||||||
#qunit-tests .fail .test-name,
|
#qunit-tests .fail .test-name,
|
||||||
#qunit-tests .fail .module-name { color: #000000; }
|
#qunit-tests .fail .module-name { color: #000; }
|
||||||
|
|
||||||
#qunit-tests .fail .test-actual { color: #EE5757; }
|
#qunit-tests .fail .test-actual { color: #EE5757; }
|
||||||
#qunit-tests .fail .test-expected { color: green; }
|
#qunit-tests .fail .test-expected { color: #008000; }
|
||||||
|
|
||||||
#qunit-banner.qunit-fail { background-color: #EE5757; }
|
#qunit-banner.qunit-fail { background-color: #EE5757; }
|
||||||
|
|
||||||
|
/*** Skipped tests */
|
||||||
|
|
||||||
|
#qunit-tests .skipped {
|
||||||
|
background-color: #EBECE9;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests .qunit-skipped-label {
|
||||||
|
background-color: #F4FF77;
|
||||||
|
display: inline-block;
|
||||||
|
font-style: normal;
|
||||||
|
color: #366097;
|
||||||
|
line-height: 1.8em;
|
||||||
|
padding: 0 0.5em;
|
||||||
|
margin: -0.4em 0.4em -0.4em 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** Result */
|
/** Result */
|
||||||
|
|
||||||
#qunit-testresult {
|
#qunit-testresult {
|
||||||
padding: 0.5em 0.5em 0.5em 2.5em;
|
padding: 0.5em 1em 0.5em 1em;
|
||||||
|
|
||||||
color: #2b81af;
|
color: #2B81AF;
|
||||||
background-color: #D2E0E6;
|
background-color: #D2E0E6;
|
||||||
|
|
||||||
border-bottom: 1px solid white;
|
border-bottom: 1px solid #FFF;
|
||||||
}
|
}
|
||||||
#qunit-testresult .module-name {
|
#qunit-testresult .module-name {
|
||||||
font-weight: bold;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Fixture */
|
/** Fixture */
|
||||||
|
|
4508
vendor/underscore/test/vendor/qunit.js
vendored
4508
vendor/underscore/test/vendor/qunit.js
vendored
File diff suppressed because it is too large
Load diff
127
vendor/underscore/test/vendor/runner.js
vendored
127
vendor/underscore/test/vendor/runner.js
vendored
|
@ -1,127 +0,0 @@
|
||||||
/*
|
|
||||||
* QtWebKit-powered headless test runner using PhantomJS
|
|
||||||
*
|
|
||||||
* PhantomJS binaries: http://phantomjs.org/download.html
|
|
||||||
* Requires PhantomJS 1.6+ (1.7+ recommended)
|
|
||||||
*
|
|
||||||
* Run with:
|
|
||||||
* phantomjs runner.js [url-of-your-qunit-testsuite]
|
|
||||||
*
|
|
||||||
* e.g.
|
|
||||||
* phantomjs runner.js http://localhost/qunit/test/index.html
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*jshint latedef:false */
|
|
||||||
/*global phantom:false, require:false, console:false, window:false, QUnit:false */
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var args = require('system').args;
|
|
||||||
|
|
||||||
// arg[0]: scriptName, args[1...]: arguments
|
|
||||||
if (args.length !== 2) {
|
|
||||||
console.error('Usage:\n phantomjs runner.js [url-of-your-qunit-testsuite]');
|
|
||||||
phantom.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
var url = args[1],
|
|
||||||
page = require('webpage').create();
|
|
||||||
|
|
||||||
// Route `console.log()` calls from within the Page context to the main Phantom context (i.e. current `this`)
|
|
||||||
page.onConsoleMessage = function(msg) {
|
|
||||||
console.log(msg);
|
|
||||||
};
|
|
||||||
|
|
||||||
page.onInitialized = function() {
|
|
||||||
page.evaluate(addLogging);
|
|
||||||
};
|
|
||||||
|
|
||||||
page.onCallback = function(message) {
|
|
||||||
var result,
|
|
||||||
failed;
|
|
||||||
|
|
||||||
if (message) {
|
|
||||||
if (message.name === 'QUnit.done') {
|
|
||||||
result = message.data;
|
|
||||||
failed = !result || result.failed;
|
|
||||||
|
|
||||||
phantom.exit(failed ? 1 : 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
page.open(url, function(status) {
|
|
||||||
if (status !== 'success') {
|
|
||||||
console.error('Unable to access network: ' + status);
|
|
||||||
phantom.exit(1);
|
|
||||||
} else {
|
|
||||||
// Cannot do this verification with the 'DOMContentLoaded' handler because it
|
|
||||||
// will be too late to attach it if a page does not have any script tags.
|
|
||||||
var qunitMissing = page.evaluate(function() { return (typeof QUnit === 'undefined' || !QUnit); });
|
|
||||||
if (qunitMissing) {
|
|
||||||
console.error('The `QUnit` object is not present on this page.');
|
|
||||||
phantom.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do nothing... the callback mechanism will handle everything!
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function addLogging() {
|
|
||||||
window.document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
var current_test_assertions = [];
|
|
||||||
|
|
||||||
QUnit.log(function(details) {
|
|
||||||
var response;
|
|
||||||
|
|
||||||
// Ignore passing assertions
|
|
||||||
if (details.result) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
response = details.message || '';
|
|
||||||
|
|
||||||
if (typeof details.expected !== 'undefined') {
|
|
||||||
if (response) {
|
|
||||||
response += ', ';
|
|
||||||
}
|
|
||||||
|
|
||||||
response += 'expected: ' + details.expected + ', but was: ' + details.actual;
|
|
||||||
if (details.source) {
|
|
||||||
response += "\n" + details.source;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
current_test_assertions.push('Failed assertion: ' + response);
|
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.testDone(function(result) {
|
|
||||||
var i,
|
|
||||||
len,
|
|
||||||
name = result.module + ': ' + result.name;
|
|
||||||
|
|
||||||
if (result.failed) {
|
|
||||||
console.log('Test failed: ' + name);
|
|
||||||
|
|
||||||
for (i = 0, len = current_test_assertions.length; i < len; i++) {
|
|
||||||
console.log(' ' + current_test_assertions[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
current_test_assertions.length = 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.done(function(result) {
|
|
||||||
console.log('Took ' + result.runtime + 'ms to run ' + result.total + ' tests. ' + result.passed + ' passed, ' + result.failed + ' failed.');
|
|
||||||
|
|
||||||
if (typeof window.callPhantom === 'function') {
|
|
||||||
window.callPhantom({
|
|
||||||
'name': 'QUnit.done',
|
|
||||||
'data': result
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, false);
|
|
||||||
}
|
|
||||||
})();
|
|
6
vendor/underscore/underscore-min.js
vendored
6
vendor/underscore/underscore-min.js
vendored
File diff suppressed because one or more lines are too long
2
vendor/underscore/underscore-min.map
vendored
2
vendor/underscore/underscore-min.map
vendored
File diff suppressed because one or more lines are too long
1663
vendor/underscore/underscore.js
vendored
1663
vendor/underscore/underscore.js
vendored
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue