Alphabetically sort roster contacts according to type and status
Also added a new jasmine spec for this as well as jquery.tinysort to do the sorting.
This commit is contained in:
parent
624ab458d0
commit
39c0823f2a
211
Libraries/jquery.tinysort.js
Normal file
211
Libraries/jquery.tinysort.js
Normal file
|
@ -0,0 +1,211 @@
|
|||
/*! TinySort 1.4.29
|
||||
* Copyright (c) 2008-2012 Ron Valstar http://www.sjeiti.com/
|
||||
*
|
||||
* Dual licensed under the MIT and GPL licenses:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*//*
|
||||
* Description:
|
||||
* A jQuery plugin to sort child nodes by (sub) contents or attributes.
|
||||
*
|
||||
* Contributors:
|
||||
* brian.gibson@gmail.com
|
||||
* michael.thornberry@gmail.com
|
||||
*
|
||||
* Usage:
|
||||
* $("ul#people>li").tsort();
|
||||
* $("ul#people>li").tsort("span.surname");
|
||||
* $("ul#people>li").tsort("span.surname",{order:"desc"});
|
||||
* $("ul#people>li").tsort({place:"end"});
|
||||
*
|
||||
* Change default like so:
|
||||
* $.tinysort.defaults.order = "desc";
|
||||
*
|
||||
* in this update:
|
||||
* - added plugin hook
|
||||
* - stripped non-latin character ordering and turned it into a plugin
|
||||
*
|
||||
* in last update:
|
||||
* - header comment no longer stripped in minified version
|
||||
* - revision number no longer corresponds to svn revision since it's now git
|
||||
*
|
||||
* Todos:
|
||||
* - todo: uppercase vs lowercase
|
||||
* - todo: 'foobar' != 'foobars' in non-latin
|
||||
*
|
||||
*/
|
||||
;(function($) {
|
||||
// private vars
|
||||
var fls = !1 // minify placeholder
|
||||
,nll = null // minify placeholder
|
||||
,prsflt = parseFloat // minify placeholder
|
||||
,mathmn = Math.min // minify placeholder
|
||||
,rxLastNr = /(-?\d+\.?\d*)$/g // regex for testing strings ending on numbers
|
||||
,aPluginPrepare = []
|
||||
,aPluginSort = []
|
||||
;
|
||||
//
|
||||
// init plugin
|
||||
$.tinysort = {
|
||||
id: 'TinySort'
|
||||
,version: '1.4.29'
|
||||
,copyright: 'Copyright (c) 2008-2012 Ron Valstar'
|
||||
,uri: 'http://tinysort.sjeiti.com/'
|
||||
,licensed: {
|
||||
MIT: 'http://www.opensource.org/licenses/mit-license.php'
|
||||
,GPL: 'http://www.gnu.org/licenses/gpl.html'
|
||||
}
|
||||
,plugin: function(prepare,sort){
|
||||
aPluginPrepare.push(prepare); // function(settings){doStuff();}
|
||||
aPluginSort.push(sort); // function(valuesAreNumeric,sA,sB,iReturn){doStuff();return iReturn;}
|
||||
}
|
||||
,defaults: { // default settings
|
||||
|
||||
order: 'asc' // order: asc, desc or rand
|
||||
|
||||
,attr: nll // order by attribute value
|
||||
,data: nll // use the data attribute for sorting
|
||||
,useVal: fls // use element value instead of text
|
||||
|
||||
,place: 'start' // place ordered elements at position: start, end, org (original position), first
|
||||
,returns: fls // return all elements or only the sorted ones (true/false)
|
||||
|
||||
,cases: fls // a case sensitive sort orders [aB,aa,ab,bb]
|
||||
,forceStrings:fls // if false the string '2' will sort with the value 2, not the string '2'
|
||||
|
||||
,sortFunction: nll // override the default sort function
|
||||
}
|
||||
};
|
||||
$.fn.extend({
|
||||
tinysort: function(_find,_settings) {
|
||||
if (_find&&typeof(_find)!='string') {
|
||||
_settings = _find;
|
||||
_find = nll;
|
||||
}
|
||||
|
||||
var oSettings = $.extend({}, $.tinysort.defaults, _settings)
|
||||
,sParent
|
||||
,oThis = this
|
||||
,iLen = $(this).length
|
||||
,oElements = {} // contains sortable- and non-sortable list per parent
|
||||
,bFind = !(!_find||_find=='')
|
||||
,bAttr = !(oSettings.attr===nll||oSettings.attr=="")
|
||||
,bData = oSettings.data!==nll
|
||||
// since jQuery's filter within each works on array index and not actual index we have to create the filter in advance
|
||||
,bFilter = bFind&&_find[0]==':'
|
||||
,$Filter = bFilter?oThis.filter(_find):oThis
|
||||
,fnSort = oSettings.sortFunction
|
||||
,iAsc = oSettings.order=='asc'?1:-1
|
||||
,aNewOrder = []
|
||||
;
|
||||
|
||||
$.each(aPluginPrepare,function(i,fn){
|
||||
fn.call(fn,oSettings);
|
||||
});
|
||||
|
||||
|
||||
if (!fnSort) fnSort = oSettings.order=='rand'?function() {
|
||||
return Math.random()<.5?1:-1;
|
||||
}:function(a,b) {
|
||||
var bNumeric = fls
|
||||
// maybe toLower
|
||||
,sA = !oSettings.cases?toLowerCase(a.s):a.s
|
||||
,sB = !oSettings.cases?toLowerCase(b.s):b.s;
|
||||
// maybe force Strings
|
||||
// var bAString = typeof(sA)=='string';
|
||||
// var bBString = typeof(sB)=='string';
|
||||
// if (!oSettings.forceStrings&&(bAString||bBString)) {
|
||||
// if (!bAString) sA = ''+sA;
|
||||
// if (!bBString) sB = ''+sB;
|
||||
if (!oSettings.forceStrings) {
|
||||
// maybe mixed
|
||||
var aAnum = sA&&sA.match(rxLastNr)
|
||||
,aBnum = sB&&sB.match(rxLastNr);
|
||||
if (aAnum&&aBnum) {
|
||||
var sAprv = sA.substr(0,sA.length-aAnum[0].length)
|
||||
,sBprv = sB.substr(0,sB.length-aBnum[0].length);
|
||||
if (sAprv==sBprv) {
|
||||
bNumeric = !fls;
|
||||
sA = prsflt(aAnum[0]);
|
||||
sB = prsflt(aBnum[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// return sort-integer
|
||||
var iReturn = iAsc*(sA<sB?-1:(sA>sB?1:0));
|
||||
|
||||
$.each(aPluginSort,function(i,fn){
|
||||
iReturn = fn.call(fn,bNumeric,sA,sB,iReturn);
|
||||
});
|
||||
|
||||
return iReturn;
|
||||
};
|
||||
|
||||
oThis.each(function(i,el) {
|
||||
var $Elm = $(el)
|
||||
// element or sub selection
|
||||
,mElmOrSub = bFind?(bFilter?$Filter.filter(el):$Elm.find(_find)):$Elm
|
||||
// text or attribute value
|
||||
,sSort = bData?''+mElmOrSub.data(oSettings.data):(bAttr?mElmOrSub.attr(oSettings.attr):(oSettings.useVal?mElmOrSub.val():mElmOrSub.text()))
|
||||
// to sort or not to sort
|
||||
,mParent = $Elm.parent();
|
||||
if (!oElements[mParent]) oElements[mParent] = {s:[],n:[]}; // s: sort, n: not sort
|
||||
if (mElmOrSub.length>0) oElements[mParent].s.push({s:sSort,e:$Elm,n:i}); // s:string, e:element, n:number
|
||||
else oElements[mParent].n.push({e:$Elm,n:i});
|
||||
});
|
||||
//
|
||||
// sort
|
||||
for (sParent in oElements) oElements[sParent].s.sort(fnSort);
|
||||
//
|
||||
// order elements and fill new order
|
||||
for (sParent in oElements) {
|
||||
var oParent = oElements[sParent]
|
||||
,aOrg = [] // list for original position
|
||||
,iLow = iLen
|
||||
,aCnt = [0,0] // count how much we've sorted for retreival from either the sort list or the non-sort list (oParent.s/oParent.n)
|
||||
,i;
|
||||
switch (oSettings.place) {
|
||||
case 'first': $.each(oParent.s,function(i,obj) { iLow = mathmn(iLow,obj.n) }); break;
|
||||
case 'org': $.each(oParent.s,function(i,obj) { aOrg.push(obj.n) }); break;
|
||||
case 'end': iLow = oParent.n.length; break;
|
||||
default: iLow = 0;
|
||||
}
|
||||
for (i = 0;i<iLen;i++) {
|
||||
var bSList = contains(aOrg,i)?!fls:i>=iLow&&i<iLow+oParent.s.length
|
||||
,mEl = (bSList?oParent.s:oParent.n)[aCnt[bSList?0:1]].e;
|
||||
mEl.parent().append(mEl);
|
||||
if (bSList||!oSettings.returns) aNewOrder.push(mEl.get(0));
|
||||
aCnt[bSList?0:1]++;
|
||||
}
|
||||
}
|
||||
oThis.length = 0;
|
||||
Array.prototype.push.apply(oThis,aNewOrder);
|
||||
return oThis;
|
||||
}
|
||||
});
|
||||
// toLowerCase
|
||||
function toLowerCase(s) {
|
||||
return s&&s.toLowerCase?s.toLowerCase():s;
|
||||
}
|
||||
// array contains
|
||||
function contains(a,n) {
|
||||
for (var i=0,l=a.length;i<l;i++) if (a[i]==n) return !fls;
|
||||
return fls;
|
||||
}
|
||||
// set functions
|
||||
$.fn.TinySort = $.fn.Tinysort = $.fn.tsort = $.fn.tinysort;
|
||||
})(jQuery);
|
||||
|
||||
/*! Array.prototype.indexOf for IE (issue #26) */
|
||||
if (!Array.prototype.indexOf) {
|
||||
Array.prototype.indexOf = function(elt /*, from*/) {
|
||||
var len = this.length
|
||||
,from = Number(arguments[1])||0;
|
||||
from = from<0?Math.ceil(from):Math.floor(from);
|
||||
if (from<0) from += len;
|
||||
for (;from<len;from++){
|
||||
if (from in this && this[from]===elt) return from;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
}
|
141
converse.js
141
converse.js
|
@ -43,12 +43,13 @@
|
|||
define([
|
||||
"Libraries/burry.js/burry",
|
||||
"Libraries/underscore.string",
|
||||
"Libraries/jquery.tinysort",
|
||||
"Libraries/jquery-ui-1.9.1.custom",
|
||||
"Libraries/sjcl",
|
||||
"Libraries/backbone",
|
||||
"Libraries/strophe.muc",
|
||||
"Libraries/strophe.roster"
|
||||
], function (Burry, _s, logging) {
|
||||
], function (Burry, _s) {
|
||||
var store = new Burry.Store('collective.xmpp.chat');
|
||||
// Init underscore.str
|
||||
_.str = _s;
|
||||
|
@ -1246,7 +1247,7 @@
|
|||
that = this,
|
||||
subscription = item.get('subscription');
|
||||
|
||||
$(this.el).addClass(item.get('presence_type')).attr('id', 'online-users-'+item.get('user_id'));
|
||||
$(this.el).addClass(item.get('presence_type'));
|
||||
|
||||
if (ask === 'subscribe') {
|
||||
this.$el.addClass('pending-xmpp-contact');
|
||||
|
@ -1521,78 +1522,80 @@
|
|||
}
|
||||
});
|
||||
|
||||
xmppchat.RosterView= (function (roster, _, $, console) {
|
||||
var View = Backbone.View.extend({
|
||||
el: $('#xmppchat-roster'),
|
||||
model: roster,
|
||||
rosteritemviews: {},
|
||||
xmppchat.RosterView = Backbone.View.extend({
|
||||
el: $('#xmppchat-roster'),
|
||||
rosteritemviews: {},
|
||||
|
||||
initialize: function () {
|
||||
this.model.on("add", function (item) {
|
||||
var view = new xmppchat.RosterItemView({model: item});
|
||||
this.rosteritemviews[item.id] = view;
|
||||
if (item.get('ask') === 'request') {
|
||||
view.on('decline-request', function (item) {
|
||||
this.model.remove(item.id);
|
||||
}, this);
|
||||
}
|
||||
this.render();
|
||||
}, this);
|
||||
|
||||
this.model.on('change', function (item) {
|
||||
this.render();
|
||||
}, this);
|
||||
|
||||
this.model.on("remove", function (item) {
|
||||
delete this.rosteritemviews[item.id];
|
||||
this.render();
|
||||
}, this);
|
||||
},
|
||||
|
||||
template: _.template('<dt id="xmpp-contact-requests">Contact requests</dt>' +
|
||||
'<dt id="xmpp-contacts">My contacts</dt>' +
|
||||
'<dt id="pending-xmpp-contacts">Pending contacts</dt>'),
|
||||
|
||||
render: function () {
|
||||
this.$el.empty().html(this.template());
|
||||
var models = this.model.sort().models,
|
||||
children = $(this.el).children(),
|
||||
my_contacts = this.$el.find('#xmpp-contacts').hide(),
|
||||
contact_requests = this.$el.find('#xmpp-contact-requests').hide(),
|
||||
pending_contacts = this.$el.find('#pending-xmpp-contacts').hide(),
|
||||
$count, num;
|
||||
|
||||
for (var i=0; i<models.length; i++) {
|
||||
var model = models[i],
|
||||
user_id = Strophe.getNodeFromJid(model.id),
|
||||
view = this.rosteritemviews[model.id],
|
||||
ask = model.get('ask'),
|
||||
subscription = model.get('subscription');
|
||||
|
||||
if (ask === 'subscribe') {
|
||||
pending_contacts.after(view.render().el);
|
||||
} else if (ask === 'request') {
|
||||
contact_requests.after(view.render().el);
|
||||
} else if (subscription === 'both') {
|
||||
my_contacts.after(view.render().el);
|
||||
}
|
||||
initialize: function () {
|
||||
this.model.on("add", function (item) {
|
||||
var view = new xmppchat.RosterItemView({model: item});
|
||||
this.rosteritemviews[item.id] = view;
|
||||
if (item.get('ask') === 'request') {
|
||||
view.on('decline-request', function (item) {
|
||||
this.model.remove(item.id);
|
||||
}, this);
|
||||
}
|
||||
// Hide the headings if there are no contacts under them
|
||||
_.each([my_contacts, contact_requests, pending_contacts], function (h) {
|
||||
if (h.nextUntil('dt').length > 0) {
|
||||
h.show();
|
||||
}
|
||||
});
|
||||
$count = $('#online-count');
|
||||
$count.text(this.model.getNumOnlineContacts());
|
||||
this.render();
|
||||
}, this);
|
||||
|
||||
this.model.on('change', function (item) {
|
||||
this.render();
|
||||
}, this);
|
||||
|
||||
this.model.on("remove", function (item) {
|
||||
delete this.rosteritemviews[item.id];
|
||||
this.render();
|
||||
}, this);
|
||||
},
|
||||
|
||||
template: _.template('<dt id="xmpp-contact-requests">Contact requests</dt>' +
|
||||
'<dt id="xmpp-contacts">My contacts</dt>' +
|
||||
'<dt id="pending-xmpp-contacts">Pending contacts</dt>'),
|
||||
|
||||
render: function () {
|
||||
this.$el.empty().html(this.template());
|
||||
var models = this.model.sort().models,
|
||||
children = $(this.el).children(),
|
||||
$my_contacts = this.$el.find('#xmpp-contacts').hide(),
|
||||
$contact_requests = this.$el.find('#xmpp-contact-requests').hide(),
|
||||
$pending_contacts = this.$el.find('#pending-xmpp-contacts').hide(),
|
||||
$count, num;
|
||||
|
||||
for (var i=0; i<models.length; i++) {
|
||||
var model = models[i],
|
||||
user_id = Strophe.getNodeFromJid(model.id),
|
||||
view = this.rosteritemviews[model.id],
|
||||
ask = model.get('ask'),
|
||||
subscription = model.get('subscription');
|
||||
crit = {order:'asc'};
|
||||
|
||||
if (ask === 'subscribe') {
|
||||
$pending_contacts.after(view.render().el);
|
||||
$pending_contacts.after($pending_contacts.siblings('dd.pending-xmpp-contact').tsort(crit));
|
||||
} else if (ask === 'request') {
|
||||
$contact_requests.after(view.render().el);
|
||||
$contact_requests.after($contact_requests.siblings('dd.requesting-xmpp-contact').tsort(crit));
|
||||
} else if (subscription === 'both') {
|
||||
$my_contacts.after(view.render().el);
|
||||
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.offline').tsort('a', crit));
|
||||
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.unavailable').tsort('a', crit));
|
||||
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.away').tsort('a', crit));
|
||||
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.busy').tsort('a', crit));
|
||||
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.online').tsort('a', crit));
|
||||
}
|
||||
}
|
||||
});
|
||||
var view = new View();
|
||||
return view;
|
||||
// Hide the headings if there are no contacts under them
|
||||
_.each([$my_contacts, $contact_requests, $pending_contacts], function (h) {
|
||||
if (h.nextUntil('dt').length > 0) {
|
||||
h.show();
|
||||
}
|
||||
});
|
||||
$count = $('#online-count');
|
||||
$count.text(this.model.getNumOnlineContacts());
|
||||
}
|
||||
});
|
||||
|
||||
xmppchat.XMPPStatus = Backbone.Model.extend({
|
||||
|
||||
initialize: function () {
|
||||
this.set({
|
||||
'status' : this.getStatus(),
|
||||
|
@ -1781,7 +1784,7 @@
|
|||
this.chatboxesview = new this.ChatBoxesView({'model': this.chatboxes});
|
||||
|
||||
this.roster = new this.RosterItems();
|
||||
this.rosterview = Backbone.View.extend(this.RosterView(this.roster, _, $, console));
|
||||
this.rosterview = new this.RosterView({'model':this.roster});
|
||||
|
||||
this.connection.addHandler(
|
||||
$.proxy(this.roster.subscribeToSuggestedItems, this.roster),
|
||||
|
|
208
spec/RosterSpec.js
Normal file
208
spec/RosterSpec.js
Normal file
|
@ -0,0 +1,208 @@
|
|||
(function (root, factory) {
|
||||
define([
|
||||
"converse"
|
||||
], function (xmppchat) {
|
||||
return factory(xmppchat);
|
||||
}
|
||||
);
|
||||
} (this, function (xmppchat) {
|
||||
|
||||
return describe("Contacts Roster", function() {
|
||||
|
||||
// Names from http://www.fakenamegenerator.com/
|
||||
names = [
|
||||
'Louw Spekman', 'Mohamad Stet', 'Dominik Beyer', 'Dirk Eichel', 'Marco Duerr', 'Ute Schiffer',
|
||||
'Billie Westerhuis', 'Sarah Kuester', 'Sabrina Loewe', 'Laura Duerr', 'Mathias Meyer',
|
||||
'Tijm Keller', 'Lea Gerste', 'Martin Pfeffer', 'Ulrike Abt', 'Zoubida van Rooij',
|
||||
'Maylin Hettema', 'Ruwan Bechan', 'Marco Beich', 'Karin Busch', 'Mathias Müller',
|
||||
'Suleyman van Beusichem', 'Nicole Diederich', 'Nanja van Yperen', 'Delany Bloemendaal',
|
||||
'Jannah Hofmeester', 'Christine Trommler', 'Martin Bumgarner', 'Emil Baeten', 'Farshad Brasser',
|
||||
'Gabriele Fisher', 'Sofiane Schopman', 'Sky Wismans', 'Jeffery Stoelwinder', 'Ganesh Waaijenberg',
|
||||
'Dani Boldewijn', 'Katrin Propst', 'Martina Kaiser', 'Philipp Kappel', 'Meeke Grootendorst',
|
||||
'Max Frankfurter', 'Candice van der Knijff', 'Irini Vlastuin', 'Rinse Sommer', 'Annegreet Gomez',
|
||||
'Robin Schook', 'Marcel Eberhardt', 'Simone Brauer', 'Asmaa Haakman', 'Felix Amsel',
|
||||
'Lena Grunewald', 'Laura Grunewald', 'Mandy Seiler', 'Sven Bosch', 'Nuriye Cuypers', 'Ben Zomer',
|
||||
'Leah Weiss', 'Francesca Disseldorp', 'Sven Bumgarner', 'Benjamin Zweig'
|
||||
];
|
||||
|
||||
describe("contacts roster", function () {
|
||||
|
||||
xmppchat.roster = new xmppchat.RosterItems();
|
||||
xmppchat.rosterview = new xmppchat.RosterView({'model':xmppchat.roster});
|
||||
// stub
|
||||
xmppchat.chatboxesview = {openChat: function () {} };
|
||||
// Hack to make sure there is an element.
|
||||
xmppchat.rosterview.$el = $('<dl id="xmppchat-roster"></dl>');
|
||||
xmppchat.rosterview.render();
|
||||
|
||||
it("should hide the requesting contacts heading if there aren't any", function () {
|
||||
expect(xmppchat.rosterview.$el.find('dt#xmpp-contact-requests').css('display')).toEqual('none');
|
||||
});
|
||||
|
||||
it("should be able to add requesting contacts, and they should be sorted alphabetically", function () {
|
||||
var jid, i, t;
|
||||
spyOn(xmppchat.rosterview, 'render').andCallThrough();
|
||||
spyOn(xmppchat.chatboxesview, 'openChat');
|
||||
for (i=0; i<10; i++) {
|
||||
jid = names[i].replace(' ','.').toLowerCase() + '@localhost';
|
||||
xmppchat.roster.addRosterItem(jid, 'none', 'request', names[i]);
|
||||
expect(xmppchat.rosterview.render).toHaveBeenCalled();
|
||||
// Check that they are sorted alphabetically
|
||||
t = xmppchat.rosterview.$el.find('dt#xmpp-contact-requests').siblings('dd.requesting-xmpp-contact').text().replace(/AcceptDecline/g, '');
|
||||
expect(t).toEqual(names.slice(0,i+1).sort().join(''));
|
||||
// When a requesting contact is added, the controlbox must
|
||||
// be opened.
|
||||
expect(xmppchat.chatboxesview.openChat).toHaveBeenCalledWith('controlbox');
|
||||
}
|
||||
});
|
||||
|
||||
it("should show the requesting contacts heading after they have been added", function () {
|
||||
expect(xmppchat.rosterview.$el.find('dt#xmpp-contact-requests').css('display')).toEqual('block');
|
||||
});
|
||||
|
||||
it("should hide the pending contacts heading if there aren't any", function () {
|
||||
expect(xmppchat.rosterview.$el.find('dt#pending-xmpp-contacts').css('display')).toEqual('none');
|
||||
});
|
||||
|
||||
it("should be able to add pending contacts, and they should be sorted alphabetically", function () {
|
||||
var jid, i, t;
|
||||
spyOn(xmppchat.rosterview, 'render').andCallThrough();
|
||||
for (i=10; i<20; i++) {
|
||||
jid = names[i].replace(' ','.').toLowerCase() + '@localhost';
|
||||
xmppchat.roster.addRosterItem(jid, 'none', 'subscribe', names[i]);
|
||||
expect(xmppchat.rosterview.render).toHaveBeenCalled();
|
||||
// Check that they are sorted alphabetically
|
||||
t = xmppchat.rosterview.$el.find('dt#pending-xmpp-contacts').siblings('dd.pending-xmpp-contact').text();
|
||||
expect(t).toEqual(names.slice(10,i+1).sort().join(''));
|
||||
}
|
||||
});
|
||||
|
||||
it("should show the pending contacts heading after they have been added", function () {
|
||||
expect(xmppchat.rosterview.$el.find('dt#pending-xmpp-contacts').css('display')).toEqual('block');
|
||||
});
|
||||
|
||||
it("should hide the current contacts heading if there aren't any", function () {
|
||||
expect(xmppchat.rosterview.$el.find('dt#xmpp-contacts').css('display')).toEqual('none');
|
||||
});
|
||||
|
||||
it("should be able to add existing contacts, and they should be sorted alphabetically", function () {
|
||||
var jid, i, t;
|
||||
spyOn(xmppchat.rosterview, 'render').andCallThrough();
|
||||
// Add 40 properly regisertered contacts (initially all offline) and check that they are sorted alphabetically
|
||||
for (i=20; i<60; i++) {
|
||||
jid = names[i].replace(' ','.').toLowerCase() + '@localhost';
|
||||
xmppchat.roster.addRosterItem(jid, 'both', null, names[i]);
|
||||
expect(xmppchat.rosterview.render).toHaveBeenCalled();
|
||||
// Check that they are sorted alphabetically
|
||||
t = xmppchat.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact.offline').find('a.open-chat').text();
|
||||
expect(t).toEqual(names.slice(20,i+1).sort().join(''));
|
||||
}
|
||||
});
|
||||
|
||||
it("should show the current contacts heading if they have been added", function () {
|
||||
expect(xmppchat.rosterview.$el.find('dt#xmpp-contacts').css('display')).toEqual('block');
|
||||
});
|
||||
|
||||
describe("roster items", function () {
|
||||
|
||||
it("should be able to change their status to online and be sorted alphabetically", function () {
|
||||
var item, view, jid;
|
||||
spyOn(xmppchat.rosterview, 'render').andCallThrough();
|
||||
for (i=59; i>54; i--) {
|
||||
jid = names[i].replace(' ','.').toLowerCase() + '@localhost';
|
||||
view = xmppchat.rosterview.rosteritemviews[jid];
|
||||
spyOn(view, 'render').andCallThrough();
|
||||
item = view.model;
|
||||
item.set('presence_type', 'online');
|
||||
expect(view.render).toHaveBeenCalled();
|
||||
expect(xmppchat.rosterview.render).toHaveBeenCalled();
|
||||
|
||||
// Check that they are sorted alphabetically
|
||||
t = xmppchat.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact.online').find('a.open-chat').text();
|
||||
expect(t).toEqual(names.slice(-(60-i)).sort().join(''));
|
||||
}
|
||||
});
|
||||
|
||||
it("should be able to change their status to busy and be sorted alphabetically", function () {
|
||||
var item, view, jid;
|
||||
spyOn(xmppchat.rosterview, 'render').andCallThrough();
|
||||
for (i=54; i>49; i--) {
|
||||
jid = names[i].replace(' ','.').toLowerCase() + '@localhost';
|
||||
view = xmppchat.rosterview.rosteritemviews[jid];
|
||||
spyOn(view, 'render').andCallThrough();
|
||||
item = view.model;
|
||||
item.set('presence_type', 'busy');
|
||||
expect(view.render).toHaveBeenCalled();
|
||||
expect(xmppchat.rosterview.render).toHaveBeenCalled();
|
||||
|
||||
// Check that they are sorted alphabetically
|
||||
t = xmppchat.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact.busy').find('a.open-chat').text();
|
||||
expect(t).toEqual(names.slice(-(60-i), -5).sort().join(''));
|
||||
}
|
||||
});
|
||||
|
||||
it("should be able to change their status to away and be sorted alphabetically", function () {
|
||||
var item, view, jid;
|
||||
spyOn(xmppchat.rosterview, 'render').andCallThrough();
|
||||
for (i=49; i>44; i--) {
|
||||
jid = names[i].replace(' ','.').toLowerCase() + '@localhost';
|
||||
view = xmppchat.rosterview.rosteritemviews[jid];
|
||||
spyOn(view, 'render').andCallThrough();
|
||||
item = view.model;
|
||||
item.set('presence_type', 'away');
|
||||
expect(view.render).toHaveBeenCalled();
|
||||
expect(xmppchat.rosterview.render).toHaveBeenCalled();
|
||||
|
||||
// Check that they are sorted alphabetically
|
||||
t = xmppchat.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact.away').find('a.open-chat').text();
|
||||
expect(t).toEqual(names.slice(-(60-i),-10).sort().join(''));
|
||||
}
|
||||
});
|
||||
|
||||
it("should be able to change their status to unavailable and be sorted alphabetically", function () {
|
||||
var item, view, jid;
|
||||
spyOn(xmppchat.rosterview, 'render').andCallThrough();
|
||||
for (i=44; i>39; i--) {
|
||||
jid = names[i].replace(' ','.').toLowerCase() + '@localhost';
|
||||
view = xmppchat.rosterview.rosteritemviews[jid];
|
||||
spyOn(view, 'render').andCallThrough();
|
||||
item = view.model;
|
||||
item.set('presence_type', 'unavailable');
|
||||
expect(view.render).toHaveBeenCalled();
|
||||
expect(xmppchat.rosterview.render).toHaveBeenCalled();
|
||||
|
||||
// Check that they are sorted alphabetically
|
||||
t = xmppchat.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact.unavailable').find('a.open-chat').text();
|
||||
expect(t).toEqual(names.slice(-(60-i), -15).sort().join(''));
|
||||
}
|
||||
});
|
||||
|
||||
it("should be ordered according to status: online, busy, away, unavailable, offline", function () {
|
||||
var contacts = xmppchat.rosterview.$el.find('dd.current-xmpp-contact');
|
||||
var i;
|
||||
// The first five contacts are online.
|
||||
for (i=0; i<5; i++) {
|
||||
expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('online');
|
||||
}
|
||||
// The next five are busy
|
||||
for (i=5; i<10; i++) {
|
||||
expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('busy');
|
||||
}
|
||||
// The next five are away
|
||||
for (i=10; i<15; i++) {
|
||||
expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('away');
|
||||
}
|
||||
// The next five are unavailable
|
||||
for (i=15; i<20; i++) {
|
||||
expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('unavailable');
|
||||
}
|
||||
// The next 20 are offline
|
||||
for (i=20; i<40; i++) {
|
||||
expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('offline');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
}));
|
|
@ -1,5 +1,6 @@
|
|||
require(["jquery",
|
||||
"spec/StorageSpec"], function($) {
|
||||
"spec/StorageSpec",
|
||||
"spec/RosterSpec"], function($) {
|
||||
|
||||
$(function($) {
|
||||
var jasmineEnv = jasmine.getEnv();
|
||||
|
|
Loading…
Reference in New Issue
Block a user