Update for underscore 1.8.3.
This commit is contained in:
parent
7c3686a5b3
commit
96712db8cb
|
@ -547,7 +547,7 @@ define([
|
|||
'<% _.each(items, function(item) { %>',
|
||||
'<li id="<%= item.id %>" data-value="<%= item.value %>"><a tabindex="-1" type="menuitem"><%= scope.getDisplayValue(item) %></a></li>',
|
||||
'<% }); %>'
|
||||
].join(''), {
|
||||
].join(''))({
|
||||
items: this.store.toJSON(),
|
||||
scope: this
|
||||
}));
|
||||
|
|
|
@ -353,7 +353,7 @@ define([
|
|||
'<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;"/>',
|
||||
'</li>'
|
||||
].join(''), {
|
||||
].join(''))({
|
||||
item: item.attributes,
|
||||
scope: this
|
||||
}));
|
||||
|
|
|
@ -421,7 +421,7 @@ define([
|
|||
_.extend(options, {
|
||||
cls: 'alert',
|
||||
onprimary: onKeyDown,
|
||||
tpl: _.template(template, options)
|
||||
tpl: _.template(template)(options)
|
||||
});
|
||||
|
||||
var win = new Common.UI.Window(options),
|
||||
|
@ -556,7 +556,7 @@ define([
|
|||
render : function() {
|
||||
var renderto = this.initConfig.renderTo || document.body;
|
||||
$(renderto).append(
|
||||
_.template(template, this.initConfig)
|
||||
_.template(template)(this.initConfig)
|
||||
);
|
||||
|
||||
this.$window = $('#' + this.initConfig.id);
|
||||
|
|
|
@ -71,7 +71,7 @@ define([
|
|||
'</div>'
|
||||
].join('');
|
||||
|
||||
_options.tpl = _.template(this.template, _options);
|
||||
_options.tpl = _.template(this.template)(_options);
|
||||
|
||||
this.handler = _options.handler;
|
||||
this.toggleGroup = _options.toggleGroup;
|
||||
|
|
|
@ -67,7 +67,7 @@ define([
|
|||
|
||||
templateUserList: _.template('<ul>' +
|
||||
'<% _.each(users, function(item) { %>' +
|
||||
'<%= _.template(usertpl, {user: item, scope: scope}) %>' +
|
||||
'<%= _.template(usertpl)({user: item, scope: scope}) %>' +
|
||||
'<% }); %>' +
|
||||
'</ul>'),
|
||||
|
||||
|
@ -82,7 +82,7 @@ define([
|
|||
|
||||
templateMsgList: _.template('<ul>' +
|
||||
'<% _.each(messages, function(item) { %>' +
|
||||
'<%= _.template(msgtpl, {msg: item, scope: scope}) %>' +
|
||||
'<%= _.template(msgtpl)({msg: item, scope: scope}) %>' +
|
||||
'<% }); %>' +
|
||||
'</ul>'),
|
||||
|
||||
|
@ -162,7 +162,7 @@ define([
|
|||
|
||||
_onAddUser: function(m, c, opts) {
|
||||
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});
|
||||
}
|
||||
},
|
||||
|
@ -186,7 +186,7 @@ define([
|
|||
var content = this.panelMessages.find('ul');
|
||||
if (content && content.length) {
|
||||
this._prepareMessage(m);
|
||||
content.append(_.template(this.tplMsg, {msg: m, scope: this}));
|
||||
content.append(_.template(this.tplMsg)({msg: m, scope: this}));
|
||||
|
||||
// scroll to end
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ define([
|
|||
this.store = options.store;
|
||||
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.sdkBounds = {width: 0, height: 0, padding: 10, paddingTop: 20};
|
||||
|
|
|
@ -83,7 +83,7 @@ define([
|
|||
'</div>'
|
||||
].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);
|
||||
},
|
||||
|
|
|
@ -57,7 +57,7 @@ define([
|
|||
'<div id="id-sharing-placeholder"></div>'
|
||||
].join('');
|
||||
|
||||
_options.tpl = _.template(this.template, _options);
|
||||
_options.tpl = _.template(this.template)(_options);
|
||||
|
||||
this.settingsurl = options.settingsurl || '';
|
||||
Common.UI.Window.prototype.initialize.call(this, _options);
|
||||
|
|
|
@ -66,7 +66,7 @@ define([
|
|||
'</div>'
|
||||
].join('');
|
||||
|
||||
_options.tpl = _.template(this.template, _options);
|
||||
_options.tpl = _.template(this.template)(_options);
|
||||
|
||||
this.handler = _options.handler;
|
||||
this._chartData = null;
|
||||
|
|
|
@ -66,7 +66,7 @@ define([
|
|||
'</div>'
|
||||
].join('');
|
||||
|
||||
_options.tpl = _.template(this.template, _options);
|
||||
_options.tpl = _.template(this.template)(_options);
|
||||
|
||||
this.handler = _options.handler;
|
||||
this._mergeData = null;
|
||||
|
|
|
@ -65,7 +65,7 @@ define([
|
|||
'</div>'
|
||||
].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);
|
||||
},
|
||||
|
|
|
@ -73,7 +73,7 @@ define([
|
|||
'</div>'
|
||||
].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);
|
||||
},
|
||||
|
|
|
@ -93,7 +93,7 @@ define([
|
|||
this.codepages = options.codepages;
|
||||
this.settings = options.settings;
|
||||
|
||||
_options.tpl = _.template(this.template, _options);
|
||||
_options.tpl = _.template(this.template)(_options);
|
||||
|
||||
Common.UI.Window.prototype.initialize.call(this, _options);
|
||||
},
|
||||
|
|
|
@ -314,7 +314,7 @@ define([
|
|||
'<% } %>'
|
||||
].join('');
|
||||
|
||||
_options.tpl = _.template(this.template, _options);
|
||||
_options.tpl = _.template(this.template)(_options);
|
||||
|
||||
this.url = options.url || '';
|
||||
Common.UI.Window.prototype.initialize.call(this, _options);
|
||||
|
|
|
@ -66,7 +66,7 @@ define([
|
|||
'</div>'
|
||||
].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);
|
||||
},
|
||||
|
|
|
@ -80,7 +80,7 @@ define([
|
|||
this.store = options.store;
|
||||
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.sdkBounds = {width: 0, height: 0, padding: 10, paddingTop: 20};
|
||||
|
@ -616,7 +616,7 @@ define([
|
|||
},
|
||||
|
||||
getPanel: function () {
|
||||
this.$el = $(_.template( template, {} ));
|
||||
this.$el = $(_.template(template)( {} ));
|
||||
|
||||
if ( this.appConfig.canReview ) {
|
||||
this.btnPrev.render(this.$el.find('#btn-change-prev'));
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
'</div>'
|
||||
].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);
|
||||
},
|
||||
|
|
|
@ -81,7 +81,7 @@ define([
|
|||
'</div>'
|
||||
].join('');
|
||||
|
||||
this.options.tpl = _.template(this.template, this.options);
|
||||
this.options.tpl = _.template(this.template)(this.options);
|
||||
this.api = this.options.api;
|
||||
|
||||
Common.UI.Window.prototype.initialize.call(this, this.options);
|
||||
|
|
|
@ -54,7 +54,7 @@ define([
|
|||
'<div id="id-mail-recepients-placeholder"></div>'
|
||||
].join('');
|
||||
|
||||
_options.tpl = _.template(this.template, _options);
|
||||
_options.tpl = _.template(this.template)(_options);
|
||||
|
||||
this.fileChoiceUrl = options.fileChoiceUrl || '';
|
||||
Common.UI.Window.prototype.initialize.call(this, _options);
|
||||
|
|
|
@ -55,7 +55,7 @@ define([
|
|||
'<div id="id-mail-merge-folder-placeholder"></div>'
|
||||
].join('');
|
||||
|
||||
_options.tpl = _.template(this.template, _options);
|
||||
_options.tpl = _.template(this.template)(_options);
|
||||
|
||||
this.mergeFolderUrl = options.mergeFolderUrl || '';
|
||||
this.mergedFileUrl = options.mergedFileUrl || '';
|
||||
|
|
|
@ -89,7 +89,7 @@ define([
|
|||
'</div>'
|
||||
].join('');
|
||||
|
||||
this.options.tpl = _.template(this.template, this.options);
|
||||
this.options.tpl = _.template(this.template)(this.options);
|
||||
|
||||
this.spinners = [];
|
||||
this._noApply = false;
|
||||
|
|
|
@ -79,7 +79,7 @@ define([
|
|||
'</div>'
|
||||
].join('');
|
||||
|
||||
this.options.tpl = _.template(this.template, this.options);
|
||||
this.options.tpl = _.template(this.template)(this.options);
|
||||
|
||||
this.spinners = [];
|
||||
this._noApply = false;
|
||||
|
|
|
@ -430,7 +430,7 @@ define([
|
|||
label: this.labelSelect,
|
||||
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);
|
||||
},
|
||||
|
|
|
@ -70,7 +70,7 @@ define([
|
|||
'</div>'
|
||||
].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);
|
||||
},
|
||||
|
|
|
@ -195,7 +195,7 @@ define([
|
|||
{ caption: me.textTabHome, action: 'home', extcls: 'canedit'},
|
||||
{ caption: me.textTabInsert, action: 'ins', extcls: 'canedit'},
|
||||
{ caption: me.textTabLayout, action: 'layout', extcls: 'canedit'} ];
|
||||
config.$dom = $(_.template(template, config));
|
||||
config.$dom = $(_.template(template)(config));
|
||||
|
||||
/**
|
||||
* UI Components
|
||||
|
@ -2476,7 +2476,7 @@ define([
|
|||
var _elements = $tabs || config.$dom.find('.tabs');
|
||||
var $target = _elements.find('a[data-tab=' + _after_action + ']');
|
||||
if ( $target.length ) {
|
||||
$target.parent().after( _.template(_tplTab, tab) );
|
||||
$target.parent().after( _.template(_tplTab)(tab) );
|
||||
|
||||
if ( panel ) {
|
||||
_elements = $panels || config.$dom.find('.box-panels > .panel');
|
||||
|
|
|
@ -175,7 +175,7 @@ define([
|
|||
'</div>',
|
||||
'</label>',
|
||||
'</li>'
|
||||
].join(''), {
|
||||
].join(''))({
|
||||
android: Framework7.prototype.device.android,
|
||||
item: size,
|
||||
index: index,
|
||||
|
|
|
@ -203,7 +203,7 @@ define([
|
|||
'<% }); %>',
|
||||
'</ul>',
|
||||
'<% }); %>'
|
||||
].join(''), {
|
||||
].join(''))({
|
||||
styles: styles
|
||||
});
|
||||
|
||||
|
|
|
@ -138,7 +138,7 @@ define([
|
|||
'</div>',
|
||||
'<% }); %>',
|
||||
'</div>'
|
||||
].join(''), {
|
||||
].join(''))({
|
||||
styles: styles
|
||||
});
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ define([
|
|||
render: function () {
|
||||
var el = $(this.el),
|
||||
me = this;
|
||||
el.html(_.template(this.template, {
|
||||
el.html(_.template(this.template)({
|
||||
scope: this
|
||||
}));
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ define([
|
|||
'</div>'
|
||||
].join('');
|
||||
|
||||
this.options.tpl = _.template(this.template, this.options);
|
||||
this.options.tpl = _.template(this.template)(this.options);
|
||||
this.slides = this.options.slides;
|
||||
this.api = this.options.api;
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ define([
|
|||
'</div>'
|
||||
].join('');
|
||||
|
||||
this.options.tpl = _.template(this.template, this.options);
|
||||
this.options.tpl = _.template(this.template)(this.options);
|
||||
|
||||
this.spinners = [];
|
||||
this._noApply = false;
|
||||
|
|
|
@ -68,7 +68,7 @@ define([
|
|||
'</div>'
|
||||
].join('');
|
||||
|
||||
this.options.tpl = _.template(this.template, this.options);
|
||||
this.options.tpl = _.template(this.template)(this.options);
|
||||
|
||||
this.spinners = [];
|
||||
this._noApply = false;
|
||||
|
|
|
@ -251,7 +251,7 @@ define([
|
|||
{ caption: 'Home', action: 'home', extcls: 'canedit'},
|
||||
{ caption: 'Insert', action: 'ins', extcls: 'canedit'} ];
|
||||
|
||||
config.$layout = $(_.template(template, config));
|
||||
config.$layout = $(_.template(template)(config));
|
||||
|
||||
me.paragraphControls = [];
|
||||
me.shapeControls = [];
|
||||
|
@ -1795,7 +1795,7 @@ define([
|
|||
var _elements = $tabs || config.$layout.find('.tabs');
|
||||
var $target = _elements.find('a[data-tab=' + _after_action + ']');
|
||||
if ( $target.length ) {
|
||||
$target.parent().after( _.template(_tplTab, tab) );
|
||||
$target.parent().after( _.template(_tplTab)(tab) );
|
||||
|
||||
if ( panel ) {
|
||||
_elements = $panels || config.$layout.find('.box-panels > .panel');
|
||||
|
|
|
@ -123,7 +123,7 @@ define([
|
|||
'<% }); %>',
|
||||
'</ul>',
|
||||
'<% }); %>'
|
||||
].join(''), {
|
||||
].join(''))({
|
||||
layouts: layouts
|
||||
});
|
||||
|
||||
|
|
|
@ -203,7 +203,7 @@ define([
|
|||
'<% }); %>',
|
||||
'</ul>',
|
||||
'<% }); %>'
|
||||
].join(''), {
|
||||
].join(''))({
|
||||
styles: styles
|
||||
});
|
||||
|
||||
|
|
|
@ -235,7 +235,7 @@ define([
|
|||
'<% }); %>',
|
||||
'</ul>',
|
||||
'<% }); %>'
|
||||
].join(''), {
|
||||
].join(''))({
|
||||
layouts: layouts
|
||||
});
|
||||
|
||||
|
@ -268,7 +268,7 @@ define([
|
|||
'<% }); %>',
|
||||
'</div>',
|
||||
'<% }); %>'
|
||||
].join(''), {
|
||||
].join(''))({
|
||||
themes: themes
|
||||
});
|
||||
|
||||
|
@ -291,7 +291,7 @@ define([
|
|||
'</label>',
|
||||
'</li>',
|
||||
'<% }); %>'
|
||||
].join(''), {
|
||||
].join(''))({
|
||||
android : Common.SharedSettings.get('android'),
|
||||
types: _arrCurrentEffectTypes
|
||||
});
|
||||
|
|
|
@ -138,7 +138,7 @@ define([
|
|||
'</div>',
|
||||
'<% }); %>',
|
||||
'</div>'
|
||||
].join(''), {
|
||||
].join(''))({
|
||||
styles: styles
|
||||
});
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ define([
|
|||
this.handler = options.handler;
|
||||
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);
|
||||
},
|
||||
|
@ -342,7 +342,7 @@ define([
|
|||
this.api = options.api;
|
||||
this.handler = options.handler;
|
||||
|
||||
_options.tpl = _.template(this.template, _options);
|
||||
_options.tpl = _.template(this.template)(_options);
|
||||
|
||||
Common.UI.Window.prototype.initialize.call(this, _options);
|
||||
},
|
||||
|
@ -516,7 +516,7 @@ define([
|
|||
this.throughIndexes = [];
|
||||
this.filteredIndexes = [];
|
||||
|
||||
_options.tpl = _.template(this.template, _options);
|
||||
_options.tpl = _.template(this.template)(_options);
|
||||
|
||||
Common.UI.Window.prototype.initialize.call(this, _options);
|
||||
},
|
||||
|
|
|
@ -69,7 +69,7 @@ define([
|
|||
'</div>'
|
||||
].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);
|
||||
},
|
||||
|
|
|
@ -92,7 +92,7 @@ define([
|
|||
this.formulasGroups = options.formulasGroups;
|
||||
this.handler = options.handler;
|
||||
|
||||
_options.tpl = _.template(this.template, _options);
|
||||
_options.tpl = _.template(this.template)(_options);
|
||||
|
||||
Common.UI.Window.prototype.initialize.call(this, _options);
|
||||
},
|
||||
|
|
|
@ -99,7 +99,7 @@ define([
|
|||
'</div>'
|
||||
].join('');
|
||||
|
||||
this.options.tpl = _.template(this.template, this.options);
|
||||
this.options.tpl = _.template(this.template)(this.options);
|
||||
this.api = this.options.api;
|
||||
|
||||
Common.UI.Window.prototype.initialize.call(this, this.options);
|
||||
|
|
|
@ -67,7 +67,7 @@ define([
|
|||
'</div>'
|
||||
].join('');
|
||||
|
||||
this.options.tpl = _.template(this.template, this.options);
|
||||
this.options.tpl = _.template(this.template)(this.options);
|
||||
this.startvalue = this.options.startvalue;
|
||||
this.maxvalue = this.options.maxvalue;
|
||||
this.defaultUnit = this.options.defaultUnit;
|
||||
|
|
|
@ -68,7 +68,7 @@ define([
|
|||
|
||||
templateUserList: _.template('<ul>' +
|
||||
'<% _.each(users, function(item) { %>' +
|
||||
'<%= _.template(usertpl, {user: item, scope: scope}) %>' +
|
||||
'<%= _.template(usertpl)({user: item, scope: scope}) %>' +
|
||||
'<% }); %>' +
|
||||
'</ul>'),
|
||||
|
||||
|
@ -489,7 +489,7 @@ define([
|
|||
|
||||
_onAddUser: function(m, c, opts) {
|
||||
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});
|
||||
}
|
||||
},
|
||||
|
@ -706,7 +706,7 @@ define([
|
|||
label: this.labelSheetName,
|
||||
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);
|
||||
},
|
||||
|
@ -823,7 +823,7 @@ define([
|
|||
label: options.ismove ? this.textMoveBefore : this.textCopyBefore,
|
||||
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);
|
||||
},
|
||||
|
|
|
@ -72,7 +72,7 @@ define([
|
|||
'</div>'
|
||||
].join('');
|
||||
|
||||
this.options.tpl = _.template(this.template, this.options);
|
||||
this.options.tpl = _.template(this.template)(this.options);
|
||||
this.checkRangeType = Asc.c_oAscSelectionDialogType.FormatTable;
|
||||
this.selectionType = Asc.c_oAscSelectionType.RangeCells;
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ define([
|
|||
};
|
||||
|
||||
_.extend(_params, args);
|
||||
var $content = $('<div/>').append(_.template(this.template, _params));
|
||||
var $content = $('<div/>').append(_.template(this.template)(_params));
|
||||
|
||||
// Android fix for navigation
|
||||
if (Framework7.prototype.device.android) {
|
||||
|
@ -121,7 +121,7 @@ define([
|
|||
'Logical': me.sCatLogical
|
||||
};
|
||||
|
||||
me.layout = $('<div/>').append(_.template(me.template, {
|
||||
me.layout = $('<div/>').append(_.template(me.template)({
|
||||
android : Common.SharedSettings.get('android'),
|
||||
phone : Common.SharedSettings.get('phone'),
|
||||
textGroups : me.textGroups,
|
||||
|
|
|
@ -210,7 +210,7 @@ define([
|
|||
'<% }) %>';
|
||||
|
||||
this.layout.find('#add-link-sheet select').html(
|
||||
_.template(tpl, {
|
||||
_.template(tpl)({
|
||||
worksheets: sheets
|
||||
})
|
||||
);
|
||||
|
@ -219,7 +219,7 @@ define([
|
|||
|
||||
if ($view.length > 0) {
|
||||
$view.find('#add-link-sheet select').html(
|
||||
_.template(tpl, {
|
||||
_.template(tpl)({
|
||||
worksheets: sheets
|
||||
})
|
||||
);
|
||||
|
|
|
@ -76,8 +76,7 @@ define([
|
|||
}
|
||||
|
||||
mapNavigation =
|
||||
el = _.template(tplNavigation,
|
||||
{
|
||||
el = _.template(tplNavigation)({
|
||||
android : Common.SharedSettings.get('android'),
|
||||
phone : Common.SharedSettings.get('phone'),
|
||||
textBack : this.textBack,
|
||||
|
|
|
@ -133,7 +133,7 @@ define([
|
|||
'<% }); %>',
|
||||
'</ul>',
|
||||
'<% }); %>'
|
||||
].join(''), {
|
||||
].join(''))({
|
||||
styles: styles,
|
||||
styleSize: styleSize
|
||||
});
|
||||
|
|
|
@ -160,7 +160,7 @@ define([
|
|||
'<% }); %>',
|
||||
'</ul>',
|
||||
'<% }); %>'
|
||||
].join(''), {
|
||||
].join(''))({
|
||||
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
|
||||
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
|
||||
sudo: false
|
||||
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:
|
||||
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
|
||||
|
||||
* 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.
|
||||
|
||||
* 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/).
|
||||
|
||||
* 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
|
||||
|
||||
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...)
|
||||
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:
|
||||
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:
|
||||
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-family: 'novecento-bold';
|
||||
src: url('public/fonts/novecento-bold.eot');
|
||||
src: url('public/fonts/novecento-bold.eot?#iefix') format('embedded-opentype'),
|
||||
url('public/fonts/novecento-bold.woff') format('woff'),
|
||||
url('public/fonts/novecento-bold.ttf') format('truetype');
|
||||
font-family: 'roboto-black';
|
||||
src: url('public/fonts/roboto-black.eot');
|
||||
src: url('public/fonts/roboto-black.eot?#iefix') format('embedded-opentype'),
|
||||
url('public/fonts/roboto-black.woff') format('woff'),
|
||||
url('public/fonts/roboto-black.ttf') format('truetype');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
@ -51,15 +51,23 @@ b, strong {
|
|||
font-family: "aller-bold";
|
||||
}
|
||||
|
||||
p, ul, ol {
|
||||
p {
|
||||
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 {
|
||||
color: #112233;
|
||||
line-height: 1em;
|
||||
font-weight: normal;
|
||||
font-family: "novecento-bold";
|
||||
font-family: "roboto-black";
|
||||
text-transform: uppercase;
|
||||
margin: 30px 0 15px 0;
|
||||
}
|
||||
|
@ -67,10 +75,13 @@ h1, h2, h3, h4, h5, h6 {
|
|||
h1 {
|
||||
margin-top: 40px;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.26em;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
background: 1px solid #ddd;
|
||||
background: 1px #ddd;
|
||||
height: 1px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
@ -172,9 +183,18 @@ ul.sections > li > div {
|
|||
display: block;
|
||||
}
|
||||
|
||||
#jump_page_wrapper{
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
#jump_page {
|
||||
padding: 5px 0 3px;
|
||||
margin: 0 0 25px 25px;
|
||||
max-height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#jump_page .source {
|
||||
|
@ -205,7 +225,6 @@ ul.sections > li > div {
|
|||
}
|
||||
|
||||
ul.sections > li > div.content {
|
||||
background: #f5f5ff;
|
||||
overflow-x:auto;
|
||||
-webkit-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 {
|
||||
padding: 13px;
|
||||
vertical-align: top;
|
||||
background: #f5f5ff;
|
||||
border: none;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
|
@ -376,125 +394,125 @@ pre code {
|
|||
background: #f8f8ff
|
||||
}
|
||||
|
||||
pre .comment,
|
||||
pre .template_comment,
|
||||
pre .diff .header,
|
||||
pre .javadoc {
|
||||
pre .hljs-comment,
|
||||
pre .hljs-template_comment,
|
||||
pre .hljs-diff .hljs-header,
|
||||
pre .hljs-javadoc {
|
||||
color: #408080;
|
||||
font-style: italic
|
||||
}
|
||||
|
||||
pre .keyword,
|
||||
pre .assignment,
|
||||
pre .literal,
|
||||
pre .css .rule .keyword,
|
||||
pre .winutils,
|
||||
pre .javascript .title,
|
||||
pre .lisp .title,
|
||||
pre .subst {
|
||||
pre .hljs-keyword,
|
||||
pre .hljs-assignment,
|
||||
pre .hljs-literal,
|
||||
pre .hljs-css .hljs-rule .hljs-keyword,
|
||||
pre .hljs-winutils,
|
||||
pre .hljs-javascript .hljs-title,
|
||||
pre .hljs-lisp .hljs-title,
|
||||
pre .hljs-subst {
|
||||
color: #954121;
|
||||
/*font-weight: bold*/
|
||||
}
|
||||
|
||||
pre .number,
|
||||
pre .hexcolor {
|
||||
pre .hljs-number,
|
||||
pre .hljs-hexcolor {
|
||||
color: #40a070
|
||||
}
|
||||
|
||||
pre .string,
|
||||
pre .tag .value,
|
||||
pre .phpdoc,
|
||||
pre .tex .formula {
|
||||
pre .hljs-string,
|
||||
pre .hljs-tag .hljs-value,
|
||||
pre .hljs-phpdoc,
|
||||
pre .hljs-tex .hljs-formula {
|
||||
color: #219161;
|
||||
}
|
||||
|
||||
pre .title,
|
||||
pre .id {
|
||||
pre .hljs-title,
|
||||
pre .hljs-id {
|
||||
color: #19469D;
|
||||
}
|
||||
pre .params {
|
||||
pre .hljs-params {
|
||||
color: #00F;
|
||||
}
|
||||
|
||||
pre .javascript .title,
|
||||
pre .lisp .title,
|
||||
pre .subst {
|
||||
pre .hljs-javascript .hljs-title,
|
||||
pre .hljs-lisp .hljs-title,
|
||||
pre .hljs-subst {
|
||||
font-weight: normal
|
||||
}
|
||||
|
||||
pre .class .title,
|
||||
pre .haskell .label,
|
||||
pre .tex .command {
|
||||
pre .hljs-class .hljs-title,
|
||||
pre .hljs-haskell .hljs-label,
|
||||
pre .hljs-tex .hljs-command {
|
||||
color: #458;
|
||||
font-weight: bold
|
||||
}
|
||||
|
||||
pre .tag,
|
||||
pre .tag .title,
|
||||
pre .rules .property,
|
||||
pre .django .tag .keyword {
|
||||
pre .hljs-tag,
|
||||
pre .hljs-tag .hljs-title,
|
||||
pre .hljs-rules .hljs-property,
|
||||
pre .hljs-django .hljs-tag .hljs-keyword {
|
||||
color: #000080;
|
||||
font-weight: normal
|
||||
}
|
||||
|
||||
pre .attribute,
|
||||
pre .variable,
|
||||
pre .instancevar,
|
||||
pre .lisp .body {
|
||||
pre .hljs-attribute,
|
||||
pre .hljs-variable,
|
||||
pre .hljs-instancevar,
|
||||
pre .hljs-lisp .hljs-body {
|
||||
color: #008080
|
||||
}
|
||||
|
||||
pre .regexp {
|
||||
pre .hljs-regexp {
|
||||
color: #B68
|
||||
}
|
||||
|
||||
pre .class {
|
||||
pre .hljs-class {
|
||||
color: #458;
|
||||
font-weight: bold
|
||||
}
|
||||
|
||||
pre .symbol,
|
||||
pre .ruby .symbol .string,
|
||||
pre .ruby .symbol .keyword,
|
||||
pre .ruby .symbol .keymethods,
|
||||
pre .lisp .keyword,
|
||||
pre .tex .special,
|
||||
pre .input_number {
|
||||
pre .hljs-symbol,
|
||||
pre .hljs-ruby .hljs-symbol .hljs-string,
|
||||
pre .hljs-ruby .hljs-symbol .hljs-keyword,
|
||||
pre .hljs-ruby .hljs-symbol .hljs-keymethods,
|
||||
pre .hljs-lisp .hljs-keyword,
|
||||
pre .hljs-tex .hljs-special,
|
||||
pre .hljs-input_number {
|
||||
color: #990073
|
||||
}
|
||||
|
||||
pre .builtin,
|
||||
pre .constructor,
|
||||
pre .built_in,
|
||||
pre .lisp .title {
|
||||
pre .hljs-builtin,
|
||||
pre .hljs-constructor,
|
||||
pre .hljs-built_in,
|
||||
pre .hljs-lisp .hljs-title {
|
||||
color: #0086b3
|
||||
}
|
||||
|
||||
pre .preprocessor,
|
||||
pre .pi,
|
||||
pre .doctype,
|
||||
pre .shebang,
|
||||
pre .cdata {
|
||||
pre .hljs-preprocessor,
|
||||
pre .hljs-pi,
|
||||
pre .hljs-doctype,
|
||||
pre .hljs-shebang,
|
||||
pre .hljs-cdata {
|
||||
color: #999;
|
||||
font-weight: bold
|
||||
}
|
||||
|
||||
pre .deletion {
|
||||
pre .hljs-deletion {
|
||||
background: #fdd
|
||||
}
|
||||
|
||||
pre .addition {
|
||||
pre .hljs-addition {
|
||||
background: #dfd
|
||||
}
|
||||
|
||||
pre .diff .change {
|
||||
pre .hljs-diff .hljs-change {
|
||||
background: #0086b3
|
||||
}
|
||||
|
||||
pre .chunk {
|
||||
pre .hljs-chunk {
|
||||
color: #aaa
|
||||
}
|
||||
|
||||
pre .tex .formula {
|
||||
pre .hljs-tex .hljs-formula {
|
||||
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",
|
||||
"description" : "JavaScript's functional programming helper library.",
|
||||
"homepage" : "http://underscorejs.org",
|
||||
"keywords" : ["util", "functional", "server", "client", "browser"],
|
||||
"author" : "Jeremy Ashkenas <jeremy@documentcloud.org>",
|
||||
"repository" : {"type": "git", "url": "git://github.com/jashkenas/underscore.git"},
|
||||
"main" : "underscore.js",
|
||||
"version" : "1.5.2",
|
||||
"name": "underscore",
|
||||
"description": "JavaScript's functional programming helper library.",
|
||||
"homepage": "http://underscorejs.org",
|
||||
"keywords": [
|
||||
"util",
|
||||
"functional",
|
||||
"server",
|
||||
"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": {
|
||||
"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": {
|
||||
"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": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "https://raw.github.com/jashkenas/underscore/master/LICENSE"
|
||||
}
|
||||
],
|
||||
"files" : ["underscore.js", "underscore-min.js", "LICENSE"]
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"underscore.js",
|
||||
"underscore-min.js",
|
||||
"underscore-min.map"
|
||||
]
|
||||
}
|
||||
|
|
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() {
|
||||
equal(_.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()"');
|
||||
equal(_.first([1,2,3], 0).join(', '), "", 'can pass an index to first');
|
||||
equal(_.first([1,2,3], 2).join(', '), '1, 2', 'can pass an index to first');
|
||||
equal(_.first([1,2,3], 5).join(', '), '1, 2, 3', 'can pass an index to first');
|
||||
var result = (function(){ return _.first(arguments); })(4, 3, 2, 1);
|
||||
equal(result, 4, 'works on an arguments object.');
|
||||
result = _.map([[1,2,3],[1,2,3]], _.first);
|
||||
equal(result.join(','), '1,1', 'works well with _.map');
|
||||
result = (function() { return _.take([1,2,3], 2); })();
|
||||
equal(result.join(','), '1,2', 'aliased as take');
|
||||
QUnit.test('first', function(assert) {
|
||||
assert.strictEqual(_.first([1, 2, 3]), 1, 'can pull out the first element of an array');
|
||||
assert.strictEqual(_([1, 2, 3]).first(), 1, 'can perform OO-style "first()"');
|
||||
assert.deepEqual(_.first([1, 2, 3], 0), [], 'returns an empty array when n <= 0 (0 case)');
|
||||
assert.deepEqual(_.first([1, 2, 3], -1), [], 'returns an empty array when n <= 0 (negative case)');
|
||||
assert.deepEqual(_.first([1, 2, 3], 2), [1, 2], 'can fetch the first n elements');
|
||||
assert.deepEqual(_.first([1, 2, 3], 5), [1, 2, 3], 'returns the whole array if n > length');
|
||||
var result = (function(){ return _.first(arguments); }(4, 3, 2, 1));
|
||||
assert.strictEqual(result, 4, 'works on an arguments object');
|
||||
result = _.map([[1, 2, 3], [1, 2, 3]], _.first);
|
||||
assert.deepEqual(result, [1, 1], 'works well with _.map');
|
||||
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];
|
||||
equal(_.rest(numbers).join(", "), "2, 3, 4", 'working rest()');
|
||||
equal(_.rest(numbers, 0).join(", "), "1, 2, 3, 4", 'working rest(0)');
|
||||
equal(_.rest(numbers, 2).join(', '), '3, 4', 'rest can take an index');
|
||||
var result = (function(){ return _(arguments).tail(); })(1, 2, 3, 4);
|
||||
equal(result.join(', '), '2, 3, 4', 'aliased as tail and works on arguments object');
|
||||
result = _.map([[1,2,3],[1,2,3]], _.rest);
|
||||
equal(_.flatten(result).join(','), '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');
|
||||
assert.deepEqual(_.rest(numbers), [2, 3, 4], 'fetches all but the first element');
|
||||
assert.deepEqual(_.rest(numbers, 0), [1, 2, 3, 4], 'returns the whole array when index is 0');
|
||||
assert.deepEqual(_.rest(numbers, 2), [3, 4], 'returns elements starting at the given index');
|
||||
var result = (function(){ return _(arguments).rest(); }(1, 2, 3, 4));
|
||||
assert.deepEqual(result, [2, 3, 4], 'works on an arguments object');
|
||||
result = _.map([[1, 2, 3], [1, 2, 3]], _.rest);
|
||||
assert.deepEqual(_.flatten(result), [2, 3, 2, 3], 'works well with _.map');
|
||||
});
|
||||
|
||||
test("initial", function() {
|
||||
equal(_.initial([1,2,3,4,5]).join(", "), "1, 2, 3, 4", 'working initial()');
|
||||
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');
|
||||
QUnit.test('tail', function(assert) {
|
||||
assert.strictEqual(_.tail, _.rest, 'is an alias for rest');
|
||||
});
|
||||
|
||||
test("last", function() {
|
||||
equal(_.last([1,2,3]), 3, 'can pull out the last element of an array');
|
||||
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');
|
||||
QUnit.test('drop', function(assert) {
|
||||
assert.strictEqual(_.drop, _.rest, 'is an alias for rest');
|
||||
});
|
||||
|
||||
test("compact", function() {
|
||||
equal(_.compact([0, 1, false, 2, false, 3]).length, 3, 'can trim out all falsy values');
|
||||
var result = (function(){ return _.compact(arguments).length; })(0, 1, false, 2, false, 3);
|
||||
equal(result, 3, 'works on an arguments object');
|
||||
QUnit.test('initial', function(assert) {
|
||||
assert.deepEqual(_.initial([1, 2, 3, 4, 5]), [1, 2, 3, 4], 'returns all but the last element');
|
||||
assert.deepEqual(_.initial([1, 2, 3, 4], 2), [1, 2], 'returns all but the last n elements');
|
||||
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]]]]];
|
||||
deepEqual(_.flatten(list), [1,2,3,4], 'can flatten nested arrays');
|
||||
deepEqual(_.flatten(list, true), [1,2,3,[[[4]]]], 'can shallowly flatten nested arrays');
|
||||
var result = (function(){ return _.flatten(arguments); })(1, [2], [3, [[[4]]]]);
|
||||
deepEqual(result, [1,2,3,4], 'works on an arguments object');
|
||||
assert.deepEqual(_.flatten(list), [1, 2, 3, 4], 'can 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]]]]));
|
||||
assert.deepEqual(result, [1, 2, 3, 4], 'works on an arguments object');
|
||||
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];
|
||||
equal(_.without(list, 0, 1).join(', '), '2, 3, 4', 'can remove all instances of an object');
|
||||
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(_.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));
|
||||
assert.deepEqual(result, [2, 3, 4], 'works on an arguments object');
|
||||
|
||||
list = [{one : 1}, {two : 2}];
|
||||
ok(_.without(list, {one : 1}).length == 2, 'uses real object identity for comparisons.');
|
||||
ok(_.without(list, list[0]).length == 1, 'ditto.');
|
||||
list = [{one: 1}, {two: 2}];
|
||||
assert.deepEqual(_.without(list, {one: 1}), list, 'compares objects by reference (value case)');
|
||||
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];
|
||||
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];
|
||||
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'}];
|
||||
var iterator = function(value) { return value.name; };
|
||||
equal(_.map(_.uniq(list, false, iterator), iterator).join(', '), 'moe, curly, larry', 'can find the unique values of an array using a custom iterator');
|
||||
list = [{name: 'Moe'}, {name: 'Curly'}, {name: 'Larry'}, {name: 'Curly'}];
|
||||
var expected = [{name: 'Moe'}, {name: 'Curly'}, {name: 'Larry'}];
|
||||
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; };
|
||||
list = [1, 2, 2, 3, 4, 4];
|
||||
equal(_.uniq(list, true, iterator).join(', '), '1, 2, 3, 4', 'iterator works with sorted array');
|
||||
assert.deepEqual(_.uniq([{0: 1}, {0: 1}, {0: 1}, {0: 2}], 0), [{0: 1}, {0: 2}], 'can use falsy pluck like iterator');
|
||||
|
||||
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'];
|
||||
equal(_.intersection(stooges, leaders).join(''), 'moe', 'can take the set intersection of two arrays');
|
||||
equal(_(stooges).intersection(leaders).join(''), 'moe', 'can perform an OO-style intersection');
|
||||
var result = (function(){ return _.intersection(arguments, leaders); })('moe', 'curly', 'larry');
|
||||
equal(result.join(''), 'moe', 'works on an arguments object');
|
||||
assert.deepEqual(_.intersection(stooges, leaders), ['moe'], 'can find the set intersection of two arrays');
|
||||
assert.deepEqual(_(stooges).intersection(leaders), ['moe'], 'can perform an OO-style intersection');
|
||||
var result = (function(){ return _.intersection(arguments, leaders); }('moe', 'curly', 'larry'));
|
||||
assert.deepEqual(result, ['moe'], 'works on an arguments object');
|
||||
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]);
|
||||
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]]);
|
||||
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;
|
||||
(function(){ args = arguments; })(1, 2, 3);
|
||||
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([10, 20], [1, 30, 10], [0, 40]);
|
||||
assert.deepEqual(result, [10, 20, 1, 30, 0, 40], 'orders values by their first encounter');
|
||||
|
||||
result = _.union(null, [1, 2, 3]);
|
||||
deepEqual(result, [null, 1, 2, 3]);
|
||||
result = (function(){ return _.union(arguments, [2, 30, 1], [1, 40]); }(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]);
|
||||
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]);
|
||||
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 stooges = _.zip(names, ages, leaders);
|
||||
equal(String(stooges), 'moe,30,true,larry,40,,curly,50,', 'zipped together arrays of different lengths');
|
||||
assert.deepEqual(_.zip(names, ages, leaders), [
|
||||
['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']);
|
||||
deepEqual(stooges, [['moe','larry','curly'],[30,40,50], ['stooge 1', 'stooge 2', 'stooge 3']], 'zipped pairs');
|
||||
var stooges = _.zip(['moe', 30, 'stooge 1'], ['larry', 40, 'stooge 2'], ['curly', 50, 'stooge 3']);
|
||||
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
|
||||
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');
|
||||
stooges = _.zip(['moe', 30], ['larry', 40], ['curly', 50, 'extra data']);
|
||||
assert.deepEqual(stooges, [['moe', 'larry', 'curly'], [30, 40, 50], [void 0, void 0, 'extra data']], 'zipped pairs with empties');
|
||||
|
||||
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 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]]);
|
||||
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};
|
||||
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];
|
||||
numbers.indexOf = null;
|
||||
equal(_.indexOf(numbers, 2), 1, 'can compute indexOf, even without the native function');
|
||||
var result = (function(){ return _.indexOf(arguments, 2); })(1, 2, 3);
|
||||
equal(result, 1, 'works on an arguments object');
|
||||
equal(_.indexOf(null, 2), -1, 'handles nulls properly');
|
||||
assert.strictEqual(_.indexOf(numbers, 2), 1, 'can compute indexOf');
|
||||
var result = (function(){ return _.indexOf(arguments, 2); }(1, 2, 3));
|
||||
assert.strictEqual(result, 1, 'works on an arguments object');
|
||||
|
||||
_.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;
|
||||
numbers = [10, 20, 30, 40, 50];
|
||||
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;
|
||||
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;
|
||||
index = _.indexOf(numbers, num, true);
|
||||
equal(index, 1, '40 is in the list');
|
||||
assert.strictEqual(_.indexOf(numbers, num, true), 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];
|
||||
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];
|
||||
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.lastIndexOf = null;
|
||||
equal(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function');
|
||||
equal(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element');
|
||||
var result = (function(){ return _.lastIndexOf(arguments, 1); })(1, 0, 1, 0, 0, 1, 0, 0, 0);
|
||||
equal(result, 5, 'works on an arguments object');
|
||||
equal(_.lastIndexOf(null, 2), -1, 'handles nulls properly');
|
||||
assert.strictEqual(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function');
|
||||
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));
|
||||
assert.strictEqual(result, 5, 'works on an arguments object');
|
||||
|
||||
_.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];
|
||||
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() {
|
||||
equal(_.range(0).join(''), '', 'range with 0 as a first argument generates an empty array');
|
||||
equal(_.range(4).join(' '), '0 1 2 3', 'range with a single positive argument generates an array of elements 0,1,2,...,n-1');
|
||||
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');
|
||||
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');
|
||||
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');
|
||||
equal(_.range(0, -10, -1).join(' '), '0 -1 -2 -3 -4 -5 -6 -7 -8 -9', 'final example in the Python docs');
|
||||
QUnit.test('lastIndexOf with NaN', function(assert) {
|
||||
assert.strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN), 3, 'Expected [1, 2, NaN] to contain NaN');
|
||||
assert.strictEqual(_.lastIndexOf([1, 2, Infinity], NaN), -1, 'Expected [1, 2, NaN] to contain NaN');
|
||||
|
||||
assert.strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN, 2), 2, 'fromIndex does not affect result');
|
||||
assert.strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN, -2), 2, 'fromIndex does not affect result');
|
||||
|
||||
(function() {
|
||||
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 = [
|
||||
"I'm a lumberjack and I'm okay",
|
||||
"I sleep all night and I work all day",
|
||||
"He's a lumberjack and he's okay",
|
||||
"He sleeps all night and he works all day"
|
||||
'I\'m a lumberjack and I\'m okay',
|
||||
'I sleep all night and I work all day',
|
||||
'He\'s a lumberjack and he\'s okay',
|
||||
'He sleeps all night and he works all day'
|
||||
];
|
||||
var counts = _(lyrics).chain()
|
||||
.map(function(line) { return line.split(''); })
|
||||
|
@ -16,12 +17,14 @@ $(document).ready(function() {
|
|||
hash[l] = hash[l] || 0;
|
||||
hash[l]++;
|
||||
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() {
|
||||
var numbers = [1,2,3,4,5,6,7,8,9,10];
|
||||
QUnit.test('select/reject/sortBy', function(assert) {
|
||||
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
numbers = _(numbers).chain().select(function(n) {
|
||||
return n % 2 === 0;
|
||||
}).reject(function(n) {
|
||||
|
@ -29,11 +32,11 @@ $(document).ready(function() {
|
|||
}).sortBy(function(n) {
|
||||
return -n;
|
||||
}).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() {
|
||||
var numbers = [1,2,3,4,5,6,7,8,9,10];
|
||||
QUnit.test('select/reject/sortBy in functional style', function(assert) {
|
||||
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
numbers = _.chain(numbers).select(function(n) {
|
||||
return n % 2 === 0;
|
||||
}).reject(function(n) {
|
||||
|
@ -41,11 +44,11 @@ $(document).ready(function() {
|
|||
}).sortBy(function(n) {
|
||||
return -n;
|
||||
}).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() {
|
||||
var numbers = [1,2,3,4,5];
|
||||
QUnit.test('reverse/concat/unshift/pop/map', function(assert) {
|
||||
var numbers = [1, 2, 3, 4, 5];
|
||||
numbers = _(numbers).chain()
|
||||
.reverse()
|
||||
.concat([5, 5, 5])
|
||||
|
@ -53,13 +56,44 @@ $(document).ready(function() {
|
|||
.pop()
|
||||
.map(function(n){ return n * 2; })
|
||||
.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();
|
||||
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 < 3; }).value(), [1, 2]);
|
||||
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() {
|
||||
var context = {name : 'moe'};
|
||||
var func = function(arg) { return "name: " + (this.name || arg); };
|
||||
QUnit.test('bind', function(assert) {
|
||||
var context = {name: 'moe'};
|
||||
var func = function(arg) { return 'name: ' + (this.name || arg); };
|
||||
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);
|
||||
equal(bound(), 'name: moe', 'can do OO-style binding');
|
||||
assert.strictEqual(bound(), 'name: moe', 'can do OO-style binding');
|
||||
|
||||
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 = _.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');
|
||||
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 = _.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); };
|
||||
_.bind(func, 0, 0, 'can bind a function to `0`')();
|
||||
_.bind(func, '', '', 'can bind a function to an empty string')();
|
||||
_.bind(func, false, false, 'can bind a function to `false`')();
|
||||
func = function() { return this; };
|
||||
assert.strictEqual(typeof _.bind(func, 0)(), 'object', 'binding a primitive to `this` returns a wrapped primitive');
|
||||
|
||||
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
|
||||
// To test this with a modern browser, set underscore's nativeBind to undefined
|
||||
var F = function () { return this; };
|
||||
var Boundf = _.bind(F, {hello: "moe curly"});
|
||||
var F = function() { return this; };
|
||||
var boundf = _.bind(F, {hello: 'moe curly'});
|
||||
var Boundf = boundf; // make eslint happy.
|
||||
var newBoundf = new Boundf();
|
||||
equal(newBoundf.hello, undefined, "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");
|
||||
ok(newBoundf instanceof F, "a bound instance is an instance of the original function");
|
||||
assert.strictEqual(newBoundf.hello, void 0, 'function should not be bound to the context, to comply with ECMAScript 5');
|
||||
assert.strictEqual(boundf().hello, 'moe curly', "When called without the new operator, it's OK to be bound to the context");
|
||||
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 func = function() { return this.name + ' ' + _.toArray(arguments).join(' '); };
|
||||
|
||||
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() {
|
||||
var curly = {name : 'curly'}, moe = {
|
||||
name : 'moe',
|
||||
getName : function() { return 'name: ' + this.name; },
|
||||
sayHi : function() { return 'hi: ' + this.name; }
|
||||
QUnit.test('bindAll', function(assert) {
|
||||
var curly = {name: 'curly'};
|
||||
var moe = {
|
||||
name: 'moe',
|
||||
getName: function() { return 'name: ' + this.name; },
|
||||
sayHi: function() { return 'hi: ' + this.name; }
|
||||
};
|
||||
curly.getName = moe.getName;
|
||||
_.bindAll(moe, 'getName', 'sayHi');
|
||||
curly.sayHi = moe.sayHi;
|
||||
equal(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.getName(), 'name: curly', 'unbound function is bound to current object');
|
||||
assert.strictEqual(curly.sayHi(), 'hi: moe', 'bound function is still bound to original object');
|
||||
|
||||
curly = {name : 'curly'};
|
||||
curly = {name: 'curly'};
|
||||
moe = {
|
||||
name : 'moe',
|
||||
getName : function() { return 'name: ' + this.name; },
|
||||
sayHi : function() { return 'hi: ' + this.name; }
|
||||
name: 'moe',
|
||||
getName: function() { return 'name: ' + 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;
|
||||
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) {
|
||||
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
|
||||
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) {
|
||||
return str;
|
||||
};
|
||||
var fastO = _.memoize(o);
|
||||
equal(o('toString'), 'toString', 'checks hasOwnProperty');
|
||||
equal(fastO('toString'), 'toString', 'checks hasOwnProperty');
|
||||
assert.strictEqual(o('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;
|
||||
_.delay(function(){ delayed = true; }, 100);
|
||||
setTimeout(function(){ ok(!delayed, "didn't delay the function quite yet"); }, 50);
|
||||
setTimeout(function(){ ok(delayed, 'delayed the function'); start(); }, 150);
|
||||
setTimeout(function(){ assert.notOk(delayed, "didn't delay the function quite yet"); }, 50);
|
||||
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;
|
||||
_.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 incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 32);
|
||||
throttledIncr(); throttledIncr();
|
||||
|
||||
equal(counter, 1, "incr was called immediately");
|
||||
_.delay(function(){ equal(counter, 2, "incr was throttled"); start(); }, 64);
|
||||
assert.strictEqual(counter, 1, 'incr was called immediately');
|
||||
_.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 update = function(val){ value = val; };
|
||||
var throttledUpdate = _.throttle(update, 32);
|
||||
throttledUpdate(1); throttledUpdate(2);
|
||||
_.delay(function(){ throttledUpdate(3); }, 64);
|
||||
equal(value, 1, "updated to latest value");
|
||||
_.delay(function(){ equal(value, 3, "updated to latest value"); start(); }, 96);
|
||||
assert.strictEqual(value, 1, 'updated to latest value');
|
||||
_.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 incr = function(){ return ++counter; };
|
||||
var throttledIncr = _.throttle(incr, 32);
|
||||
var result = throttledIncr();
|
||||
_.delay(function(){
|
||||
equal(result, 1, "throttled functions return their value");
|
||||
equal(counter, 1, "incr was called once"); start();
|
||||
assert.strictEqual(result, 1, 'throttled functions return their value');
|
||||
assert.strictEqual(counter, 1, 'incr was called once'); done();
|
||||
}, 64);
|
||||
});
|
||||
|
||||
asyncTest("throttle twice", 1, function() {
|
||||
QUnit.test('throttle twice', function(assert) {
|
||||
assert.expect(1);
|
||||
var done = assert.async();
|
||||
var counter = 0;
|
||||
var incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 32);
|
||||
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 incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 30);
|
||||
throttledIncr(); throttledIncr();
|
||||
ok(counter == 1);
|
||||
assert.strictEqual(counter, 1);
|
||||
_.delay(function(){
|
||||
ok(counter == 2);
|
||||
assert.strictEqual(counter, 2);
|
||||
throttledIncr();
|
||||
ok(counter == 3);
|
||||
start();
|
||||
assert.strictEqual(counter, 3);
|
||||
done();
|
||||
}, 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 incr = function(){ return ++counter; };
|
||||
var throttledIncr = _.throttle(incr, 100);
|
||||
|
@ -168,50 +271,56 @@ $(document).ready(function() {
|
|||
_.delay(saveResult, 160);
|
||||
_.delay(saveResult, 230);
|
||||
_.delay(function() {
|
||||
equal(results[0], 1, "incr was called once");
|
||||
equal(results[1], 1, "incr was throttled");
|
||||
equal(results[2], 1, "incr was throttled");
|
||||
equal(results[3], 2, "incr was called twice");
|
||||
equal(results[4], 2, "incr was throttled");
|
||||
equal(results[5], 3, "incr was called trailing");
|
||||
start();
|
||||
assert.strictEqual(results[0], 1, 'incr was called once');
|
||||
assert.strictEqual(results[1], 1, 'incr was throttled');
|
||||
assert.strictEqual(results[2], 1, 'incr was throttled');
|
||||
assert.strictEqual(results[3], 2, 'incr was called twice');
|
||||
assert.strictEqual(results[4], 2, 'incr was throttled');
|
||||
assert.strictEqual(results[5], 3, 'incr was called trailing');
|
||||
done();
|
||||
}, 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 limit = 48;
|
||||
var incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 32);
|
||||
|
||||
var stamp = new Date;
|
||||
while ((new Date - stamp) < limit) {
|
||||
while (new Date - stamp < limit) {
|
||||
throttledIncr();
|
||||
}
|
||||
var lastCount = counter;
|
||||
ok(counter > 1);
|
||||
assert.ok(counter > 1);
|
||||
|
||||
_.delay(function() {
|
||||
ok(counter > lastCount);
|
||||
start();
|
||||
assert.ok(counter > lastCount);
|
||||
done();
|
||||
}, 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 incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 60, {leading: false});
|
||||
|
||||
throttledIncr(); throttledIncr();
|
||||
ok(counter === 0);
|
||||
assert.strictEqual(counter, 0);
|
||||
|
||||
_.delay(function() {
|
||||
ok(counter == 1);
|
||||
start();
|
||||
assert.strictEqual(counter, 1);
|
||||
done();
|
||||
}, 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 incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 100, {leading: false});
|
||||
|
@ -220,133 +329,325 @@ $(document).ready(function() {
|
|||
_.delay(throttledIncr, 50);
|
||||
_.delay(throttledIncr, 60);
|
||||
_.delay(throttledIncr, 200);
|
||||
ok(counter === 0);
|
||||
assert.strictEqual(counter, 0);
|
||||
|
||||
_.delay(function() {
|
||||
ok(counter == 1);
|
||||
assert.strictEqual(counter, 1);
|
||||
}, 250);
|
||||
|
||||
_.delay(function() {
|
||||
ok(counter == 2);
|
||||
start();
|
||||
assert.strictEqual(counter, 2);
|
||||
done();
|
||||
}, 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 incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 100, {leading: false});
|
||||
|
||||
var time = new Date;
|
||||
while (new Date - time < 350) throttledIncr();
|
||||
ok(counter <= 3);
|
||||
assert.ok(counter <= 3);
|
||||
|
||||
_.delay(function() {
|
||||
ok(counter <= 4);
|
||||
start();
|
||||
assert.ok(counter <= 4);
|
||||
done();
|
||||
}, 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 incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 60, {trailing: false});
|
||||
|
||||
throttledIncr(); throttledIncr(); throttledIncr();
|
||||
ok(counter === 1);
|
||||
assert.strictEqual(counter, 1);
|
||||
|
||||
_.delay(function() {
|
||||
ok(counter == 1);
|
||||
assert.strictEqual(counter, 1);
|
||||
|
||||
throttledIncr(); throttledIncr();
|
||||
ok(counter == 2);
|
||||
assert.strictEqual(counter, 2);
|
||||
|
||||
_.delay(function() {
|
||||
ok(counter == 2);
|
||||
start();
|
||||
assert.strictEqual(counter, 2);
|
||||
done();
|
||||
}, 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 incr = function(){ counter++; };
|
||||
var debouncedIncr = _.debounce(incr, 32);
|
||||
debouncedIncr(); debouncedIncr();
|
||||
_.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() {
|
||||
var a, b;
|
||||
QUnit.test('debounce cancel', function(assert) {
|
||||
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 incr = function(){ return ++counter; };
|
||||
var debouncedIncr = _.debounce(incr, 64, true);
|
||||
a = debouncedIncr();
|
||||
b = debouncedIncr();
|
||||
equal(a, 1);
|
||||
equal(b, 1);
|
||||
equal(counter, 1, 'incr was called immediately');
|
||||
assert.strictEqual(a, 1);
|
||||
assert.strictEqual(b, 1);
|
||||
assert.strictEqual(counter, 1, 'incr was called immediately');
|
||||
_.delay(debouncedIncr, 16);
|
||||
_.delay(debouncedIncr, 32);
|
||||
_.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 debouncedIncr = _.debounce(function(){
|
||||
counter++;
|
||||
if (counter < 10) debouncedIncr();
|
||||
}, 32, true);
|
||||
debouncedIncr();
|
||||
equal(counter, 1, "incr was called immediately");
|
||||
_.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 96);
|
||||
assert.strictEqual(counter, 1, 'incr was called immediately');
|
||||
_.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 increment = _.once(function(){ num++; });
|
||||
var increment = _.once(function(){ return ++num; });
|
||||
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(){
|
||||
ok(true);
|
||||
assert.ok(true);
|
||||
f();
|
||||
});
|
||||
f();
|
||||
});
|
||||
|
||||
test("wrap", function() {
|
||||
var greet = function(name){ return "hi: " + name; };
|
||||
QUnit.test('wrap', function(assert) {
|
||||
var greet = function(name){ return 'hi: ' + name; };
|
||||
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 obj = {name : "Moe"};
|
||||
obj.hi = _.wrap(inner, function(fn){ return fn() + this.name; });
|
||||
equal(obj.hi(), "Hello Moe");
|
||||
var inner = function(){ return 'Hello '; };
|
||||
var obj = {name: 'Moe'};
|
||||
obj.hi = _.wrap(inner, function(fn){ return fn() + this.name; });
|
||||
assert.strictEqual(obj.hi(), 'Hello Moe');
|
||||
|
||||
var noop = function(){};
|
||||
var wrapped = _.wrap(noop, function(fn){ return Array.prototype.slice.call(arguments, 0); });
|
||||
var ret = wrapped(['whats', 'your'], 'vector', 'victor');
|
||||
deepEqual(ret, [noop, ['whats', 'your'], 'vector', 'victor']);
|
||||
var noop = function(){};
|
||||
var wrapped = _.wrap(noop, function(){ return Array.prototype.slice.call(arguments, 0); });
|
||||
var ret = wrapped(['whats', 'your'], 'vector', 'victor');
|
||||
assert.deepEqual(ret, [noop, ['whats', 'your'], 'vector', 'victor']);
|
||||
});
|
||||
|
||||
test("compose", function() {
|
||||
var greet = function(name){ return "hi: " + name; };
|
||||
QUnit.test('negate', function(assert) {
|
||||
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 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);
|
||||
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 afterCalled = 0;
|
||||
var after = _.after(afterAmount, function() {
|
||||
|
@ -356,10 +657,114 @@ $(document).ready(function() {
|
|||
return afterCalled;
|
||||
};
|
||||
|
||||
equal(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");
|
||||
equal(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(5, 5), 1, 'after(N) should fire after being called N times');
|
||||
assert.strictEqual(testAfter(5, 4), 0, 'after(N) should not fire unless called N times');
|
||||
assert.strictEqual(testAfter(0, 0), 0, 'after(0) should not fire immediately');
|
||||
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>
|
||||
<title>Underscore Test Suite</title>
|
||||
<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/jslitmus.js"></script>
|
||||
<script src="vendor/qunit-extras.js"></script>
|
||||
<script src="../underscore.js"></script>
|
||||
|
||||
<script src="qunit-setup.js"></script>
|
||||
<script src="collections.js"></script>
|
||||
<script src="arrays.js"></script>
|
||||
<script src="functions.js"></script>
|
||||
<script src="objects.js"></script>
|
||||
<script src="cross-document.js"></script>
|
||||
<script src="utility.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>
|
||||
</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;
|
||||
|
||||
module("Utility", {
|
||||
QUnit.module('Utility', {
|
||||
|
||||
setup: function() {
|
||||
beforeEach: function() {
|
||||
templateSettings = _.clone(_.templateSettings);
|
||||
},
|
||||
|
||||
teardown: function() {
|
||||
afterEach: function() {
|
||||
_.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 = _([]);
|
||||
ok(_(instance) === instance);
|
||||
ok(new _(instance) === instance);
|
||||
assert.strictEqual(_(instance), instance);
|
||||
assert.strictEqual(new _(instance), instance);
|
||||
});
|
||||
|
||||
test("identity", function() {
|
||||
var moe = {name : 'moe'};
|
||||
equal(_.identity(moe), moe, 'moe is the same as his identity');
|
||||
QUnit.test('identity', function(assert) {
|
||||
var stooge = {name: 'moe'};
|
||||
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 min = Math.pow(2, 31);
|
||||
var max = Math.pow(2, 62);
|
||||
|
||||
ok(_.every(array, function() {
|
||||
assert.ok(_.every(array, function() {
|
||||
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;
|
||||
}), "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;
|
||||
while(i++ < 100) ids.push(_.uniqueId());
|
||||
equal(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids');
|
||||
while (i++ < 100) ids.push(_.uniqueId());
|
||||
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 = [];
|
||||
_.times(3, function (i) { vals.push(i); });
|
||||
ok(_.isEqual(vals, [0,1,2]), "is 0 indexed");
|
||||
_.times(3, function(i) { vals.push(i); });
|
||||
assert.deepEqual(vals, [0, 1, 2], 'is 0 indexed');
|
||||
//
|
||||
vals = [];
|
||||
_(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
|
||||
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), []);
|
||||
deepEqual(_.times(-1, _.identity), []);
|
||||
deepEqual(_.times(parseFloat('-Infinity'), _.identity), []);
|
||||
assert.deepEqual(_.times(0, _.identity), []);
|
||||
assert.deepEqual(_.times(-1, _.identity), []);
|
||||
assert.deepEqual(_.times(parseFloat('-Infinity'), _.identity), []);
|
||||
});
|
||||
|
||||
test("mixin", function() {
|
||||
_.mixin({
|
||||
QUnit.test('mixin', function(assert) {
|
||||
var ret = _.mixin({
|
||||
myReverse: function(string) {
|
||||
return string.split('').reverse().join('');
|
||||
}
|
||||
});
|
||||
equal(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _');
|
||||
equal(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper');
|
||||
assert.strictEqual(ret, _, 'returns the _ object to facilitate chaining');
|
||||
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() {
|
||||
equal(_.escape("Curly & Moe"), "Curly & Moe");
|
||||
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), '');
|
||||
QUnit.test('_.escape', function(assert) {
|
||||
assert.strictEqual(_.escape(null), '');
|
||||
});
|
||||
|
||||
test("_.unescape", function() {
|
||||
var string = "Curly & Moe";
|
||||
equal(_.unescape("Curly & Moe"), string);
|
||||
equal(_.unescape('<a href="http://moe.com">Curly & Moe's</a>'), '<a href="http://moe.com">Curly & Moe\'s</a>');
|
||||
equal(_.unescape("Curly &amp; Moe"), "Curly & Moe");
|
||||
equal(_.unescape(null), '');
|
||||
equal(_.unescape(_.escape(string)), string);
|
||||
QUnit.test('_.unescape', function(assert) {
|
||||
var string = 'Curly & Moe';
|
||||
assert.strictEqual(_.unescape(null), '');
|
||||
assert.strictEqual(_.unescape(_.escape(string)), string);
|
||||
assert.strictEqual(_.unescape(string), string, 'don\'t unescape unnecessarily');
|
||||
});
|
||||
|
||||
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 result = basicTemplate({thing : 'This'});
|
||||
equal(result, "This is gettin' on my noives!", 'can do basic attribute interpolation');
|
||||
var result = basicTemplate({thing: 'This'});
|
||||
assert.strictEqual(result, "This is gettin' on my noives!", 'can do basic attribute interpolation');
|
||||
|
||||
var sansSemicolonTemplate = _.template("A <% this %> B");
|
||||
equal(sansSemicolonTemplate(), "A B");
|
||||
var sansSemicolonTemplate = _.template('A <% this %> B');
|
||||
assert.strictEqual(sansSemicolonTemplate(), 'A B');
|
||||
|
||||
var backslashTemplate = _.template("<%= thing %> is \\ridanculous");
|
||||
equal(backslashTemplate({thing: 'This'}), "This is \\ridanculous");
|
||||
var backslashTemplate = _.template('<%= thing %> is \\ridanculous');
|
||||
assert.strictEqual(backslashTemplate({thing: 'This'}), 'This is \\ridanculous');
|
||||
|
||||
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><% \
|
||||
for (var key in people) { \
|
||||
%><li><%= people[key] %></li><% } %></ul>");
|
||||
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');
|
||||
var fancyTemplate = _.template('<ul><% ' +
|
||||
' for (var key in people) { ' +
|
||||
'%><li><%= people[key] %></li><% } %></ul>');
|
||||
result = fancyTemplate({people: {moe: 'Moe', larry: 'Larry', curly: 'Curly'}});
|
||||
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>");
|
||||
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');
|
||||
var escapedCharsInJavaScriptTemplate = _.template('<ul><% _.each(numbers.split("\\n"), function(item) { %><li><%= item %></li><% }) %></ul>');
|
||||
result = escapedCharsInJavaScriptTemplate({numbers: 'one\ntwo\nthree\nfour'});
|
||||
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({
|
||||
pageCount: 3,
|
||||
thumbnails: {
|
||||
1: "p1-thumbnail.gif",
|
||||
2: "p2-thumbnail.gif",
|
||||
3: "p3-thumbnail.gif"
|
||||
1: 'p1-thumbnail.gif',
|
||||
2: 'p2-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();
|
||||
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");
|
||||
equal(quoteTemplate({}), "It's its, not it's");
|
||||
assert.strictEqual(quoteTemplate({}), "It's its, not it's");
|
||||
|
||||
var quoteInStatementAndBody = _.template("<%\
|
||||
if(foo == 'bar'){ \
|
||||
%>Statement quotes and 'quotes'.<% } %>");
|
||||
equal(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'.");
|
||||
var quoteInStatementAndBody = _.template('<% ' +
|
||||
" if(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.');
|
||||
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 result = template({value: "<script>"});
|
||||
equal(result, '<i><script></i>');
|
||||
var template = _.template('<i><%- value %></i>');
|
||||
result = template({value: '<script>'});
|
||||
assert.strictEqual(result, '<i><script></i>');
|
||||
|
||||
var stooge = {
|
||||
name: "Moe",
|
||||
name: 'Moe',
|
||||
template: _.template("I'm <%= this.name %>")
|
||||
};
|
||||
equal(stooge.template(), "I'm Moe");
|
||||
assert.strictEqual(stooge.template(), "I'm Moe");
|
||||
|
||||
if (!$.browser.msie) {
|
||||
var fromHTML = _.template($('#template').html());
|
||||
equal(fromHTML({data : 12345}).replace(/\s/g, ''), '<li>24690</li>');
|
||||
}
|
||||
template = _.template('\n ' +
|
||||
' <%\n ' +
|
||||
' // a comment\n ' +
|
||||
' if (data) { data += 12345; }; %>\n ' +
|
||||
' <li><%= data %></li>\n '
|
||||
);
|
||||
assert.strictEqual(template({data: 12345}).replace(/\s/g, ''), '<li>24690</li>');
|
||||
|
||||
_.templateSettings = {
|
||||
evaluate : /\{\{([\s\S]+?)\}\}/g,
|
||||
interpolate : /\{\{=([\s\S]+?)\}\}/g
|
||||
evaluate: /\{\{([\s\S]+?)\}\}/g,
|
||||
interpolate: /\{\{=([\s\S]+?)\}\}/g
|
||||
};
|
||||
|
||||
var custom = _.template("<ul>{{ for (var key in people) { }}<li>{{= people[key] }}</li>{{ } }}</ul>");
|
||||
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');
|
||||
var custom = _.template('<ul>{{ for (var key in people) { }}<li>{{= people[key] }}</li>{{ } }}</ul>');
|
||||
result = custom({people: {moe: 'Moe', larry: 'Larry', curly: 'Curly'}});
|
||||
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");
|
||||
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'.{{ } }}");
|
||||
equal(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'.");
|
||||
quoteInStatementAndBody = _.template("{{ if(foo == 'bar'){ }}Statement quotes and 'quotes'.{{ } }}");
|
||||
assert.strictEqual(quoteInStatementAndBody({foo: 'bar'}), "Statement quotes and 'quotes'.");
|
||||
|
||||
_.templateSettings = {
|
||||
evaluate : /<\?([\s\S]+?)\?>/g,
|
||||
interpolate : /<\?=([\s\S]+?)\?>/g
|
||||
evaluate: /<\?([\s\S]+?)\?>/g,
|
||||
interpolate: /<\?=([\s\S]+?)\?>/g
|
||||
};
|
||||
|
||||
var customWithSpecialChars = _.template("<ul><? for (var key in people) { ?><li><?= people[key] ?></li><? } ?></ul>");
|
||||
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');
|
||||
var customWithSpecialChars = _.template('<ul><? for (var key in people) { ?><li><?= people[key] ?></li><? } ?></ul>');
|
||||
result = customWithSpecialChars({people: {moe: 'Moe', larry: 'Larry', curly: 'Curly'}});
|
||||
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");
|
||||
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'.<? } ?>");
|
||||
equal(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'.");
|
||||
quoteInStatementAndBody = _.template("<? if(foo == 'bar'){ ?>Statement quotes and 'quotes'.<? } ?>");
|
||||
assert.strictEqual(quoteInStatementAndBody({foo: 'bar'}), "Statement quotes and 'quotes'.");
|
||||
|
||||
_.templateSettings = {
|
||||
interpolate : /\{\{(.+?)\}\}/g
|
||||
interpolate: /\{\{(.+?)\}\}/g
|
||||
};
|
||||
|
||||
var mustache = _.template("Hello {{planet}}!");
|
||||
equal(mustache({planet : "World"}), "Hello World!", "can mimic mustache.js");
|
||||
var mustache = _.template('Hello {{planet}}!');
|
||||
assert.strictEqual(mustache({planet: 'World'}), 'Hello World!', 'can mimic mustache.js');
|
||||
|
||||
var templateWithNull = _.template("a null undefined {{planet}}");
|
||||
equal(templateWithNull({planet : "world"}), "a null undefined world", "can handle missing escape and evaluate settings");
|
||||
var templateWithNull = _.template('a null undefined {{planet}}');
|
||||
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 {
|
||||
_.template('<b><%= if x %></b>');
|
||||
} 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>');
|
||||
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; }};
|
||||
strictEqual(_.result(obj, 'w'), '');
|
||||
strictEqual(_.result(obj, 'x'), 'x');
|
||||
strictEqual(_.result(obj, 'y'), 'x');
|
||||
strictEqual(_.result(obj, 'z'), undefined);
|
||||
strictEqual(_.result(null, 'x'), undefined);
|
||||
assert.strictEqual(_.result(obj, 'w'), '');
|
||||
assert.strictEqual(_.result(obj, 'x'), 'x');
|
||||
assert.strictEqual(_.result(obj, 'y'), 'x');
|
||||
assert.strictEqual(_.result(obj, 'z'), void 0);
|
||||
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 data = {x: 'x'};
|
||||
strictEqual(_.template(s, data, {variable: 'data'}), 'x');
|
||||
var tmp = _.template(s, {variable: 'data'});
|
||||
assert.strictEqual(tmp(data), 'x');
|
||||
_.templateSettings.variable = 'data';
|
||||
strictEqual(_.template(s)(data), 'x');
|
||||
assert.strictEqual(_.template(s)(data), 'x');
|
||||
});
|
||||
|
||||
test('#547 - _.templateSettings is unchanged by custom settings.', function() {
|
||||
ok(!_.templateSettings.variable);
|
||||
QUnit.test('#547 - _.templateSettings is unchanged by custom settings.', function(assert) {
|
||||
assert.notOk(_.templateSettings.variable);
|
||||
_.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%>');
|
||||
strictEqual(template({x: null}), '');
|
||||
strictEqual(template({x: undefined}), '');
|
||||
assert.strictEqual(template({x: null}), '');
|
||||
assert.strictEqual(template({x: void 0}), '');
|
||||
|
||||
var templateEscaped = _.template('<%-x%>');
|
||||
strictEqual(templateEscaped({x: null}), '');
|
||||
strictEqual(templateEscaped({x: undefined}), '');
|
||||
assert.strictEqual(templateEscaped({x: null}), '');
|
||||
assert.strictEqual(templateEscaped({x: void 0}), '');
|
||||
|
||||
var templateWithProperty = _.template('<%=x.foo%>');
|
||||
strictEqual(templateWithProperty({x: {} }), '');
|
||||
strictEqual(templateWithProperty({x: {} }), '');
|
||||
assert.strictEqual(templateWithProperty({x: {}}), '');
|
||||
assert.strictEqual(templateWithProperty({x: {}}), '');
|
||||
|
||||
var templateWithPropertyEscaped = _.template('<%-x.foo%>');
|
||||
strictEqual(templateWithPropertyEscaped({x: {} }), '');
|
||||
strictEqual(templateWithPropertyEscaped({x: {} }), '');
|
||||
assert.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 template = _.template('<%= f() %>');
|
||||
template({f: function(){ ok(!(count++)); }});
|
||||
template({f: function(){ assert.notOk(count++); }});
|
||||
|
||||
var countEscaped = 0;
|
||||
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 = {};
|
||||
_.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});
|
||||
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 2012 jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* Date: 2015-04-03T10:23Z
|
||||
*/
|
||||
|
||||
/** Font Family and Sizes */
|
||||
|
@ -31,32 +32,29 @@
|
|||
#qunit-header {
|
||||
padding: 0.5em 0 0.5em 1em;
|
||||
|
||||
color: #8699a4;
|
||||
background-color: #0d3349;
|
||||
color: #8699A4;
|
||||
background-color: #0D3349;
|
||||
|
||||
font-size: 1.5em;
|
||||
line-height: 1em;
|
||||
font-weight: normal;
|
||||
font-weight: 400;
|
||||
|
||||
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 {
|
||||
text-decoration: none;
|
||||
color: #c2ccd1;
|
||||
color: #C2CCD1;
|
||||
}
|
||||
|
||||
#qunit-header a:hover,
|
||||
#qunit-header a:focus {
|
||||
color: #fff;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar label {
|
||||
display: inline-block;
|
||||
padding: 0 .5em 0 .1em;
|
||||
padding: 0 0.5em 0 0.1em;
|
||||
}
|
||||
|
||||
#qunit-banner {
|
||||
|
@ -64,21 +62,33 @@
|
|||
}
|
||||
|
||||
#qunit-testrunner-toolbar {
|
||||
padding: 0.5em 0 0.5em 2em;
|
||||
padding: 0.5em 1em 0.5em 1em;
|
||||
color: #5E740B;
|
||||
background-color: #eee;
|
||||
background-color: #EEE;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#qunit-userAgent {
|
||||
padding: 0.5em 0 0.5em 2.5em;
|
||||
background-color: #2b81af;
|
||||
color: #fff;
|
||||
padding: 0.5em 1em 0.5em 1em;
|
||||
background-color: #2B81AF;
|
||||
color: #FFF;
|
||||
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
|
||||
}
|
||||
|
||||
#qunit-modulefilter-container {
|
||||
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 */
|
||||
|
@ -88,24 +98,51 @@
|
|||
}
|
||||
|
||||
#qunit-tests li {
|
||||
padding: 0.4em 0.5em 0.4em 2.5em;
|
||||
border-bottom: 1px solid #fff;
|
||||
padding: 0.4em 1em 0.4em 1em;
|
||||
border-bottom: 1px solid #FFF;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
|
||||
#qunit-tests > li {
|
||||
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 {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#qunit-tests li.skipped strong {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
#qunit-tests li a {
|
||||
padding: 0.5em;
|
||||
color: #c2ccd1;
|
||||
color: #C2CCD1;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#qunit-tests li p a {
|
||||
padding: 0.25em;
|
||||
color: #6B6464;
|
||||
}
|
||||
#qunit-tests li a:hover,
|
||||
#qunit-tests li a:focus {
|
||||
color: #000;
|
||||
|
@ -120,11 +157,9 @@
|
|||
margin-top: 0.5em;
|
||||
padding: 0.5em;
|
||||
|
||||
background-color: #fff;
|
||||
background-color: #FFF;
|
||||
|
||||
border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
}
|
||||
|
||||
.qunit-collapsed {
|
||||
|
@ -133,13 +168,13 @@
|
|||
|
||||
#qunit-tests table {
|
||||
border-collapse: collapse;
|
||||
margin-top: .2em;
|
||||
margin-top: 0.2em;
|
||||
}
|
||||
|
||||
#qunit-tests th {
|
||||
text-align: right;
|
||||
vertical-align: top;
|
||||
padding: 0 .5em 0 0;
|
||||
padding: 0 0.5em 0 0;
|
||||
}
|
||||
|
||||
#qunit-tests td {
|
||||
|
@ -153,26 +188,26 @@
|
|||
}
|
||||
|
||||
#qunit-tests del {
|
||||
background-color: #e0f2be;
|
||||
color: #374e0c;
|
||||
background-color: #E0F2BE;
|
||||
color: #374E0C;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#qunit-tests ins {
|
||||
background-color: #ffcaca;
|
||||
background-color: #FFCACA;
|
||||
color: #500;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/*** Test Counts */
|
||||
|
||||
#qunit-tests b.counts { color: black; }
|
||||
#qunit-tests b.counts { color: #000; }
|
||||
#qunit-tests b.passed { color: #5E740B; }
|
||||
#qunit-tests b.failed { color: #710909; }
|
||||
|
||||
#qunit-tests li li {
|
||||
padding: 5px;
|
||||
background-color: #fff;
|
||||
background-color: #FFF;
|
||||
border-bottom: none;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
@ -180,8 +215,8 @@
|
|||
/*** Passing Styles */
|
||||
|
||||
#qunit-tests li li.pass {
|
||||
color: #3c510c;
|
||||
background-color: #fff;
|
||||
color: #3C510C;
|
||||
background-color: #FFF;
|
||||
border-left: 10px solid #C6E746;
|
||||
}
|
||||
|
||||
|
@ -189,7 +224,7 @@
|
|||
#qunit-tests .pass .test-name { color: #366097; }
|
||||
|
||||
#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; }
|
||||
|
||||
|
@ -197,40 +232,52 @@
|
|||
|
||||
#qunit-tests li li.fail {
|
||||
color: #710909;
|
||||
background-color: #fff;
|
||||
background-color: #FFF;
|
||||
border-left: 10px solid #EE5757;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
#qunit-tests > li:last-child {
|
||||
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 .module-name { color: #000000; }
|
||||
#qunit-tests .fail .module-name { color: #000; }
|
||||
|
||||
#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; }
|
||||
|
||||
/*** 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 */
|
||||
|
||||
#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;
|
||||
|
||||
border-bottom: 1px solid white;
|
||||
border-bottom: 1px solid #FFF;
|
||||
}
|
||||
#qunit-testresult .module-name {
|
||||
font-weight: bold;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/** 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