Merge branch 'profiling'
This commit is contained in:
commit
52cabd0d23
|
@ -99,10 +99,15 @@ module.exports = function(grunt) {
|
||||||
done();
|
done();
|
||||||
};
|
};
|
||||||
exec('./node_modules/requirejs/bin/r.js -o src/build.js && ' +
|
exec('./node_modules/requirejs/bin/r.js -o src/build.js && ' +
|
||||||
|
'./node_modules/requirejs/bin/r.js -o src/build.js optimize=none out=builds/converse.js && ' +
|
||||||
'./node_modules/requirejs/bin/r.js -o src/build-no-locales-no-otr.js && ' +
|
'./node_modules/requirejs/bin/r.js -o src/build-no-locales-no-otr.js && ' +
|
||||||
|
'./node_modules/requirejs/bin/r.js -o src/build-no-locales-no-otr.js optimize=none out=builds/converse-no-locales-no-otr.js && ' +
|
||||||
'./node_modules/requirejs/bin/r.js -o src/build-no-otr.js &&' +
|
'./node_modules/requirejs/bin/r.js -o src/build-no-otr.js &&' +
|
||||||
|
'./node_modules/requirejs/bin/r.js -o src/build-no-otr.js optimize=none out=builds/converse-no-otr.js && ' +
|
||||||
'./node_modules/requirejs/bin/r.js -o src/build-website-no-otr.js &&' +
|
'./node_modules/requirejs/bin/r.js -o src/build-website-no-otr.js &&' +
|
||||||
'./node_modules/requirejs/bin/r.js -o src/build-website.js', callback);
|
'./node_modules/requirejs/bin/r.js -o src/build-website.js', callback);
|
||||||
|
// XXX: It might be possible to not have separate build config files. For example:
|
||||||
|
// 'r.js -o src/build.js paths.converse-dependencies=src/deps-no-otr paths.locales=locale/nolocales out=builds/converse-no-locales-no-otr.min.js'
|
||||||
});
|
});
|
||||||
|
|
||||||
grunt.registerTask('minify', 'Create a new release', ['cssmin', 'jsmin']);
|
grunt.registerTask('minify', 'Create a new release', ['cssmin', 'jsmin']);
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
"backbone.browserStorage": "*",
|
"backbone.browserStorage": "*",
|
||||||
"backbone.overview": "*",
|
"backbone.overview": "*",
|
||||||
"strophe": "~1.1.3",
|
"strophe": "~1.1.3",
|
||||||
"strophe.roster": "https://raw.github.com/strophe/strophejs-plugins/b1f364eb6e854ffe844c57add38e885cfeb9b498/roster/strophe.roster.js",
|
|
||||||
"strophe.muc": "https://raw.githubusercontent.com/strophe/strophejs-plugins/master/muc/strophe.muc.js",
|
"strophe.muc": "https://raw.githubusercontent.com/strophe/strophejs-plugins/master/muc/strophe.muc.js",
|
||||||
"otr": "0.2.12",
|
"otr": "0.2.12",
|
||||||
"crypto-js-evanvosberg": "~3.1.2",
|
"crypto-js-evanvosberg": "~3.1.2",
|
||||||
|
@ -30,7 +29,7 @@
|
||||||
"bootstrapJS": "https://raw.githubusercontent.com/jcbrand/bootstrap/7d96a5f60d26c67b5348b270a775518b96a702c8/dist/js/bootstrap.js",
|
"bootstrapJS": "https://raw.githubusercontent.com/jcbrand/bootstrap/7d96a5f60d26c67b5348b270a775518b96a702c8/dist/js/bootstrap.js",
|
||||||
"fontawesome": "~4.1.0",
|
"fontawesome": "~4.1.0",
|
||||||
"typeahead.js": "https://raw.githubusercontent.com/jcbrand/typeahead.js/eedfb10505dd3a20123d1fafc07c1352d83f0ab3/dist/typeahead.jquery.js",
|
"typeahead.js": "https://raw.githubusercontent.com/jcbrand/typeahead.js/eedfb10505dd3a20123d1fafc07c1352d83f0ab3/dist/typeahead.jquery.js",
|
||||||
"strophejs-plugins": "~0.0.4"
|
"strophejs-plugins": "https://github.com/strophe/strophejs-plugins.git#a56421ff4ecf0807113ab48c46728715597df599"
|
||||||
},
|
},
|
||||||
"exportsOverride": {}
|
"exportsOverride": {}
|
||||||
}
|
}
|
||||||
|
|
153
converse.js
153
converse.js
|
@ -541,6 +541,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
this.clearSession = function () {
|
this.clearSession = function () {
|
||||||
|
this.roster.browserStorage._clear();
|
||||||
this.session.browserStorage._clear();
|
this.session.browserStorage._clear();
|
||||||
// XXX: this should perhaps go into the beforeunload handler
|
// XXX: this should perhaps go into the beforeunload handler
|
||||||
converse.chatboxes.get('controlbox').save({'connected': false});
|
converse.chatboxes.get('controlbox').save({'connected': false});
|
||||||
|
@ -1935,8 +1936,16 @@
|
||||||
b64_sha1('converse.roster.groups'+converse.bare_jid));
|
b64_sha1('converse.roster.groups'+converse.bare_jid));
|
||||||
converse.rosterview = new converse.RosterView({model: rostergroups});
|
converse.rosterview = new converse.RosterView({model: rostergroups});
|
||||||
this.contactspanel.$el.append(converse.rosterview.$el);
|
this.contactspanel.$el.append(converse.rosterview.$el);
|
||||||
|
// TODO:
|
||||||
|
// See if we shouldn't also fetch the roster here... otherwise
|
||||||
|
// the roster is always populated by the rosterHandler method,
|
||||||
|
// which appears to be a less economic way.
|
||||||
|
// i.e. from what it seems, only groups are fetched from
|
||||||
|
// browserStorage, and no contacts.
|
||||||
|
// XXX: Make sure that if fetch is called, we don't sort on
|
||||||
|
// each item add...
|
||||||
|
// converse.roster.fetch()
|
||||||
converse.rosterview.render().fetch().update();
|
converse.rosterview.render().fetch().update();
|
||||||
converse.connection.roster.get(function () {});
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -3212,6 +3221,10 @@
|
||||||
'status': ''
|
'status': ''
|
||||||
}, attributes);
|
}, attributes);
|
||||||
this.set(attrs);
|
this.set(attrs);
|
||||||
|
},
|
||||||
|
|
||||||
|
showInRoster: function () {
|
||||||
|
return (!converse.show_only_online_users || this.get('chat_status') === 'online');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3226,24 +3239,12 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize: function () {
|
initialize: function () {
|
||||||
this.model.on("change", this.onChange, this);
|
this.model.on("change", this.render, this);
|
||||||
this.model.on("remove", this.remove, this);
|
this.model.on("remove", this.remove, this);
|
||||||
this.model.on("destroy", this.remove, this);
|
this.model.on("destroy", this.remove, this);
|
||||||
this.model.on("open", this.openChat, this);
|
this.model.on("open", this.openChat, this);
|
||||||
},
|
},
|
||||||
|
|
||||||
onChange: function () {
|
|
||||||
if (converse.show_only_online_users) {
|
|
||||||
if (this.model.get('chat_status') !== 'online') {
|
|
||||||
this.$el.hide();
|
|
||||||
} else {
|
|
||||||
this.$el.show();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.render();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
openChat: function (ev) {
|
openChat: function (ev) {
|
||||||
if (ev && ev.preventDefault) { ev.preventDefault(); }
|
if (ev && ev.preventDefault) { ev.preventDefault(); }
|
||||||
// XXX: Can this.model.attributes be used here, instead of
|
// XXX: Can this.model.attributes be used here, instead of
|
||||||
|
@ -3293,6 +3294,12 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function () {
|
render: function () {
|
||||||
|
if (!this.model.showInRoster()) {
|
||||||
|
this.$el.hide();
|
||||||
|
return this;
|
||||||
|
} else if (this.$el[0].style.display === "none") {
|
||||||
|
this.$el.show();
|
||||||
|
}
|
||||||
var item = this.model,
|
var item = this.model,
|
||||||
ask = item.get('ask'),
|
ask = item.get('ask'),
|
||||||
chat_status = item.get('chat_status'),
|
chat_status = item.get('chat_status'),
|
||||||
|
@ -3356,13 +3363,13 @@
|
||||||
|
|
||||||
this.RosterContacts = Backbone.Collection.extend({
|
this.RosterContacts = Backbone.Collection.extend({
|
||||||
model: converse.RosterContact,
|
model: converse.RosterContact,
|
||||||
|
|
||||||
comparator: function (contact1, contact2) {
|
comparator: function (contact1, contact2) {
|
||||||
var name1 = contact1.get('fullname').toLowerCase();
|
var name1, name2;
|
||||||
var status1 = contact1.get('chat_status') || 'offline';
|
var status1 = contact1.get('chat_status') || 'offline';
|
||||||
var name2 = contact2.get('fullname').toLowerCase();
|
|
||||||
var status2 = contact2.get('chat_status') || 'offline';
|
var status2 = contact2.get('chat_status') || 'offline';
|
||||||
if (STATUS_WEIGHTS[status1] === STATUS_WEIGHTS[status2]) {
|
if (STATUS_WEIGHTS[status1] === STATUS_WEIGHTS[status2]) {
|
||||||
|
name1 = contact1.get('fullname').toLowerCase();
|
||||||
|
name2 = contact2.get('fullname').toLowerCase();
|
||||||
return name1 < name2 ? -1 : (name1 > name2? 1 : 0);
|
return name1 < name2 ? -1 : (name1 > name2? 1 : 0);
|
||||||
} else {
|
} else {
|
||||||
return STATUS_WEIGHTS[status1] < STATUS_WEIGHTS[status2] ? -1 : 1;
|
return STATUS_WEIGHTS[status1] < STATUS_WEIGHTS[status2] ? -1 : 1;
|
||||||
|
@ -3370,15 +3377,13 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
subscribeToSuggestedItems: function (msg) {
|
subscribeToSuggestedItems: function (msg) {
|
||||||
$(msg).find('item').each(function () {
|
$(msg).find('item').each(function (i, items) {
|
||||||
var $this = $(this),
|
var $this = $(this),
|
||||||
jid = $this.attr('jid'),
|
jid = $this.attr('jid'),
|
||||||
action = $this.attr('action'),
|
action = $this.attr('action'),
|
||||||
fullname = $this.attr('name');
|
fullname = $this.attr('name');
|
||||||
if (action === 'add') {
|
if (action === 'add') {
|
||||||
converse.connection.roster.add(jid, fullname, [], function (iq) {
|
converse.connection.roster.subscribe(jid, null, converse.xmppstatus.get('fullname'));
|
||||||
converse.connection.roster.subscribe(jid, null, converse.xmppstatus.get('fullname'));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
|
@ -3486,7 +3491,8 @@
|
||||||
rosterHandler: function (items, item) {
|
rosterHandler: function (items, item) {
|
||||||
converse.emit('roster', items);
|
converse.emit('roster', items);
|
||||||
this.clearCache(items);
|
this.clearCache(items);
|
||||||
_.each(items, function (item, index, items) {
|
var new_items = item ? [item] : items;
|
||||||
|
_.each(new_items, function (item, index, items) {
|
||||||
if (this.isSelf(item.jid)) { return; }
|
if (this.isSelf(item.jid)) { return; }
|
||||||
var model = this.get(item.jid);
|
var model = this.get(item.jid);
|
||||||
if (!model) {
|
if (!model) {
|
||||||
|
@ -3503,7 +3509,7 @@
|
||||||
groups: item.groups,
|
groups: item.groups,
|
||||||
jid: item.jid,
|
jid: item.jid,
|
||||||
subscription: item.subscription
|
subscription: item.subscription
|
||||||
});
|
}, {sort: false});
|
||||||
} else {
|
} else {
|
||||||
if ((item.subscription === 'none') && (item.ask === null)) {
|
if ((item.subscription === 'none') && (item.ask === null)) {
|
||||||
// This user is no longer in our roster
|
// This user is no longer in our roster
|
||||||
|
@ -3686,11 +3692,13 @@
|
||||||
var view = new converse.RosterContactView({model: contact});
|
var view = new converse.RosterContactView({model: contact});
|
||||||
this.add(contact.get('id'), view);
|
this.add(contact.get('id'), view);
|
||||||
view = this.positionContact(contact).render();
|
view = this.positionContact(contact).render();
|
||||||
if (this.model.get('state') === CLOSED) {
|
if (contact.showInRoster()) {
|
||||||
view.$el.hide();
|
if (this.model.get('state') === CLOSED) {
|
||||||
this.$el.show();
|
if (view.$el[0].style.display !== "none") { view.$el.hide(); }
|
||||||
} else {
|
if (this.$el[0].style.display === "none") { this.$el.show(); }
|
||||||
this.show();
|
} else {
|
||||||
|
if (this.$el[0].style.display !== "block") { this.show(); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -3712,6 +3720,9 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
show: function () {
|
show: function () {
|
||||||
|
// FIXME: There's a bug here, if show_only_online_users is true
|
||||||
|
// Possible solution, get the group, call _.each and check
|
||||||
|
// showInRoster
|
||||||
this.$el.nextUntil('dt').addBack().show();
|
this.$el.nextUntil('dt').addBack().show();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -3729,7 +3740,7 @@
|
||||||
if (q.length === 0) {
|
if (q.length === 0) {
|
||||||
if (this.model.get('state') === OPENED) {
|
if (this.model.get('state') === OPENED) {
|
||||||
this.model.contacts.each($.proxy(function (item) {
|
this.model.contacts.each($.proxy(function (item) {
|
||||||
if (!(converse.show_only_online_users && item.get('chat_status') === 'online')) {
|
if (item.showInRoster()) {
|
||||||
this.get(item.get('id')).$el.show();
|
this.get(item.get('id')).$el.show();
|
||||||
}
|
}
|
||||||
}, this));
|
}, this));
|
||||||
|
@ -3849,16 +3860,20 @@
|
||||||
converse.roster.on("remove", this.update, this);
|
converse.roster.on("remove", this.update, this);
|
||||||
this.model.on("add", this.onGroupAdd, this);
|
this.model.on("add", this.onGroupAdd, this);
|
||||||
this.model.on("reset", this.reset, this);
|
this.model.on("reset", this.reset, this);
|
||||||
|
this.$roster = $('<dl class="roster-contacts" style="display: none;"></dl>');
|
||||||
},
|
},
|
||||||
|
|
||||||
update: function () {
|
update: _.debounce(function () {
|
||||||
var $count = $('#online-count');
|
var $count = $('#online-count');
|
||||||
$count.text('('+converse.roster.getNumOnlineContacts()+')');
|
$count.text('('+converse.roster.getNumOnlineContacts()+')');
|
||||||
if (!$count.is(':visible')) {
|
if (!$count.is(':visible')) {
|
||||||
$count.show();
|
$count.show();
|
||||||
}
|
}
|
||||||
|
if (this.$roster.parent().length === 0) {
|
||||||
|
this.$el.append(this.$roster.show());
|
||||||
|
}
|
||||||
return this.showHideFilter();
|
return this.showHideFilter();
|
||||||
},
|
}, converse.animate ? 100 : 0),
|
||||||
|
|
||||||
render: function () {
|
render: function () {
|
||||||
this.$el.html(converse.templates.roster({
|
this.$el.html(converse.templates.roster({
|
||||||
|
@ -3871,10 +3886,47 @@
|
||||||
|
|
||||||
fetch: function () {
|
fetch: function () {
|
||||||
this.model.fetch({
|
this.model.fetch({
|
||||||
silent: true,
|
silent: true, // We use the success handler to handle groups that were added,
|
||||||
success: $.proxy(this.positionFetchedGroups, this)
|
// we need to first have all groups before positionFetchedGroups
|
||||||
|
// will work properly.
|
||||||
|
success: $.proxy(function (collection, resp, options) {
|
||||||
|
if (collection.length !== 0) {
|
||||||
|
this.positionFetchedGroups(collection, resp, options);
|
||||||
|
}
|
||||||
|
converse.roster.fetch({
|
||||||
|
add: true,
|
||||||
|
success: function (collection) {
|
||||||
|
// XXX: Bit of a hack.
|
||||||
|
// strophe.roster expects .get to be called for
|
||||||
|
// every page load so that its "items" attr
|
||||||
|
// gets populated.
|
||||||
|
// This is very inefficient for large rosters,
|
||||||
|
// and we already have the roster cached in
|
||||||
|
// sessionStorage.
|
||||||
|
// Therefore we manually populate the "items"
|
||||||
|
// attr.
|
||||||
|
// Ideally we should eventually replace
|
||||||
|
// strophe.roster with something better.
|
||||||
|
if (collection.length > 0) {
|
||||||
|
collection.each(function (item) {
|
||||||
|
converse.connection.roster.items.push({
|
||||||
|
name : item.get('fullname'),
|
||||||
|
jid : item.get('jid'),
|
||||||
|
subscription : item.get('subscription'),
|
||||||
|
ask : item.get('ask'),
|
||||||
|
groups : item.get('groups'),
|
||||||
|
resources : item.get('resources')
|
||||||
|
});
|
||||||
|
});
|
||||||
|
converse.initial_presence_sent = 1;
|
||||||
|
converse.xmppstatus.sendPresence();
|
||||||
|
} else {
|
||||||
|
converse.connection.roster.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, this)
|
||||||
});
|
});
|
||||||
converse.roster.fetch({add: true});
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -3942,7 +3994,7 @@
|
||||||
// Don't hide if user is currently filtering.
|
// Don't hide if user is currently filtering.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.$('.roster-contacts').hasScrollBar()) {
|
if (this.$roster.hasScrollBar()) {
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
$filter.show();
|
$filter.show();
|
||||||
$type.show();
|
$type.show();
|
||||||
|
@ -3957,6 +4009,7 @@
|
||||||
reset: function () {
|
reset: function () {
|
||||||
converse.roster.reset();
|
converse.roster.reset();
|
||||||
this.removeAll();
|
this.removeAll();
|
||||||
|
this.$roster = $('<dl class="roster-contacts" style="display: none;"></dl>');
|
||||||
this.render().update();
|
this.render().update();
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
@ -3964,13 +4017,24 @@
|
||||||
registerRosterHandler: function () {
|
registerRosterHandler: function () {
|
||||||
// Register handlers that depend on the roster
|
// Register handlers that depend on the roster
|
||||||
converse.connection.roster.registerCallback(
|
converse.connection.roster.registerCallback(
|
||||||
$.proxy(converse.roster.rosterHandler, converse.roster),
|
$.proxy(converse.roster.rosterHandler, converse.roster)
|
||||||
null, 'presence', null);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
registerRosterXHandler: function () {
|
registerRosterXHandler: function () {
|
||||||
|
var t = 0;
|
||||||
converse.connection.addHandler(
|
converse.connection.addHandler(
|
||||||
$.proxy(converse.roster.subscribeToSuggestedItems, converse.roster),
|
function (msg) {
|
||||||
|
window.setTimeout(
|
||||||
|
function () {
|
||||||
|
converse.connection.flush();
|
||||||
|
$.proxy(converse.roster.subscribeToSuggestedItems, converse.roster)(msg);
|
||||||
|
},
|
||||||
|
t
|
||||||
|
);
|
||||||
|
t += $(msg).find('item').length*250;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
'http://jabber.org/protocol/rosterx', 'message', null);
|
'http://jabber.org/protocol/rosterx', 'message', null);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -4047,7 +4111,7 @@
|
||||||
this.add(group.get('name'), view.render());
|
this.add(group.get('name'), view.render());
|
||||||
}
|
}
|
||||||
if (idx === 0) {
|
if (idx === 0) {
|
||||||
this.$('.roster-contacts').append(view.$el);
|
this.$roster.append(view.$el);
|
||||||
} else {
|
} else {
|
||||||
this.appendGroup(view);
|
this.appendGroup(view);
|
||||||
}
|
}
|
||||||
|
@ -4058,13 +4122,14 @@
|
||||||
/* Place the group's DOM element in the correct alphabetical
|
/* Place the group's DOM element in the correct alphabetical
|
||||||
* position amongst the other groups in the roster.
|
* position amongst the other groups in the roster.
|
||||||
*/
|
*/
|
||||||
var index = this.model.indexOf(view.model);
|
var $groups = this.$roster.find('.roster-group'),
|
||||||
|
index = $groups.length ? this.model.indexOf(view.model) : 0;
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
this.$('.roster-contacts').prepend(view.$el);
|
this.$roster.prepend(view.$el);
|
||||||
} else if (index == (this.model.length-1)) {
|
} else if (index == (this.model.length-1)) {
|
||||||
this.appendGroup(view);
|
this.appendGroup(view);
|
||||||
} else {
|
} else {
|
||||||
$(this.$('.roster-group').eq(index)).before(view.$el);
|
$($groups.eq(index)).before(view.$el);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
@ -4072,7 +4137,7 @@
|
||||||
appendGroup: function (view) {
|
appendGroup: function (view) {
|
||||||
/* Add the group at the bottom of the roster
|
/* Add the group at the bottom of the roster
|
||||||
*/
|
*/
|
||||||
var $last = this.$('.roster-group').last();
|
var $last = this.$roster.find('.roster-group').last();
|
||||||
var $siblings = $last.siblings('dd');
|
var $siblings = $last.siblings('dd');
|
||||||
if ($siblings.length > 0) {
|
if ($siblings.length > 0) {
|
||||||
$siblings.last().after(view.$el);
|
$siblings.last().after(view.$el);
|
||||||
|
@ -4563,8 +4628,6 @@
|
||||||
sid = this.session.get('sid');
|
sid = this.session.get('sid');
|
||||||
jid = this.session.get('jid');
|
jid = this.session.get('jid');
|
||||||
if (rid && jid && sid) {
|
if (rid && jid && sid) {
|
||||||
// We have the necessary tokens for resuming a session
|
|
||||||
rid += 1;
|
|
||||||
this.session.save({rid: rid}); // The RID needs to be increased with each request.
|
this.session.save({rid: rid}); // The RID needs to be increased with each request.
|
||||||
this.connection.attach(jid, sid, rid, this.onConnect);
|
this.connection.attach(jid, sid, rid, this.onConnect);
|
||||||
} else if (this.prebind) {
|
} else if (this.prebind) {
|
||||||
|
|
12
index.html
12
index.html
|
@ -229,7 +229,6 @@
|
||||||
<script type="text/javascript">try { var pageTracker = _gat._getTracker("UA-2128260-8"); pageTracker._trackPageview(); } catch(err) {}</script>
|
<script type="text/javascript">try { var pageTracker = _gat._getTracker("UA-2128260-8"); pageTracker._trackPageview(); } catch(err) {}</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Configuration loaded, so safe to make other require calls.
|
|
||||||
require(['converse'], function (converse) {
|
require(['converse'], function (converse) {
|
||||||
(function () {
|
(function () {
|
||||||
/* XXX: This function initializes jquery.easing for the https://conversejs.org
|
/* XXX: This function initializes jquery.easing for the https://conversejs.org
|
||||||
|
@ -255,14 +254,17 @@
|
||||||
})();
|
})();
|
||||||
|
|
||||||
converse.initialize({
|
converse.initialize({
|
||||||
|
allow_otr: true,
|
||||||
|
auto_list_rooms: false,
|
||||||
|
auto_subscribe: false,
|
||||||
bosh_service_url: 'https://bind.conversejs.org', // Please use this connection manager only for testing purposes
|
bosh_service_url: 'https://bind.conversejs.org', // Please use this connection manager only for testing purposes
|
||||||
i18n: locales.en, // Refer to ./locale/locales.js to see which locales are supported
|
hide_muc_server: false,
|
||||||
|
i18n: locales['en'], // Refer to ./locale/locales.js to see which locales are supported
|
||||||
keepalive: true,
|
keepalive: true,
|
||||||
play_sounds: true,
|
play_sounds: true,
|
||||||
prebind: false,
|
roster_groups: true,
|
||||||
show_controlbox_by_default: true,
|
show_controlbox_by_default: true,
|
||||||
debug: true,
|
xhr_user_search: false
|
||||||
roster_groups: true
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
17
main.js
17
main.js
|
@ -1,4 +1,4 @@
|
||||||
config = {
|
require.config({
|
||||||
baseUrl: '.',
|
baseUrl: '.',
|
||||||
paths: {
|
paths: {
|
||||||
"backbone": "components/backbone/backbone",
|
"backbone": "components/backbone/backbone",
|
||||||
|
@ -17,7 +17,7 @@ config = {
|
||||||
"strophe": "components/strophe/strophe",
|
"strophe": "components/strophe/strophe",
|
||||||
"strophe.disco": "components/strophejs-plugins/disco/strophe.disco",
|
"strophe.disco": "components/strophejs-plugins/disco/strophe.disco",
|
||||||
"strophe.muc": "components/strophe.muc/index",
|
"strophe.muc": "components/strophe.muc/index",
|
||||||
"strophe.roster": "components/strophe.roster/index",
|
"strophe.roster": "src/strophe.roster",
|
||||||
"strophe.vcard": "components/strophejs-plugins/vcard/strophe.vcard",
|
"strophe.vcard": "components/strophejs-plugins/vcard/strophe.vcard",
|
||||||
"text": 'components/requirejs-text/text',
|
"text": 'components/requirejs-text/text',
|
||||||
"tpl": 'components/requirejs-tpl-jcbrand/tpl',
|
"tpl": 'components/requirejs-tpl-jcbrand/tpl',
|
||||||
|
@ -139,16 +139,13 @@ config = {
|
||||||
'crypto.sha1': { deps: ['crypto.core'] },
|
'crypto.sha1': { deps: ['crypto.core'] },
|
||||||
'crypto.sha256': { deps: ['crypto.core'] },
|
'crypto.sha256': { deps: ['crypto.core'] },
|
||||||
'bigint': { deps: ['crypto'] },
|
'bigint': { deps: ['crypto'] },
|
||||||
|
'strophe': { exports: 'Strophe' },
|
||||||
'strophe.disco': { deps: ['strophe'] },
|
'strophe.disco': { deps: ['strophe'] },
|
||||||
'strophe.muc': { deps: ['strophe'] },
|
'strophe.muc': { deps: ['strophe'] },
|
||||||
'strophe.roster': { deps: ['strophe'] },
|
'strophe.roster': { deps: ['strophe'] },
|
||||||
'strophe.vcard': { deps: ['strophe'] }
|
'strophe.vcard': { deps: ['strophe'] }
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
require(["converse"], function(converse) {
|
||||||
if (typeof(require) !== 'undefined') {
|
window.converse = converse;
|
||||||
require.config(config);
|
});
|
||||||
require(["jquery", "converse"], function($, converse) {
|
|
||||||
window.converse = converse;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
|
@ -57,23 +57,26 @@
|
||||||
expect($("#conversejs .chatbox").length).toBe(1); // Controlbox is open
|
expect($("#conversejs .chatbox").length).toBe(1); // Controlbox is open
|
||||||
|
|
||||||
// Test that they can be trimmed
|
// Test that they can be trimmed
|
||||||
var online_contacts = this.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact').find('a.open-chat');
|
|
||||||
for (i=0; i<online_contacts.length; i++) {
|
|
||||||
$el = $(online_contacts[i]);
|
|
||||||
jid = $el.text().replace(/ /g,'.').toLowerCase() + '@localhost';
|
|
||||||
$el.click();
|
|
||||||
expect(this.chatboxviews.trimChats).toHaveBeenCalled();
|
|
||||||
|
|
||||||
chatboxview = this.chatboxviews.get(jid);
|
|
||||||
spyOn(chatboxview, 'hide').andCallThrough();
|
|
||||||
chatboxview.model.set({'minimized': true});
|
|
||||||
expect(trimmed_chatboxes.addChat).toHaveBeenCalled();
|
|
||||||
expect(chatboxview.hide).toHaveBeenCalled();
|
|
||||||
trimmedview = trimmed_chatboxes.get(jid);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that they can be maximized again
|
|
||||||
runs($.proxy(function () {
|
runs($.proxy(function () {
|
||||||
|
converse.rosterview.update(); // XXX: Hack to make sure $roster element is attaced.
|
||||||
|
}, this));
|
||||||
|
waits(50);
|
||||||
|
runs($.proxy(function () {
|
||||||
|
// Test that they can be maximized again
|
||||||
|
var online_contacts = this.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact').find('a.open-chat');
|
||||||
|
for (i=0; i<online_contacts.length; i++) {
|
||||||
|
$el = $(online_contacts[i]);
|
||||||
|
jid = $el.text().replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
|
$el.click();
|
||||||
|
expect(this.chatboxviews.trimChats).toHaveBeenCalled();
|
||||||
|
|
||||||
|
chatboxview = this.chatboxviews.get(jid);
|
||||||
|
spyOn(chatboxview, 'hide').andCallThrough();
|
||||||
|
chatboxview.model.set({'minimized': true});
|
||||||
|
expect(trimmed_chatboxes.addChat).toHaveBeenCalled();
|
||||||
|
expect(chatboxview.hide).toHaveBeenCalled();
|
||||||
|
trimmedview = trimmed_chatboxes.get(jid);
|
||||||
|
}
|
||||||
var key = this.chatboxviews.keys()[1];
|
var key = this.chatboxviews.keys()[1];
|
||||||
trimmedview = trimmed_chatboxes.get(key);
|
trimmedview = trimmed_chatboxes.get(key);
|
||||||
chatbox = trimmedview.model;
|
chatbox = trimmedview.model;
|
||||||
|
@ -99,11 +102,19 @@
|
||||||
chatbox = test_utils.openChatBoxFor(contact_jid);
|
chatbox = test_utils.openChatBoxFor(contact_jid);
|
||||||
chatboxview = this.chatboxviews.get(contact_jid);
|
chatboxview = this.chatboxviews.get(contact_jid);
|
||||||
spyOn(chatboxview, 'focus');
|
spyOn(chatboxview, 'focus');
|
||||||
$el = this.rosterview.$el.find('a.open-chat:contains("'+chatbox.get('fullname')+'")');
|
|
||||||
jid = $el.text().replace(/ /g,'.').toLowerCase() + '@localhost';
|
// Test that they can be trimmed
|
||||||
$el.click();
|
runs($.proxy(function () {
|
||||||
expect(this.chatboxes.length).toEqual(2);
|
converse.rosterview.update(); // XXX: Hack to make sure $roster element is attaced.
|
||||||
expect(chatboxview.focus).toHaveBeenCalled();
|
}, this));
|
||||||
|
waits(50);
|
||||||
|
runs($.proxy(function () {
|
||||||
|
$el = this.rosterview.$el.find('a.open-chat:contains("'+chatbox.get('fullname')+'")');
|
||||||
|
jid = $el.text().replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
|
$el.click();
|
||||||
|
expect(this.chatboxes.length).toEqual(2);
|
||||||
|
expect(chatboxview.focus).toHaveBeenCalled();
|
||||||
|
}, this));
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
it("can be saved to, and retrieved from, browserStorage", $.proxy(function () {
|
it("can be saved to, and retrieved from, browserStorage", $.proxy(function () {
|
||||||
|
|
|
@ -145,7 +145,7 @@
|
||||||
subscription: 'both'
|
subscription: 'both'
|
||||||
});
|
});
|
||||||
converse.rosterview.update(); // XXX: Will normally called as event handler
|
converse.rosterview.update(); // XXX: Will normally called as event handler
|
||||||
if (converse.rosterview.$('.roster-contacts').hasScrollBar()) {
|
if (converse.rosterview.$roster.hasScrollBar()) {
|
||||||
expect($filter.is(':visible')).toBeTruthy();
|
expect($filter.is(':visible')).toBeTruthy();
|
||||||
} else {
|
} else {
|
||||||
expect($filter.is(':visible')).toBeFalsy();
|
expect($filter.is(':visible')).toBeFalsy();
|
||||||
|
@ -154,11 +154,16 @@
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
it("can be used to filter the contacts shown", function () {
|
it("can be used to filter the contacts shown", function () {
|
||||||
converse.roster_groups = true;
|
var $filter;
|
||||||
_clearContacts();
|
var $roster;
|
||||||
utils.createGroupedContacts();
|
runs(function () {
|
||||||
var $filter = converse.rosterview.$('.roster-filter');
|
_clearContacts();
|
||||||
var $roster = converse.rosterview.$('.roster-contacts');
|
converse.roster_groups = true;
|
||||||
|
utils.createGroupedContacts();
|
||||||
|
$filter = converse.rosterview.$('.roster-filter');
|
||||||
|
$roster = converse.rosterview.$roster;
|
||||||
|
});
|
||||||
|
waits(350); // Needed, due to debounce
|
||||||
runs(function () {
|
runs(function () {
|
||||||
expect($roster.find('dd:visible').length).toBe(15);
|
expect($roster.find('dd:visible').length).toBe(15);
|
||||||
expect($roster.find('dt:visible').length).toBe(5);
|
expect($roster.find('dt:visible').length).toBe(5);
|
||||||
|
@ -199,13 +204,19 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
it("can be used to filter the groups shown", function () {
|
it("can be used to filter the groups shown", function () {
|
||||||
converse.roster_groups = true;
|
var $filter;
|
||||||
_clearContacts();
|
var $roster;
|
||||||
utils.createGroupedContacts();
|
var $type;
|
||||||
var $filter = converse.rosterview.$('.roster-filter');
|
runs(function () {
|
||||||
var $roster = converse.rosterview.$('.roster-contacts');
|
converse.roster_groups = true;
|
||||||
var $type = converse.rosterview.$('.filter-type');
|
_clearContacts();
|
||||||
$type.val('groups');
|
utils.createGroupedContacts();
|
||||||
|
$filter = converse.rosterview.$('.roster-filter');
|
||||||
|
$roster = converse.rosterview.$roster;
|
||||||
|
$type = converse.rosterview.$('.filter-type');
|
||||||
|
$type.val('groups');
|
||||||
|
});
|
||||||
|
waits(350); // Needed, due to debounce
|
||||||
runs(function () {
|
runs(function () {
|
||||||
expect($roster.find('dd:visible').length).toBe(15);
|
expect($roster.find('dd:visible').length).toBe(15);
|
||||||
expect($roster.find('dt:visible').length).toBe(5);
|
expect($roster.find('dt:visible').length).toBe(5);
|
||||||
|
@ -242,7 +253,7 @@
|
||||||
_clearContacts();
|
_clearContacts();
|
||||||
utils.createGroupedContacts();
|
utils.createGroupedContacts();
|
||||||
var $filter = converse.rosterview.$('.roster-filter');
|
var $filter = converse.rosterview.$('.roster-filter');
|
||||||
var $roster = converse.rosterview.$('.roster-contacts');
|
var $roster = converse.rosterview.$roster;
|
||||||
runs (function () {
|
runs (function () {
|
||||||
$filter.val("xxx");
|
$filter.val("xxx");
|
||||||
$filter.trigger('keydown');
|
$filter.trigger('keydown');
|
||||||
|
@ -267,56 +278,66 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
it("can be used to organize existing contacts", $.proxy(function () {
|
it("can be used to organize existing contacts", $.proxy(function () {
|
||||||
_clearContacts();
|
runs($.proxy(function () {
|
||||||
spyOn(converse, 'emit');
|
_clearContacts();
|
||||||
spyOn(this.rosterview, 'update').andCallThrough();
|
spyOn(converse, 'emit');
|
||||||
converse.rosterview.render();
|
spyOn(this.rosterview, 'update').andCallThrough();
|
||||||
utils.createContacts('pending');
|
converse.rosterview.render();
|
||||||
utils.createContacts('requesting');
|
utils.createContacts('pending');
|
||||||
utils.createGroupedContacts();
|
utils.createContacts('requesting');
|
||||||
// Check that the groups appear alphabetically and that
|
utils.createGroupedContacts();
|
||||||
// requesting and pending contacts are last.
|
}, this));
|
||||||
var group_titles = $.map(this.rosterview.$el.find('dt'), function (o) { return $(o).text().trim(); });
|
waits(50); // Needed, due to debounce
|
||||||
expect(group_titles).toEqual([
|
runs($.proxy(function () {
|
||||||
"colleagues",
|
// Check that the groups appear alphabetically and that
|
||||||
"Family",
|
// requesting and pending contacts are last.
|
||||||
"friends & acquaintences",
|
var group_titles = $.map(this.rosterview.$el.find('dt'), function (o) { return $(o).text().trim(); });
|
||||||
"ænemies",
|
expect(group_titles).toEqual([
|
||||||
"Ungrouped",
|
"colleagues",
|
||||||
"Contact requests",
|
"Family",
|
||||||
"Pending contacts"
|
"friends & acquaintences",
|
||||||
]);
|
"ænemies",
|
||||||
// Check that usernames appear alphabetically per group
|
"Ungrouped",
|
||||||
_.each(_.keys(mock.groups), $.proxy(function (name) {
|
"Contact requests",
|
||||||
var $contacts = this.rosterview.$('dt.roster-group[data-group="'+name+'"]').nextUntil('dt', 'dd');
|
"Pending contacts"
|
||||||
var names = $.map($contacts, function (o) { return $(o).text().trim(); });
|
]);
|
||||||
expect(names).toEqual(_.clone(names).sort());
|
// Check that usernames appear alphabetically per group
|
||||||
}, converse));
|
_.each(_.keys(mock.groups), $.proxy(function (name) {
|
||||||
|
var $contacts = this.rosterview.$('dt.roster-group[data-group="'+name+'"]').nextUntil('dt', 'dd');
|
||||||
|
var names = $.map($contacts, function (o) { return $(o).text().trim(); });
|
||||||
|
expect(names).toEqual(_.clone(names).sort());
|
||||||
|
}, converse));
|
||||||
|
}, this));
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
it("can share contacts with other roster groups", $.proxy(function () {
|
it("can share contacts with other roster groups", $.proxy(function () {
|
||||||
_clearContacts();
|
|
||||||
var i=0, j=0;
|
|
||||||
spyOn(converse, 'emit');
|
|
||||||
spyOn(this.rosterview, 'update').andCallThrough();
|
|
||||||
converse.rosterview.render();
|
|
||||||
var groups = ['colleagues', 'friends'];
|
var groups = ['colleagues', 'friends'];
|
||||||
for (i=0; i<mock.cur_names.length; i++) {
|
runs($.proxy(function () {
|
||||||
this.roster.create({
|
_clearContacts();
|
||||||
jid: mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost',
|
var i=0, j=0;
|
||||||
subscription: 'both',
|
spyOn(converse, 'emit');
|
||||||
ask: null,
|
spyOn(this.rosterview, 'update').andCallThrough();
|
||||||
groups: groups,
|
converse.rosterview.render();
|
||||||
fullname: mock.cur_names[i]
|
for (i=0; i<mock.cur_names.length; i++) {
|
||||||
});
|
this.roster.create({
|
||||||
}
|
jid: mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost',
|
||||||
// Check that usernames appear alphabetically per group
|
subscription: 'both',
|
||||||
_.each(groups, $.proxy(function (name) {
|
ask: null,
|
||||||
var $contacts = this.rosterview.$('dt.roster-group[data-group="'+name+'"]').nextUntil('dt', 'dd');
|
groups: groups,
|
||||||
var names = $.map($contacts, function (o) { return $(o).text().trim(); });
|
fullname: mock.cur_names[i]
|
||||||
expect(names).toEqual(_.clone(names).sort());
|
});
|
||||||
expect(names.length).toEqual(mock.cur_names.length);
|
}
|
||||||
}, converse));
|
}, this));
|
||||||
|
waits(50); // Needed, due to debounce
|
||||||
|
runs($.proxy(function () {
|
||||||
|
// Check that usernames appear alphabetically per group
|
||||||
|
_.each(groups, $.proxy(function (name) {
|
||||||
|
var $contacts = this.rosterview.$('dt.roster-group[data-group="'+name+'"]').nextUntil('dt', 'dd');
|
||||||
|
var names = $.map($contacts, function (o) { return $(o).text().trim(); });
|
||||||
|
expect(names).toEqual(_.clone(names).sort());
|
||||||
|
expect(names.length).toEqual(mock.cur_names.length);
|
||||||
|
}, this));
|
||||||
|
}, this));
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
it("remembers whether it is closed or opened", $.proxy(function () {
|
it("remembers whether it is closed or opened", $.proxy(function () {
|
||||||
|
@ -361,8 +382,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
it("can be collapsed under their own header", $.proxy(function () {
|
it("can be collapsed under their own header", $.proxy(function () {
|
||||||
_addContacts();
|
runs(function () {
|
||||||
checkHeaderToggling.apply(this, [this.rosterview.get('Pending contacts').$el]);
|
_addContacts();
|
||||||
|
});
|
||||||
|
waits(50);
|
||||||
|
runs($.proxy(function () {
|
||||||
|
checkHeaderToggling.apply(this, [this.rosterview.get('Pending contacts').$el]);
|
||||||
|
}, this));
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
it("can be added to the roster", $.proxy(function () {
|
it("can be added to the roster", $.proxy(function () {
|
||||||
|
@ -385,40 +411,62 @@
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
it("can be removed by the user", $.proxy(function () {
|
it("can be removed by the user", $.proxy(function () {
|
||||||
_addContacts();
|
runs($.proxy(function () {
|
||||||
var name = mock.pend_names[0];
|
_addContacts();
|
||||||
var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
|
}, this));
|
||||||
spyOn(window, 'confirm').andReturn(true);
|
waits(50);
|
||||||
spyOn(converse, 'emit');
|
runs($.proxy(function () {
|
||||||
spyOn(this.connection.roster, 'remove').andCallThrough();
|
/* FIXME: Monkepatch
|
||||||
spyOn(this.connection.roster, 'unauthorize');
|
* After refactoring the mock connection to use a
|
||||||
spyOn(this.rosterview.model, 'remove').andCallThrough();
|
* Strophe.Connection object, these tests fail because "remove"
|
||||||
|
* function in strophe.roster (line 292) gets called and it
|
||||||
|
* then tries to actually remove the user which is not in the roster...
|
||||||
|
*/
|
||||||
|
var old_remove = this.connection.roster.remove;
|
||||||
|
this.connection.roster.remove = function (jid, callback) { callback(); };
|
||||||
|
|
||||||
converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')")
|
var name = mock.pend_names[0];
|
||||||
.siblings('.remove-xmpp-contact').click();
|
var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
|
spyOn(window, 'confirm').andReturn(true);
|
||||||
|
spyOn(converse, 'emit');
|
||||||
|
spyOn(this.connection.roster, 'remove').andCallThrough();
|
||||||
|
spyOn(this.connection.roster, 'unauthorize');
|
||||||
|
spyOn(this.rosterview.model, 'remove').andCallThrough();
|
||||||
|
|
||||||
expect(window.confirm).toHaveBeenCalled();
|
converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')")
|
||||||
expect(this.connection.roster.remove).toHaveBeenCalled();
|
.siblings('.remove-xmpp-contact').click();
|
||||||
expect(this.connection.roster.unauthorize).toHaveBeenCalled();
|
|
||||||
expect(this.rosterview.model.remove).toHaveBeenCalled();
|
expect(window.confirm).toHaveBeenCalled();
|
||||||
expect(converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')").length).toEqual(0);
|
expect(this.connection.roster.remove).toHaveBeenCalled();
|
||||||
|
expect(this.connection.roster.unauthorize).toHaveBeenCalled();
|
||||||
|
expect(this.rosterview.model.remove).toHaveBeenCalled();
|
||||||
|
expect(converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')").length).toEqual(0);
|
||||||
|
|
||||||
|
/* XXX Restore Monkeypatch */
|
||||||
|
this.connection.roster.remove = old_remove;
|
||||||
|
}, this));
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
it("do not have a header if there aren't any", $.proxy(function () {
|
it("do not have a header if there aren't any", $.proxy(function () {
|
||||||
var name = mock.pend_names[0];
|
var name = mock.pend_names[0];
|
||||||
_clearContacts();
|
runs($.proxy(function () {
|
||||||
spyOn(window, 'confirm').andReturn(true);
|
_clearContacts();
|
||||||
this.roster.create({
|
}, this));
|
||||||
jid: name.replace(/ /g,'.').toLowerCase() + '@localhost',
|
waits(50);
|
||||||
subscription: 'none',
|
runs($.proxy(function () {
|
||||||
ask: 'subscribe',
|
spyOn(window, 'confirm').andReturn(true);
|
||||||
fullname: name
|
this.roster.create({
|
||||||
});
|
jid: name.replace(/ /g,'.').toLowerCase() + '@localhost',
|
||||||
expect(this.rosterview.get('Pending contacts').$el.is(':visible')).toEqual(true);
|
subscription: 'none',
|
||||||
converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')")
|
ask: 'subscribe',
|
||||||
.siblings('.remove-xmpp-contact').click();
|
fullname: name
|
||||||
expect(window.confirm).toHaveBeenCalled();
|
});
|
||||||
expect(this.rosterview.get('Pending contacts').$el.is(':visible')).toEqual(false);
|
expect(this.rosterview.get('Pending contacts').$el.is(':visible')).toEqual(true);
|
||||||
|
converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')")
|
||||||
|
.siblings('.remove-xmpp-contact').click();
|
||||||
|
expect(window.confirm).toHaveBeenCalled();
|
||||||
|
expect(this.rosterview.get('Pending contacts').$el.is(':visible')).toEqual(false);
|
||||||
|
}, this));
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
|
|
||||||
|
@ -467,8 +515,13 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
it("can be collapsed under their own header", $.proxy(function () {
|
it("can be collapsed under their own header", $.proxy(function () {
|
||||||
_addContacts();
|
runs(function () {
|
||||||
checkHeaderToggling.apply(this, [this.rosterview.$el.find('dt.roster-group')]);
|
_addContacts();
|
||||||
|
});
|
||||||
|
waits(50);
|
||||||
|
runs($.proxy(function () {
|
||||||
|
checkHeaderToggling.apply(this, [this.rosterview.$el.find('dt.roster-group')]);
|
||||||
|
}, this));
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
it("will be hidden when appearing under a collapsed group", $.proxy(function () {
|
it("will be hidden when appearing under a collapsed group", $.proxy(function () {
|
||||||
|
@ -488,180 +541,237 @@
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
it("can be added to the roster and they will be sorted alphabetically", $.proxy(function () {
|
it("can be added to the roster and they will be sorted alphabetically", $.proxy(function () {
|
||||||
_clearContacts();
|
runs(function () {
|
||||||
var i, t;
|
_clearContacts();
|
||||||
spyOn(converse, 'emit');
|
});
|
||||||
spyOn(this.rosterview, 'update').andCallThrough();
|
waits(50);
|
||||||
for (i=0; i<mock.cur_names.length; i++) {
|
runs($.proxy(function () {
|
||||||
this.roster.create({
|
var i, t;
|
||||||
jid: mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost',
|
spyOn(converse, 'emit');
|
||||||
subscription: 'both',
|
spyOn(this.rosterview, 'update').andCallThrough();
|
||||||
ask: null,
|
for (i=0; i<mock.cur_names.length; i++) {
|
||||||
fullname: mock.cur_names[i]
|
this.roster.create({
|
||||||
});
|
jid: mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost',
|
||||||
expect(this.rosterview.update).toHaveBeenCalled();
|
subscription: 'both',
|
||||||
}
|
ask: null,
|
||||||
// Check that they are sorted alphabetically
|
fullname: mock.cur_names[i]
|
||||||
t = this.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.offline').find('a.open-chat').text();
|
});
|
||||||
expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
|
expect(this.rosterview.update).toHaveBeenCalled();
|
||||||
|
}
|
||||||
|
// Check that they are sorted alphabetically
|
||||||
|
t = this.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.offline').find('a.open-chat').text();
|
||||||
|
expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
|
||||||
|
}, this));
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
it("can be removed by the user", $.proxy(function () {
|
it("can be removed by the user", $.proxy(function () {
|
||||||
_addContacts();
|
runs(function () {
|
||||||
var name = mock.cur_names[0];
|
_addContacts();
|
||||||
var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
|
});
|
||||||
spyOn(window, 'confirm').andReturn(true);
|
waits(50);
|
||||||
spyOn(converse, 'emit');
|
runs($.proxy(function () {
|
||||||
spyOn(this.connection.roster, 'remove').andCallThrough();
|
/* FIXME: Monkepatch
|
||||||
spyOn(this.connection.roster, 'unauthorize');
|
* After refactoring the mock connection to use a
|
||||||
spyOn(this.rosterview.model, 'remove').andCallThrough();
|
* Strophe.Connection object, these tests fail because "remove"
|
||||||
|
* function in strophe.roster (line 292) gets called and it
|
||||||
|
* then tries to actually remove the user which is not in the roster...
|
||||||
|
*/
|
||||||
|
var old_remove = this.connection.roster.remove;
|
||||||
|
this.connection.roster.remove = function (jid, callback) { callback(); };
|
||||||
|
|
||||||
converse.rosterview.$el.find(".open-chat:contains('"+name+"')")
|
var name = mock.cur_names[0];
|
||||||
.siblings('.remove-xmpp-contact').click();
|
var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
|
spyOn(window, 'confirm').andReturn(true);
|
||||||
|
spyOn(converse, 'emit');
|
||||||
|
spyOn(this.connection.roster, 'remove').andCallThrough();
|
||||||
|
spyOn(this.connection.roster, 'unauthorize');
|
||||||
|
spyOn(this.rosterview.model, 'remove').andCallThrough();
|
||||||
|
|
||||||
expect(window.confirm).toHaveBeenCalled();
|
converse.rosterview.$el.find(".open-chat:contains('"+name+"')")
|
||||||
expect(this.connection.roster.remove).toHaveBeenCalled();
|
.siblings('.remove-xmpp-contact').click();
|
||||||
expect(this.connection.roster.unauthorize).toHaveBeenCalled();
|
|
||||||
expect(this.rosterview.model.remove).toHaveBeenCalled();
|
expect(window.confirm).toHaveBeenCalled();
|
||||||
expect(converse.rosterview.$el.find(".open-chat:contains('"+name+"')").length).toEqual(0);
|
expect(this.connection.roster.remove).toHaveBeenCalled();
|
||||||
|
expect(this.connection.roster.unauthorize).toHaveBeenCalled();
|
||||||
|
expect(this.rosterview.model.remove).toHaveBeenCalled();
|
||||||
|
expect(converse.rosterview.$el.find(".open-chat:contains('"+name+"')").length).toEqual(0);
|
||||||
|
|
||||||
|
/* XXX Restore Monkeypatch */
|
||||||
|
this.connection.roster.remove = old_remove;
|
||||||
|
}, this));
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
|
|
||||||
it("do not have a header if there aren't any", $.proxy(function () {
|
it("do not have a header if there aren't any", $.proxy(function () {
|
||||||
var name = mock.cur_names[0];
|
var name = mock.cur_names[0];
|
||||||
_clearContacts();
|
runs(function () {
|
||||||
spyOn(window, 'confirm').andReturn(true);
|
_clearContacts();
|
||||||
this.roster.create({
|
|
||||||
jid: name.replace(/ /g,'.').toLowerCase() + '@localhost',
|
|
||||||
subscription: 'both',
|
|
||||||
ask: null,
|
|
||||||
fullname: name
|
|
||||||
});
|
});
|
||||||
expect(this.rosterview.$el.find('dt.roster-group').css('display')).toEqual('block');
|
waits(50);
|
||||||
converse.rosterview.$el.find(".open-chat:contains('"+name+"')")
|
runs($.proxy(function () {
|
||||||
.siblings('.remove-xmpp-contact').click();
|
spyOn(window, 'confirm').andReturn(true);
|
||||||
expect(window.confirm).toHaveBeenCalled();
|
this.roster.create({
|
||||||
expect(this.rosterview.$el.find('dt.roster-group').css('display')).toEqual('none');
|
jid: name.replace(/ /g,'.').toLowerCase() + '@localhost',
|
||||||
|
subscription: 'both',
|
||||||
|
ask: null,
|
||||||
|
fullname: name
|
||||||
|
});
|
||||||
|
expect(this.rosterview.$el.find('dt.roster-group').css('display')).toEqual('block');
|
||||||
|
converse.rosterview.$el.find(".open-chat:contains('"+name+"')")
|
||||||
|
.siblings('.remove-xmpp-contact').click();
|
||||||
|
expect(window.confirm).toHaveBeenCalled();
|
||||||
|
expect(this.rosterview.$el.find('dt.roster-group').css('display')).toEqual('none');
|
||||||
|
}, this));
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
it("can change their status to online and be sorted alphabetically", $.proxy(function () {
|
it("can change their status to online and be sorted alphabetically", $.proxy(function () {
|
||||||
_addContacts();
|
runs(function () {
|
||||||
var jid, t;
|
_addContacts();
|
||||||
spyOn(converse, 'emit');
|
});
|
||||||
spyOn(this.rosterview, 'update').andCallThrough();
|
waits(50);
|
||||||
for (i=0; i<mock.cur_names.length; i++) {
|
runs($.proxy(function () {
|
||||||
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
var jid, t;
|
||||||
this.roster.get(jid).set('chat_status', 'online');
|
spyOn(converse, 'emit');
|
||||||
expect(this.rosterview.update).toHaveBeenCalled();
|
spyOn(this.rosterview, 'update').andCallThrough();
|
||||||
// Check that they are sorted alphabetically
|
for (i=0; i<mock.cur_names.length; i++) {
|
||||||
t = this.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.online').find('a.open-chat').text();
|
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
|
this.roster.get(jid).set('chat_status', 'online');
|
||||||
}
|
expect(this.rosterview.update).toHaveBeenCalled();
|
||||||
|
// Check that they are sorted alphabetically
|
||||||
|
t = this.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.online').find('a.open-chat').text();
|
||||||
|
expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
|
||||||
|
}
|
||||||
|
}, this));
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
it("can change their status to busy and be sorted alphabetically", $.proxy(function () {
|
it("can change their status to busy and be sorted alphabetically", $.proxy(function () {
|
||||||
_addContacts();
|
runs(function () {
|
||||||
var jid, t;
|
_addContacts();
|
||||||
spyOn(converse, 'emit');
|
});
|
||||||
spyOn(this.rosterview, 'update').andCallThrough();
|
waits(50);
|
||||||
for (i=0; i<mock.cur_names.length; i++) {
|
runs($.proxy(function () {
|
||||||
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
var jid, t;
|
||||||
this.roster.get(jid).set('chat_status', 'dnd');
|
spyOn(converse, 'emit');
|
||||||
expect(this.rosterview.update).toHaveBeenCalled();
|
spyOn(this.rosterview, 'update').andCallThrough();
|
||||||
// Check that they are sorted alphabetically
|
for (i=0; i<mock.cur_names.length; i++) {
|
||||||
t = this.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.dnd').find('a.open-chat').text();
|
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
|
this.roster.get(jid).set('chat_status', 'dnd');
|
||||||
}
|
expect(this.rosterview.update).toHaveBeenCalled();
|
||||||
|
// Check that they are sorted alphabetically
|
||||||
|
t = this.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.dnd').find('a.open-chat').text();
|
||||||
|
expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
|
||||||
|
}
|
||||||
|
}, this));
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
it("can change their status to away and be sorted alphabetically", $.proxy(function () {
|
it("can change their status to away and be sorted alphabetically", $.proxy(function () {
|
||||||
_addContacts();
|
runs(function () {
|
||||||
var jid, t;
|
_addContacts();
|
||||||
spyOn(converse, 'emit');
|
});
|
||||||
spyOn(this.rosterview, 'update').andCallThrough();
|
waits(50);
|
||||||
for (i=0; i<mock.cur_names.length; i++) {
|
runs($.proxy(function () {
|
||||||
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
var jid, t;
|
||||||
this.roster.get(jid).set('chat_status', 'away');
|
spyOn(converse, 'emit');
|
||||||
expect(this.rosterview.update).toHaveBeenCalled();
|
spyOn(this.rosterview, 'update').andCallThrough();
|
||||||
// Check that they are sorted alphabetically
|
for (i=0; i<mock.cur_names.length; i++) {
|
||||||
t = this.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.away').find('a.open-chat').text();
|
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
|
this.roster.get(jid).set('chat_status', 'away');
|
||||||
}
|
expect(this.rosterview.update).toHaveBeenCalled();
|
||||||
|
// Check that they are sorted alphabetically
|
||||||
|
t = this.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.away').find('a.open-chat').text();
|
||||||
|
expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
|
||||||
|
}
|
||||||
|
}, this));
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
it("can change their status to xa and be sorted alphabetically", $.proxy(function () {
|
it("can change their status to xa and be sorted alphabetically", $.proxy(function () {
|
||||||
_addContacts();
|
runs(function () {
|
||||||
var jid, t;
|
_addContacts();
|
||||||
spyOn(converse, 'emit');
|
});
|
||||||
spyOn(this.rosterview, 'update').andCallThrough();
|
waits(50);
|
||||||
for (i=0; i<mock.cur_names.length; i++) {
|
runs($.proxy(function () {
|
||||||
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
var jid, t;
|
||||||
this.roster.get(jid).set('chat_status', 'xa');
|
spyOn(converse, 'emit');
|
||||||
expect(this.rosterview.update).toHaveBeenCalled();
|
spyOn(this.rosterview, 'update').andCallThrough();
|
||||||
// Check that they are sorted alphabetically
|
for (i=0; i<mock.cur_names.length; i++) {
|
||||||
t = this.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.xa').find('a.open-chat').text();
|
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
|
this.roster.get(jid).set('chat_status', 'xa');
|
||||||
}
|
expect(this.rosterview.update).toHaveBeenCalled();
|
||||||
|
// Check that they are sorted alphabetically
|
||||||
|
t = this.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.xa').find('a.open-chat').text();
|
||||||
|
expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
|
||||||
|
}
|
||||||
|
}, this));
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
it("can change their status to unavailable and be sorted alphabetically", $.proxy(function () {
|
it("can change their status to unavailable and be sorted alphabetically", $.proxy(function () {
|
||||||
_addContacts();
|
runs(function () {
|
||||||
var jid, t;
|
_addContacts();
|
||||||
spyOn(converse, 'emit');
|
});
|
||||||
spyOn(this.rosterview, 'update').andCallThrough();
|
waits(50);
|
||||||
for (i=0; i<mock.cur_names.length; i++) {
|
runs($.proxy(function () {
|
||||||
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
var jid, t;
|
||||||
this.roster.get(jid).set('chat_status', 'unavailable');
|
spyOn(converse, 'emit');
|
||||||
expect(this.rosterview.update).toHaveBeenCalled();
|
spyOn(this.rosterview, 'update').andCallThrough();
|
||||||
// Check that they are sorted alphabetically
|
for (i=0; i<mock.cur_names.length; i++) {
|
||||||
t = this.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.unavailable').find('a.open-chat').text();
|
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
expect(t).toEqual(mock.cur_names.slice(0, i+1).sort().join(''));
|
this.roster.get(jid).set('chat_status', 'unavailable');
|
||||||
}
|
expect(this.rosterview.update).toHaveBeenCalled();
|
||||||
|
// Check that they are sorted alphabetically
|
||||||
|
t = this.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.unavailable').find('a.open-chat').text();
|
||||||
|
expect(t).toEqual(mock.cur_names.slice(0, i+1).sort().join(''));
|
||||||
|
}
|
||||||
|
}, this));
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
it("are ordered according to status: online, busy, away, xa, unavailable, offline", $.proxy(function () {
|
it("are ordered according to status: online, busy, away, xa, unavailable, offline", $.proxy(function () {
|
||||||
_addContacts();
|
runs(function () {
|
||||||
var i;
|
_addContacts();
|
||||||
for (i=0; i<3; i++) {
|
});
|
||||||
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
waits(50);
|
||||||
this.roster.get(jid).set('chat_status', 'online');
|
runs($.proxy(function () {
|
||||||
}
|
var i;
|
||||||
for (i=3; i<6; i++) {
|
for (i=0; i<3; i++) {
|
||||||
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
this.roster.get(jid).set('chat_status', 'dnd');
|
this.roster.get(jid).set('chat_status', 'online');
|
||||||
}
|
}
|
||||||
for (i=6; i<9; i++) {
|
for (i=3; i<6; i++) {
|
||||||
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
this.roster.get(jid).set('chat_status', 'away');
|
this.roster.get(jid).set('chat_status', 'dnd');
|
||||||
}
|
}
|
||||||
for (i=9; i<12; i++) {
|
for (i=6; i<9; i++) {
|
||||||
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
this.roster.get(jid).set('chat_status', 'xa');
|
this.roster.get(jid).set('chat_status', 'away');
|
||||||
}
|
}
|
||||||
for (i=12; i<15; i++) {
|
for (i=9; i<12; i++) {
|
||||||
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
this.roster.get(jid).set('chat_status', 'unavailable');
|
this.roster.get(jid).set('chat_status', 'xa');
|
||||||
}
|
}
|
||||||
|
for (i=12; i<15; i++) {
|
||||||
|
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
|
this.roster.get(jid).set('chat_status', 'unavailable');
|
||||||
|
}
|
||||||
|
|
||||||
var contacts = this.rosterview.$el.find('dd.current-xmpp-contact');
|
var contacts = this.rosterview.$el.find('dd.current-xmpp-contact');
|
||||||
for (i=0; i<3; i++) {
|
for (i=0; i<3; i++) {
|
||||||
expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('online');
|
expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('online');
|
||||||
}
|
}
|
||||||
for (i=3; i<6; i++) {
|
for (i=3; i<6; i++) {
|
||||||
expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('dnd');
|
expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('dnd');
|
||||||
}
|
}
|
||||||
for (i=6; i<9; i++) {
|
for (i=6; i<9; i++) {
|
||||||
expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('away');
|
expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('away');
|
||||||
}
|
}
|
||||||
for (i=9; i<12; i++) {
|
for (i=9; i<12; i++) {
|
||||||
expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('xa');
|
expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('xa');
|
||||||
}
|
}
|
||||||
for (i=12; i<15; i++) {
|
for (i=12; i<15; i++) {
|
||||||
expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('unavailable');
|
expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('unavailable');
|
||||||
}
|
}
|
||||||
for (i=15; i<mock.cur_names.length; i++) {
|
for (i=15; i<mock.cur_names.length; i++) {
|
||||||
expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('offline');
|
expect($(contacts[i]).attr('class').split(' ',1)[0]).toEqual('offline');
|
||||||
}
|
}
|
||||||
|
}, this));
|
||||||
}, converse));
|
}, converse));
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
|
@ -713,20 +823,25 @@
|
||||||
it("do not have a header if there aren't any", $.proxy(function () {
|
it("do not have a header if there aren't any", $.proxy(function () {
|
||||||
converse.rosterview.model.reset(); // We want to manually create users so that we can spy
|
converse.rosterview.model.reset(); // We want to manually create users so that we can spy
|
||||||
var name = mock.req_names[0];
|
var name = mock.req_names[0];
|
||||||
spyOn(window, 'confirm').andReturn(true);
|
runs($.proxy(function () {
|
||||||
this.roster.create({
|
spyOn(window, 'confirm').andReturn(true);
|
||||||
jid: name.replace(/ /g,'.').toLowerCase() + '@localhost',
|
this.roster.create({
|
||||||
subscription: 'none',
|
jid: name.replace(/ /g,'.').toLowerCase() + '@localhost',
|
||||||
ask: null,
|
subscription: 'none',
|
||||||
requesting: true,
|
ask: null,
|
||||||
fullname: name
|
requesting: true,
|
||||||
});
|
fullname: name
|
||||||
expect(this.rosterview.get('Contact requests').$el.is(':visible')).toEqual(true);
|
});
|
||||||
converse.rosterview.$el.find(".req-contact-name:contains('"+name+"')")
|
}, this));
|
||||||
.siblings('.request-actions')
|
waits(50);
|
||||||
.find('.decline-xmpp-request').click();
|
runs($.proxy(function () {
|
||||||
expect(window.confirm).toHaveBeenCalled();
|
expect(this.rosterview.get('Contact requests').$el.is(':visible')).toEqual(true);
|
||||||
expect(this.rosterview.get('Contact requests').$el.is(':visible')).toEqual(false);
|
converse.rosterview.$el.find(".req-contact-name:contains('"+name+"')")
|
||||||
|
.siblings('.request-actions')
|
||||||
|
.find('.decline-xmpp-request').click();
|
||||||
|
expect(window.confirm).toHaveBeenCalled();
|
||||||
|
expect(this.rosterview.get('Contact requests').$el.is(':visible')).toEqual(false);
|
||||||
|
}, this));
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
it("can be collapsed under their own header", $.proxy(function () {
|
it("can be collapsed under their own header", $.proxy(function () {
|
||||||
|
@ -750,20 +865,70 @@
|
||||||
|
|
||||||
it("can have their requests denied by the user", $.proxy(function () {
|
it("can have their requests denied by the user", $.proxy(function () {
|
||||||
this.rosterview.model.reset();
|
this.rosterview.model.reset();
|
||||||
spyOn(converse, 'emit');
|
runs($.proxy(function () {
|
||||||
spyOn(this.connection.roster, 'unauthorize');
|
spyOn(converse, 'emit');
|
||||||
spyOn(window, 'confirm').andReturn(true);
|
spyOn(this.connection.roster, 'unauthorize');
|
||||||
utils.createContacts('requesting').openControlBox();
|
spyOn(window, 'confirm').andReturn(true);
|
||||||
var name = mock.req_names.sort()[1];
|
utils.createContacts('requesting').openControlBox();
|
||||||
var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
|
converse.rosterview.update(); // XXX: Hack to make sure $roster element is attaced.
|
||||||
converse.rosterview.$el.find(".req-contact-name:contains('"+name+"')")
|
}, this));
|
||||||
.siblings('.request-actions')
|
waits(50);
|
||||||
.find('.decline-xmpp-request').click();
|
runs($.proxy(function () {
|
||||||
expect(window.confirm).toHaveBeenCalled();
|
var name = mock.req_names.sort()[1];
|
||||||
expect(this.connection.roster.unauthorize).toHaveBeenCalled();
|
converse.rosterview.$el.find(".req-contact-name:contains('"+name+"')")
|
||||||
// There should now be one less contact
|
.siblings('.request-actions')
|
||||||
expect(this.roster.length).toEqual(mock.req_names.length-1);
|
.find('.decline-xmpp-request').click();
|
||||||
|
}, this));
|
||||||
|
waits(50);
|
||||||
|
runs($.proxy(function () {
|
||||||
|
expect(window.confirm).toHaveBeenCalled();
|
||||||
|
expect(this.connection.roster.unauthorize).toHaveBeenCalled();
|
||||||
|
// There should now be one less contact
|
||||||
|
expect(this.roster.length).toEqual(mock.req_names.length-1);
|
||||||
|
}, this));
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
|
it("are persisted even if other contacts' change their presence ", $.proxy(function() {
|
||||||
|
/* This is a regression test.
|
||||||
|
* https://github.com/jcbrand/converse.js/issues/262
|
||||||
|
*/
|
||||||
|
this.rosterview.model.reset();
|
||||||
|
spyOn(this.roster, 'clearCache').andCallThrough();
|
||||||
|
expect(this.roster.pluck('jid').length).toBe(0);
|
||||||
|
|
||||||
|
var stanza = $pres({from: 'data@enterprise/resource', type: 'subscribe'});
|
||||||
|
this.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
|
expect(this.roster.pluck('jid').length).toBe(1);
|
||||||
|
expect(_.contains(this.roster.pluck('jid'), 'data@enterprise')).toBeTruthy();
|
||||||
|
|
||||||
|
// Taken from the spec
|
||||||
|
// http://xmpp.org/rfcs/rfc3921.html#rfc.section.7.3
|
||||||
|
stanza = $iq({
|
||||||
|
to: this.connection.jid,
|
||||||
|
type: 'result',
|
||||||
|
id: 'roster_1'
|
||||||
|
}).c('query', {
|
||||||
|
xmlns: 'jabber:iq:roster',
|
||||||
|
}).c('item', {
|
||||||
|
jid: 'romeo@example.net',
|
||||||
|
name: 'Romeo',
|
||||||
|
subscription:'both'
|
||||||
|
}).c('group').t('Friends').up().up()
|
||||||
|
.c('item', {
|
||||||
|
jid: 'mercutio@example.org',
|
||||||
|
name: 'Mercutio',
|
||||||
|
subscription:'from'
|
||||||
|
}).c('group').t('Friends').up().up()
|
||||||
|
.c('item', {
|
||||||
|
jid: 'benvolio@example.org',
|
||||||
|
name: 'Benvolio',
|
||||||
|
subscription:'both'
|
||||||
|
}).c('group').t('Friends');
|
||||||
|
this.connection.roster._onReceiveRosterSuccess(null, stanza.tree());
|
||||||
|
expect(this.roster.clearCache).toHaveBeenCalled();
|
||||||
|
expect(_.contains(this.roster.pluck('jid'), 'data@enterprise')).toBeTruthy();
|
||||||
|
}, converse));
|
||||||
|
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
describe("All Contacts", $.proxy(function () {
|
describe("All Contacts", $.proxy(function () {
|
||||||
|
@ -775,7 +940,7 @@
|
||||||
}, converse));
|
}, converse));
|
||||||
|
|
||||||
it("are saved to, and can be retrieved from, browserStorage", $.proxy(function () {
|
it("are saved to, and can be retrieved from, browserStorage", $.proxy(function () {
|
||||||
var new_attrs, old_attrs, attrs, old_roster;
|
var new_attrs, old_attrs, attrs;
|
||||||
var num_contacts = this.roster.length;
|
var num_contacts = this.roster.length;
|
||||||
new_roster = new this.RosterContacts();
|
new_roster = new this.RosterContacts();
|
||||||
// Roster items are yet to be fetched from browserStorage
|
// Roster items are yet to be fetched from browserStorage
|
||||||
|
|
71
spec/profiling.js
Normal file
71
spec/profiling.js
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
(function (root, factory) {
|
||||||
|
define([
|
||||||
|
"jquery",
|
||||||
|
"mock",
|
||||||
|
"test_utils"
|
||||||
|
], function ($, mock, test_utils) {
|
||||||
|
return factory($, mock, test_utils);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} (this, function ($, mock, test_utils) {
|
||||||
|
describe("Profiling", function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
converse.connection.roster.items = [];
|
||||||
|
converse.connection._changeConnectStatus(Strophe.Status.CONNECTED);
|
||||||
|
});
|
||||||
|
|
||||||
|
xit("adds hundreds of contacts to the roster", $.proxy(function() {
|
||||||
|
converse.roster_groups = false;
|
||||||
|
spyOn(this.roster, 'clearCache').andCallThrough();
|
||||||
|
expect(this.roster.pluck('jid').length).toBe(0);
|
||||||
|
var stanza = $iq({
|
||||||
|
to: this.connection.jid,
|
||||||
|
type: 'result',
|
||||||
|
id: 'roster_1'
|
||||||
|
}).c('query', {
|
||||||
|
xmlns: 'jabber:iq:roster'
|
||||||
|
});
|
||||||
|
_.each(['Friends', 'Colleagues', 'Family', 'Acquaintances'], function (group) {
|
||||||
|
var i;
|
||||||
|
for (i=0; i<100; i++) {
|
||||||
|
stanza = stanza.c('item', {
|
||||||
|
jid: Math.random().toString().replace('0.', '')+'@example.net',
|
||||||
|
subscription:'both'
|
||||||
|
}).c('group').t(group).up().up();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.connection.roster._onReceiveRosterSuccess(null, stanza.tree());
|
||||||
|
expect(this.roster.clearCache).toHaveBeenCalled();
|
||||||
|
expect(this.roster.pluck('jid').length).toBe(400);
|
||||||
|
}, converse));
|
||||||
|
|
||||||
|
xit("adds hundreds of contacts to the roster, with roster groups", $.proxy(function() {
|
||||||
|
// converse.show_only_online_users = true;
|
||||||
|
converse.roster_groups = true;
|
||||||
|
spyOn(this.roster, 'clearCache').andCallThrough();
|
||||||
|
expect(this.roster.pluck('jid').length).toBe(0);
|
||||||
|
var stanza = $iq({
|
||||||
|
to: this.connection.jid,
|
||||||
|
type: 'result',
|
||||||
|
id: 'roster_1'
|
||||||
|
}).c('query', {
|
||||||
|
xmlns: 'jabber:iq:roster'
|
||||||
|
});
|
||||||
|
_.each(['Friends', 'Colleagues', 'Family', 'Acquaintances'], function (group) {
|
||||||
|
var i;
|
||||||
|
for (i=0; i<100; i++) {
|
||||||
|
stanza = stanza.c('item', {
|
||||||
|
jid: Math.random().toString().replace('0.', '')+'@example.net',
|
||||||
|
subscription:'both'
|
||||||
|
}).c('group').t(group).up().up();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.connection.roster._onReceiveRosterSuccess(null, stanza.tree());
|
||||||
|
expect(this.roster.clearCache).toHaveBeenCalled();
|
||||||
|
//expect(this.roster.pluck('jid').length).toBe(400);
|
||||||
|
}, converse));
|
||||||
|
|
||||||
|
it("contacts in a very large roster change their statuses", $.proxy(function() {
|
||||||
|
}, converse));
|
||||||
|
});
|
||||||
|
}));
|
|
@ -19,77 +19,9 @@
|
||||||
// be an unresolvable cyclic dependency.
|
// be an unresolvable cyclic dependency.
|
||||||
'jquery-private': { 'jquery': 'jquery' }
|
'jquery-private': { 'jquery': 'jquery' }
|
||||||
},
|
},
|
||||||
|
mainConfigFile: '../main.js',
|
||||||
paths: {
|
paths: {
|
||||||
"backbone": "components/backbone/backbone",
|
|
||||||
"backbone.browserStorage": "components/backbone.browserStorage/backbone.browserStorage",
|
|
||||||
"backbone.overview": "components/backbone.overview/backbone.overview",
|
|
||||||
"bootstrap": "components/bootstrap/dist/js/bootstrap", // XXX: Only required for https://conversejs.org website
|
|
||||||
"converse-dependencies": "src/deps-no-otr",
|
"converse-dependencies": "src/deps-no-otr",
|
||||||
"converse-templates": "src/templates",
|
"locales": "locale/nolocales"
|
||||||
"eventemitter": "components/otr/build/dep/eventemitter",
|
|
||||||
"jquery": "components/jquery/dist/jquery",
|
|
||||||
"jquery-private": "src/jquery-private",
|
|
||||||
"jquery.browser": "components/jquery.browser/index",
|
|
||||||
"jquery.easing": "components/jquery-easing-original/index", // XXX: Only required for https://conversejs.org website
|
|
||||||
"moment": "components/momentjs/moment",
|
|
||||||
"strophe": "components/strophe/strophe",
|
|
||||||
"strophe.disco": "components/strophe.disco/index",
|
|
||||||
"strophe.muc": "components/strophe.muc/index",
|
|
||||||
"strophe.roster": "components/strophe.roster/index",
|
|
||||||
"strophe.vcard": "components/strophe.vcard/index",
|
|
||||||
"text": 'components/requirejs-text/text',
|
|
||||||
"tpl": 'components/requirejs-tpl-jcbrand/tpl',
|
|
||||||
"typeahead": "components/typeahead.js/index",
|
|
||||||
"underscore": "components/underscore/underscore",
|
|
||||||
"utils": "src/utils",
|
|
||||||
|
|
||||||
// Locales paths
|
|
||||||
"locales": "locale/nolocales",
|
|
||||||
"jed": "components/jed/jed",
|
|
||||||
|
|
||||||
// Templates
|
|
||||||
"action": "src/templates/action",
|
|
||||||
"add_contact_dropdown": "src/templates/add_contact_dropdown",
|
|
||||||
"add_contact_form": "src/templates/add_contact_form",
|
|
||||||
"change_status_message": "src/templates/change_status_message",
|
|
||||||
"chat_status": "src/templates/chat_status",
|
|
||||||
"chatarea": "src/templates/chatarea",
|
|
||||||
"chatbox": "src/templates/chatbox",
|
|
||||||
"chatroom": "src/templates/chatroom",
|
|
||||||
"chatroom_password_form": "src/templates/chatroom_password_form",
|
|
||||||
"chatroom_sidebar": "src/templates/chatroom_sidebar",
|
|
||||||
"chatrooms_tab": "src/templates/chatrooms_tab",
|
|
||||||
"chats_panel": "src/templates/chats_panel",
|
|
||||||
"choose_status": "src/templates/choose_status",
|
|
||||||
"contacts_panel": "src/templates/contacts_panel",
|
|
||||||
"contacts_tab": "src/templates/contacts_tab",
|
|
||||||
"controlbox": "src/templates/controlbox",
|
|
||||||
"controlbox_toggle": "src/templates/controlbox_toggle",
|
|
||||||
"field": "src/templates/field",
|
|
||||||
"form_checkbox": "src/templates/form_checkbox",
|
|
||||||
"form_input": "src/templates/form_input",
|
|
||||||
"form_select": "src/templates/form_select",
|
|
||||||
"group_header": "src/templates/group_header",
|
|
||||||
"info": "src/templates/info",
|
|
||||||
"login_panel": "src/templates/login_panel",
|
|
||||||
"login_tab": "src/templates/login_tab",
|
|
||||||
"message": "src/templates/message",
|
|
||||||
"new_day": "src/templates/new_day",
|
|
||||||
"occupant": "src/templates/occupant",
|
|
||||||
"pending_contact": "src/templates/pending_contact",
|
|
||||||
"pending_contacts": "src/templates/pending_contacts",
|
|
||||||
"requesting_contact": "src/templates/requesting_contact",
|
|
||||||
"requesting_contacts": "src/templates/requesting_contacts",
|
|
||||||
"room_description": "src/templates/room_description",
|
|
||||||
"room_item": "src/templates/room_item",
|
|
||||||
"room_panel": "src/templates/room_panel",
|
|
||||||
"roster": "src/templates/roster",
|
|
||||||
"roster_item": "src/templates/roster_item",
|
|
||||||
"search_contact": "src/templates/search_contact",
|
|
||||||
"select_option": "src/templates/select_option",
|
|
||||||
"status_option": "src/templates/status_option",
|
|
||||||
"toggle_chats": "src/templates/toggle_chats",
|
|
||||||
"toolbar": "src/templates/toolbar",
|
|
||||||
"trimmed_chat": "src/templates/trimmed_chat"
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -19,89 +19,8 @@
|
||||||
// be an unresolvable cyclic dependency.
|
// be an unresolvable cyclic dependency.
|
||||||
'jquery-private': { 'jquery': 'jquery' }
|
'jquery-private': { 'jquery': 'jquery' }
|
||||||
},
|
},
|
||||||
|
mainConfigFile: '../main.js',
|
||||||
paths: {
|
paths: {
|
||||||
"backbone": "components/backbone/backbone",
|
"converse-dependencies": "src/deps-no-otr"
|
||||||
"backbone.browserStorage": "components/backbone.browserStorage/backbone.browserStorage",
|
|
||||||
"backbone.overview": "components/backbone.overview/backbone.overview",
|
|
||||||
"converse-dependencies": "src/deps-no-otr",
|
|
||||||
"converse-templates": "src/templates",
|
|
||||||
"eventemitter": "components/otr/build/dep/eventemitter",
|
|
||||||
"jquery": "components/jquery/dist/jquery",
|
|
||||||
"jquery-private": "src/jquery-private",
|
|
||||||
"jquery.browser": "components/jquery.browser/index",
|
|
||||||
"moment": "components/momentjs/moment",
|
|
||||||
"strophe": "components/strophe/strophe",
|
|
||||||
"strophe.disco": "components/strophe.disco/index",
|
|
||||||
"strophe.muc": "components/strophe.muc/index",
|
|
||||||
"strophe.roster": "components/strophe.roster/index",
|
|
||||||
"strophe.vcard": "components/strophe.vcard/index",
|
|
||||||
"text": 'components/requirejs-text/text',
|
|
||||||
"tpl": 'components/requirejs-tpl-jcbrand/tpl',
|
|
||||||
"typeahead": "components/typeahead.js/index",
|
|
||||||
"underscore": "components/underscore/underscore",
|
|
||||||
"utils": "src/utils",
|
|
||||||
|
|
||||||
// Locales paths
|
|
||||||
"locales": "locale/locales",
|
|
||||||
"jed": "components/jed/jed",
|
|
||||||
"af": "locale/af/LC_MESSAGES/af",
|
|
||||||
"de": "locale/de/LC_MESSAGES/de",
|
|
||||||
"en": "locale/en/LC_MESSAGES/en",
|
|
||||||
"es": "locale/es/LC_MESSAGES/es",
|
|
||||||
"fr": "locale/fr/LC_MESSAGES/fr",
|
|
||||||
"he": "locale/he/LC_MESSAGES/he",
|
|
||||||
"hu": "locale/hu/LC_MESSAGES/hu",
|
|
||||||
"id": "locale/id/LC_MESSAGES/id",
|
|
||||||
"it": "locale/it/LC_MESSAGES/it",
|
|
||||||
"ja": "locale/ja/LC_MESSAGES/ja",
|
|
||||||
"nl": "locale/nl/LC_MESSAGES/nl",
|
|
||||||
"pt_BR": "locale/pt_BR/LC_MESSAGES/pt_BR",
|
|
||||||
"ru": "locale/ru/LC_MESSAGES/ru",
|
|
||||||
"zh": "locale/zh/LC_MESSAGES/zh",
|
|
||||||
|
|
||||||
// Templates
|
|
||||||
"action": "src/templates/action",
|
|
||||||
"add_contact_dropdown": "src/templates/add_contact_dropdown",
|
|
||||||
"add_contact_form": "src/templates/add_contact_form",
|
|
||||||
"change_status_message": "src/templates/change_status_message",
|
|
||||||
"chat_status": "src/templates/chat_status",
|
|
||||||
"chatarea": "src/templates/chatarea",
|
|
||||||
"chatbox": "src/templates/chatbox",
|
|
||||||
"chatroom": "src/templates/chatroom",
|
|
||||||
"chatroom_password_form": "src/templates/chatroom_password_form",
|
|
||||||
"chatroom_sidebar": "src/templates/chatroom_sidebar",
|
|
||||||
"chatrooms_tab": "src/templates/chatrooms_tab",
|
|
||||||
"chats_panel": "src/templates/chats_panel",
|
|
||||||
"choose_status": "src/templates/choose_status",
|
|
||||||
"contacts_panel": "src/templates/contacts_panel",
|
|
||||||
"contacts_tab": "src/templates/contacts_tab",
|
|
||||||
"controlbox": "src/templates/controlbox",
|
|
||||||
"controlbox_toggle": "src/templates/controlbox_toggle",
|
|
||||||
"field": "src/templates/field",
|
|
||||||
"form_checkbox": "src/templates/form_checkbox",
|
|
||||||
"form_input": "src/templates/form_input",
|
|
||||||
"form_select": "src/templates/form_select",
|
|
||||||
"group_header": "src/templates/group_header",
|
|
||||||
"info": "src/templates/info",
|
|
||||||
"login_panel": "src/templates/login_panel",
|
|
||||||
"login_tab": "src/templates/login_tab",
|
|
||||||
"message": "src/templates/message",
|
|
||||||
"new_day": "src/templates/new_day",
|
|
||||||
"occupant": "src/templates/occupant",
|
|
||||||
"pending_contact": "src/templates/pending_contact",
|
|
||||||
"pending_contacts": "src/templates/pending_contacts",
|
|
||||||
"requesting_contact": "src/templates/requesting_contact",
|
|
||||||
"requesting_contacts": "src/templates/requesting_contacts",
|
|
||||||
"room_description": "src/templates/room_description",
|
|
||||||
"room_item": "src/templates/room_item",
|
|
||||||
"room_panel": "src/templates/room_panel",
|
|
||||||
"roster": "src/templates/roster",
|
|
||||||
"roster_item": "src/templates/roster_item",
|
|
||||||
"search_contact": "src/templates/search_contact",
|
|
||||||
"select_option": "src/templates/select_option",
|
|
||||||
"status_option": "src/templates/status_option",
|
|
||||||
"toggle_chats": "src/templates/toggle_chats",
|
|
||||||
"toolbar": "src/templates/toolbar",
|
|
||||||
"trimmed_chat": "src/templates/trimmed_chat"
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -19,91 +19,8 @@
|
||||||
// be an unresolvable cyclic dependency.
|
// be an unresolvable cyclic dependency.
|
||||||
'jquery-private': { 'jquery': 'jquery' }
|
'jquery-private': { 'jquery': 'jquery' }
|
||||||
},
|
},
|
||||||
|
mainConfigFile: '../main.js',
|
||||||
paths: {
|
paths: {
|
||||||
"backbone": "components/backbone/backbone",
|
"converse-dependencies": "src/deps-website-no-otr"
|
||||||
"backbone.browserStorage": "components/backbone.browserStorage/backbone.browserStorage",
|
|
||||||
"backbone.overview": "components/backbone.overview/backbone.overview",
|
|
||||||
"bootstrapJS": "components/bootstrapJS/index", // XXX: Only required for https://conversejs.org website
|
|
||||||
"converse-dependencies": "src/deps-website-no-otr",
|
|
||||||
"converse-templates": "src/templates",
|
|
||||||
"eventemitter": "components/otr/build/dep/eventemitter",
|
|
||||||
"jquery": "components/jquery/dist/jquery",
|
|
||||||
"jquery-private": "src/jquery-private",
|
|
||||||
"jquery.browser": "components/jquery.browser/index",
|
|
||||||
"jquery.easing": "components/jquery-easing-original/index", // XXX: Only required for https://conversejs.org website
|
|
||||||
"moment": "components/momentjs/moment",
|
|
||||||
"strophe": "components/strophe/strophe",
|
|
||||||
"strophe.disco": "components/strophe.disco/index",
|
|
||||||
"strophe.muc": "components/strophe.muc/index",
|
|
||||||
"strophe.roster": "components/strophe.roster/index",
|
|
||||||
"strophe.vcard": "components/strophe.vcard/index",
|
|
||||||
"text": 'components/requirejs-text/text',
|
|
||||||
"tpl": 'components/requirejs-tpl-jcbrand/tpl',
|
|
||||||
"typeahead": "components/typeahead.js/index",
|
|
||||||
"underscore": "components/underscore/underscore",
|
|
||||||
"utils": "src/utils",
|
|
||||||
|
|
||||||
// Locales paths
|
|
||||||
"locales": "locale/locales",
|
|
||||||
"jed": "components/jed/jed",
|
|
||||||
"af": "locale/af/LC_MESSAGES/af",
|
|
||||||
"de": "locale/de/LC_MESSAGES/de",
|
|
||||||
"en": "locale/en/LC_MESSAGES/en",
|
|
||||||
"es": "locale/es/LC_MESSAGES/es",
|
|
||||||
"fr": "locale/fr/LC_MESSAGES/fr",
|
|
||||||
"he": "locale/he/LC_MESSAGES/he",
|
|
||||||
"hu": "locale/hu/LC_MESSAGES/hu",
|
|
||||||
"id": "locale/id/LC_MESSAGES/id",
|
|
||||||
"it": "locale/it/LC_MESSAGES/it",
|
|
||||||
"ja": "locale/ja/LC_MESSAGES/ja",
|
|
||||||
"nl": "locale/nl/LC_MESSAGES/nl",
|
|
||||||
"pt_BR": "locale/pt_BR/LC_MESSAGES/pt_BR",
|
|
||||||
"ru": "locale/ru/LC_MESSAGES/ru",
|
|
||||||
"zh": "locale/zh/LC_MESSAGES/zh",
|
|
||||||
|
|
||||||
// Templates
|
|
||||||
"action": "src/templates/action",
|
|
||||||
"add_contact_dropdown": "src/templates/add_contact_dropdown",
|
|
||||||
"add_contact_form": "src/templates/add_contact_form",
|
|
||||||
"change_status_message": "src/templates/change_status_message",
|
|
||||||
"chat_status": "src/templates/chat_status",
|
|
||||||
"chatarea": "src/templates/chatarea",
|
|
||||||
"chatbox": "src/templates/chatbox",
|
|
||||||
"chatroom": "src/templates/chatroom",
|
|
||||||
"chatroom_password_form": "src/templates/chatroom_password_form",
|
|
||||||
"chatroom_sidebar": "src/templates/chatroom_sidebar",
|
|
||||||
"chatrooms_tab": "src/templates/chatrooms_tab",
|
|
||||||
"chats_panel": "src/templates/chats_panel",
|
|
||||||
"choose_status": "src/templates/choose_status",
|
|
||||||
"contacts_panel": "src/templates/contacts_panel",
|
|
||||||
"contacts_tab": "src/templates/contacts_tab",
|
|
||||||
"controlbox": "src/templates/controlbox",
|
|
||||||
"controlbox_toggle": "src/templates/controlbox_toggle",
|
|
||||||
"field": "src/templates/field",
|
|
||||||
"form_checkbox": "src/templates/form_checkbox",
|
|
||||||
"form_input": "src/templates/form_input",
|
|
||||||
"form_select": "src/templates/form_select",
|
|
||||||
"group_header": "src/templates/group_header",
|
|
||||||
"info": "src/templates/info",
|
|
||||||
"login_panel": "src/templates/login_panel",
|
|
||||||
"login_tab": "src/templates/login_tab",
|
|
||||||
"message": "src/templates/message",
|
|
||||||
"new_day": "src/templates/new_day",
|
|
||||||
"occupant": "src/templates/occupant",
|
|
||||||
"pending_contact": "src/templates/pending_contact",
|
|
||||||
"pending_contacts": "src/templates/pending_contacts",
|
|
||||||
"requesting_contact": "src/templates/requesting_contact",
|
|
||||||
"requesting_contacts": "src/templates/requesting_contacts",
|
|
||||||
"room_description": "src/templates/room_description",
|
|
||||||
"room_item": "src/templates/room_item",
|
|
||||||
"room_panel": "src/templates/room_panel",
|
|
||||||
"roster": "src/templates/roster",
|
|
||||||
"roster_item": "src/templates/roster_item",
|
|
||||||
"search_contact": "src/templates/search_contact",
|
|
||||||
"select_option": "src/templates/select_option",
|
|
||||||
"status_option": "src/templates/status_option",
|
|
||||||
"toggle_chats": "src/templates/toggle_chats",
|
|
||||||
"toolbar": "src/templates/toolbar",
|
|
||||||
"trimmed_chat": "src/templates/trimmed_chat"
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -19,108 +19,8 @@
|
||||||
// be an unresolvable cyclic dependency.
|
// be an unresolvable cyclic dependency.
|
||||||
'jquery-private': { 'jquery': 'jquery' }
|
'jquery-private': { 'jquery': 'jquery' }
|
||||||
},
|
},
|
||||||
|
mainConfigFile: '../main.js',
|
||||||
paths: {
|
paths: {
|
||||||
"backbone": "components/backbone/backbone",
|
"converse-dependencies": "src/deps-website"
|
||||||
"backbone.browserStorage": "components/backbone.browserStorage/backbone.browserStorage",
|
|
||||||
"backbone.overview": "components/backbone.overview/backbone.overview",
|
|
||||||
"bootstrapJS": "components/bootstrapJS/index", // XXX: Only required for https://conversejs.org website
|
|
||||||
"converse-dependencies": "src/deps-website",
|
|
||||||
"converse-templates": "src/templates",
|
|
||||||
"eventemitter": "components/otr/build/dep/eventemitter",
|
|
||||||
"jquery": "components/jquery/dist/jquery",
|
|
||||||
"jquery-private": "src/jquery-private",
|
|
||||||
"jquery.browser": "components/jquery.browser/index",
|
|
||||||
"jquery.easing": "components/jquery-easing-original/index", // XXX: Only required for https://conversejs.org website
|
|
||||||
"moment": "components/momentjs/moment",
|
|
||||||
"strophe": "components/strophe/strophe",
|
|
||||||
"strophe.disco": "components/strophe.disco/index",
|
|
||||||
"strophe.muc": "components/strophe.muc/index",
|
|
||||||
"strophe.roster": "components/strophe.roster/index",
|
|
||||||
"strophe.vcard": "components/strophe.vcard/index",
|
|
||||||
"text": 'components/requirejs-text/text',
|
|
||||||
"tpl": 'components/requirejs-tpl-jcbrand/tpl',
|
|
||||||
"typeahead": "components/typeahead.js/index",
|
|
||||||
"underscore": "components/underscore/underscore",
|
|
||||||
"utils": "src/utils",
|
|
||||||
|
|
||||||
// Off-the-record-encryption
|
|
||||||
"bigint": "src/bigint",
|
|
||||||
"crypto": "src/crypto",
|
|
||||||
"crypto.aes": "components/otr/vendor/cryptojs/aes",
|
|
||||||
"crypto.cipher-core": "components/otr/vendor/cryptojs/cipher-core",
|
|
||||||
"crypto.core": "components/otr/vendor/cryptojs/core",
|
|
||||||
"crypto.enc-base64": "components/otr/vendor/cryptojs/enc-base64",
|
|
||||||
"crypto.evpkdf": "components/crypto-js-evanvosberg/src/evpkdf",
|
|
||||||
"crypto.hmac": "components/otr/vendor/cryptojs/hmac",
|
|
||||||
"crypto.md5": "components/crypto-js-evanvosberg/src/md5",
|
|
||||||
"crypto.mode-ctr": "components/otr/vendor/cryptojs/mode-ctr",
|
|
||||||
"crypto.pad-nopadding": "components/otr/vendor/cryptojs/pad-nopadding",
|
|
||||||
"crypto.sha1": "components/otr/vendor/cryptojs/sha1",
|
|
||||||
"crypto.sha256": "components/otr/vendor/cryptojs/sha256",
|
|
||||||
"salsa20": "components/otr/build/dep/salsa20",
|
|
||||||
"otr": "src/otr",
|
|
||||||
|
|
||||||
// Locales paths
|
|
||||||
"locales": "locale/locales",
|
|
||||||
"jed": "components/jed/jed",
|
|
||||||
"af": "locale/af/LC_MESSAGES/af",
|
|
||||||
"de": "locale/de/LC_MESSAGES/de",
|
|
||||||
"en": "locale/en/LC_MESSAGES/en",
|
|
||||||
"es": "locale/es/LC_MESSAGES/es",
|
|
||||||
"fr": "locale/fr/LC_MESSAGES/fr",
|
|
||||||
"he": "locale/he/LC_MESSAGES/he",
|
|
||||||
"hu": "locale/hu/LC_MESSAGES/hu",
|
|
||||||
"id": "locale/id/LC_MESSAGES/id",
|
|
||||||
"it": "locale/it/LC_MESSAGES/it",
|
|
||||||
"ja": "locale/ja/LC_MESSAGES/ja",
|
|
||||||
"nl": "locale/nl/LC_MESSAGES/nl",
|
|
||||||
"pt_BR": "locale/pt_BR/LC_MESSAGES/pt_BR",
|
|
||||||
"ru": "locale/ru/LC_MESSAGES/ru",
|
|
||||||
"zh": "locale/zh/LC_MESSAGES/zh",
|
|
||||||
|
|
||||||
// Templates
|
|
||||||
"action": "src/templates/action",
|
|
||||||
"add_contact_dropdown": "src/templates/add_contact_dropdown",
|
|
||||||
"add_contact_form": "src/templates/add_contact_form",
|
|
||||||
"change_status_message": "src/templates/change_status_message",
|
|
||||||
"chat_status": "src/templates/chat_status",
|
|
||||||
"chatarea": "src/templates/chatarea",
|
|
||||||
"chatbox": "src/templates/chatbox",
|
|
||||||
"chatroom": "src/templates/chatroom",
|
|
||||||
"chatroom_password_form": "src/templates/chatroom_password_form",
|
|
||||||
"chatroom_sidebar": "src/templates/chatroom_sidebar",
|
|
||||||
"chatrooms_tab": "src/templates/chatrooms_tab",
|
|
||||||
"chats_panel": "src/templates/chats_panel",
|
|
||||||
"choose_status": "src/templates/choose_status",
|
|
||||||
"contacts_panel": "src/templates/contacts_panel",
|
|
||||||
"contacts_tab": "src/templates/contacts_tab",
|
|
||||||
"controlbox": "src/templates/controlbox",
|
|
||||||
"controlbox_toggle": "src/templates/controlbox_toggle",
|
|
||||||
"field": "src/templates/field",
|
|
||||||
"form_checkbox": "src/templates/form_checkbox",
|
|
||||||
"form_input": "src/templates/form_input",
|
|
||||||
"form_select": "src/templates/form_select",
|
|
||||||
"group_header": "src/templates/group_header",
|
|
||||||
"info": "src/templates/info",
|
|
||||||
"login_panel": "src/templates/login_panel",
|
|
||||||
"login_tab": "src/templates/login_tab",
|
|
||||||
"message": "src/templates/message",
|
|
||||||
"new_day": "src/templates/new_day",
|
|
||||||
"occupant": "src/templates/occupant",
|
|
||||||
"pending_contact": "src/templates/pending_contact",
|
|
||||||
"pending_contacts": "src/templates/pending_contacts",
|
|
||||||
"requesting_contact": "src/templates/requesting_contact",
|
|
||||||
"requesting_contacts": "src/templates/requesting_contacts",
|
|
||||||
"room_description": "src/templates/room_description",
|
|
||||||
"room_item": "src/templates/room_item",
|
|
||||||
"room_panel": "src/templates/room_panel",
|
|
||||||
"roster": "src/templates/roster",
|
|
||||||
"roster_item": "src/templates/roster_item",
|
|
||||||
"search_contact": "src/templates/search_contact",
|
|
||||||
"select_option": "src/templates/select_option",
|
|
||||||
"status_option": "src/templates/status_option",
|
|
||||||
"toggle_chats": "src/templates/toggle_chats",
|
|
||||||
"toolbar": "src/templates/toolbar",
|
|
||||||
"trimmed_chat": "src/templates/trimmed_chat"
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
102
src/build.js
102
src/build.js
|
@ -19,106 +19,8 @@
|
||||||
// be an unresolvable cyclic dependency.
|
// be an unresolvable cyclic dependency.
|
||||||
'jquery-private': { 'jquery': 'jquery' }
|
'jquery-private': { 'jquery': 'jquery' }
|
||||||
},
|
},
|
||||||
|
mainConfigFile: '../main.js',
|
||||||
paths: {
|
paths: {
|
||||||
"backbone": "components/backbone/backbone",
|
"converse-dependencies": "src/deps-full"
|
||||||
"backbone.browserStorage": "components/backbone.browserStorage/backbone.browserStorage",
|
|
||||||
"backbone.overview": "components/backbone.overview/backbone.overview",
|
|
||||||
"converse-dependencies": "src/deps-full",
|
|
||||||
"converse-templates": "src/templates",
|
|
||||||
"eventemitter": "components/otr/build/dep/eventemitter",
|
|
||||||
"jquery": "components/jquery/dist/jquery",
|
|
||||||
"jquery-private": "src/jquery-private",
|
|
||||||
"jquery.browser": "components/jquery.browser/index",
|
|
||||||
"moment": "components/momentjs/moment",
|
|
||||||
"strophe": "components/strophe/strophe",
|
|
||||||
"strophe.disco": "components/strophe.disco/index",
|
|
||||||
"strophe.muc": "components/strophe.muc/index",
|
|
||||||
"strophe.roster": "components/strophe.roster/index",
|
|
||||||
"strophe.vcard": "components/strophe.vcard/index",
|
|
||||||
"text": 'components/requirejs-text/text',
|
|
||||||
"tpl": 'components/requirejs-tpl-jcbrand/tpl',
|
|
||||||
"typeahead": "components/typeahead.js/index",
|
|
||||||
"underscore": "components/underscore/underscore",
|
|
||||||
"utils": "src/utils",
|
|
||||||
|
|
||||||
// Off-the-record-encryption
|
|
||||||
"bigint": "src/bigint",
|
|
||||||
"crypto": "src/crypto",
|
|
||||||
"crypto.aes": "components/otr/vendor/cryptojs/aes",
|
|
||||||
"crypto.cipher-core": "components/otr/vendor/cryptojs/cipher-core",
|
|
||||||
"crypto.core": "components/otr/vendor/cryptojs/core",
|
|
||||||
"crypto.enc-base64": "components/otr/vendor/cryptojs/enc-base64",
|
|
||||||
"crypto.evpkdf": "components/crypto-js-evanvosberg/src/evpkdf",
|
|
||||||
"crypto.hmac": "components/otr/vendor/cryptojs/hmac",
|
|
||||||
"crypto.md5": "components/crypto-js-evanvosberg/src/md5",
|
|
||||||
"crypto.mode-ctr": "components/otr/vendor/cryptojs/mode-ctr",
|
|
||||||
"crypto.pad-nopadding": "components/otr/vendor/cryptojs/pad-nopadding",
|
|
||||||
"crypto.sha1": "components/otr/vendor/cryptojs/sha1",
|
|
||||||
"crypto.sha256": "components/otr/vendor/cryptojs/sha256",
|
|
||||||
"salsa20": "components/otr/build/dep/salsa20",
|
|
||||||
"otr": "src/otr",
|
|
||||||
|
|
||||||
// Locales paths
|
|
||||||
"locales": "locale/locales",
|
|
||||||
"jed": "components/jed/jed",
|
|
||||||
"af": "locale/af/LC_MESSAGES/af",
|
|
||||||
"de": "locale/de/LC_MESSAGES/de",
|
|
||||||
"en": "locale/en/LC_MESSAGES/en",
|
|
||||||
"es": "locale/es/LC_MESSAGES/es",
|
|
||||||
"fr": "locale/fr/LC_MESSAGES/fr",
|
|
||||||
"he": "locale/he/LC_MESSAGES/he",
|
|
||||||
"hu": "locale/hu/LC_MESSAGES/hu",
|
|
||||||
"id": "locale/id/LC_MESSAGES/id",
|
|
||||||
"it": "locale/it/LC_MESSAGES/it",
|
|
||||||
"ja": "locale/ja/LC_MESSAGES/ja",
|
|
||||||
"nl": "locale/nl/LC_MESSAGES/nl",
|
|
||||||
"pt_BR": "locale/pt_BR/LC_MESSAGES/pt_BR",
|
|
||||||
"ru": "locale/ru/LC_MESSAGES/ru",
|
|
||||||
"zh": "locale/zh/LC_MESSAGES/zh",
|
|
||||||
|
|
||||||
// Templates
|
|
||||||
"action": "src/templates/action",
|
|
||||||
"add_contact_dropdown": "src/templates/add_contact_dropdown",
|
|
||||||
"add_contact_form": "src/templates/add_contact_form",
|
|
||||||
"change_status_message": "src/templates/change_status_message",
|
|
||||||
"chat_status": "src/templates/chat_status",
|
|
||||||
"chatarea": "src/templates/chatarea",
|
|
||||||
"chatbox": "src/templates/chatbox",
|
|
||||||
"chatroom": "src/templates/chatroom",
|
|
||||||
"chatroom_password_form": "src/templates/chatroom_password_form",
|
|
||||||
"chatroom_sidebar": "src/templates/chatroom_sidebar",
|
|
||||||
"chatrooms_tab": "src/templates/chatrooms_tab",
|
|
||||||
"chats_panel": "src/templates/chats_panel",
|
|
||||||
"choose_status": "src/templates/choose_status",
|
|
||||||
"contacts_panel": "src/templates/contacts_panel",
|
|
||||||
"contacts_tab": "src/templates/contacts_tab",
|
|
||||||
"controlbox": "src/templates/controlbox",
|
|
||||||
"controlbox_toggle": "src/templates/controlbox_toggle",
|
|
||||||
"field": "src/templates/field",
|
|
||||||
"form_checkbox": "src/templates/form_checkbox",
|
|
||||||
"form_input": "src/templates/form_input",
|
|
||||||
"form_select": "src/templates/form_select",
|
|
||||||
"group_header": "src/templates/group_header",
|
|
||||||
"info": "src/templates/info",
|
|
||||||
"login_panel": "src/templates/login_panel",
|
|
||||||
"login_tab": "src/templates/login_tab",
|
|
||||||
"message": "src/templates/message",
|
|
||||||
"new_day": "src/templates/new_day",
|
|
||||||
"occupant": "src/templates/occupant",
|
|
||||||
"pending_contact": "src/templates/pending_contact",
|
|
||||||
"pending_contacts": "src/templates/pending_contacts",
|
|
||||||
"requesting_contact": "src/templates/requesting_contact",
|
|
||||||
"requesting_contacts": "src/templates/requesting_contacts",
|
|
||||||
"room_description": "src/templates/room_description",
|
|
||||||
"room_item": "src/templates/room_item",
|
|
||||||
"room_panel": "src/templates/room_panel",
|
|
||||||
"roster": "src/templates/roster",
|
|
||||||
"roster_item": "src/templates/roster_item",
|
|
||||||
"search_contact": "src/templates/search_contact",
|
|
||||||
"select_option": "src/templates/select_option",
|
|
||||||
"status_option": "src/templates/status_option",
|
|
||||||
"toggle_chats": "src/templates/toggle_chats",
|
|
||||||
"toolbar": "src/templates/toolbar",
|
|
||||||
"trimmed_chat": "src/templates/trimmed_chat"
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
447
src/strophe.roster.js
Normal file
447
src/strophe.roster.js
Normal file
|
@ -0,0 +1,447 @@
|
||||||
|
/*
|
||||||
|
Copyright 2010, François de Metz <francois@2metz.fr>
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Roster Plugin
|
||||||
|
* Allow easily roster management
|
||||||
|
*
|
||||||
|
* Features
|
||||||
|
* * Get roster from server
|
||||||
|
* * handle presence
|
||||||
|
* * handle roster iq
|
||||||
|
* * subscribe/unsubscribe
|
||||||
|
* * authorize/unauthorize
|
||||||
|
* * roster versioning (xep 237)
|
||||||
|
*/
|
||||||
|
Strophe.addConnectionPlugin('roster',
|
||||||
|
{
|
||||||
|
/** Function: init
|
||||||
|
* Plugin init
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* (Strophe.Connection) conn - Strophe connection
|
||||||
|
*/
|
||||||
|
init: function(conn)
|
||||||
|
{
|
||||||
|
this._connection = conn;
|
||||||
|
this._callbacks = [];
|
||||||
|
/** Property: items
|
||||||
|
* Roster items
|
||||||
|
* [
|
||||||
|
* {
|
||||||
|
* name : "",
|
||||||
|
* jid : "",
|
||||||
|
* subscription : "",
|
||||||
|
* ask : "",
|
||||||
|
* groups : ["", ""],
|
||||||
|
* resources : {
|
||||||
|
* myresource : {
|
||||||
|
* show : "",
|
||||||
|
* status : "",
|
||||||
|
* priority : ""
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ]
|
||||||
|
*/
|
||||||
|
this.items = [];
|
||||||
|
/** Property: ver
|
||||||
|
* current roster revision
|
||||||
|
* always null if server doesn't support xep 237
|
||||||
|
*/
|
||||||
|
this.ver = null;
|
||||||
|
// Override the connect and attach methods to always add presence and roster handlers.
|
||||||
|
// They are removed when the connection disconnects, so must be added on connection.
|
||||||
|
var oldCallback, roster = this, _connect = conn.connect, _attach = conn.attach;
|
||||||
|
var newCallback = function(status)
|
||||||
|
{
|
||||||
|
if (status == Strophe.Status.ATTACHED || status == Strophe.Status.CONNECTED)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Presence subscription
|
||||||
|
conn.addHandler(roster._onReceivePresence.bind(roster), null, 'presence', null, null, null);
|
||||||
|
conn.addHandler(roster._onReceiveIQ.bind(roster), Strophe.NS.ROSTER, 'iq', "set", null, null);
|
||||||
|
}
|
||||||
|
catch (e)
|
||||||
|
{
|
||||||
|
Strophe.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof oldCallback === "function") {
|
||||||
|
oldCallback.apply(this, arguments);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
conn.connect = function(jid, pass, callback, wait, hold)
|
||||||
|
{
|
||||||
|
oldCallback = callback;
|
||||||
|
if (typeof jid == "undefined")
|
||||||
|
jid = null;
|
||||||
|
if (typeof pass == "undefined")
|
||||||
|
pass = null;
|
||||||
|
callback = newCallback;
|
||||||
|
_connect.apply(conn, [jid, pass, callback, wait, hold]);
|
||||||
|
};
|
||||||
|
conn.attach = function(jid, sid, rid, callback, wait, hold, wind)
|
||||||
|
{
|
||||||
|
oldCallback = callback;
|
||||||
|
if (typeof jid == "undefined")
|
||||||
|
jid = null;
|
||||||
|
if (typeof sid == "undefined")
|
||||||
|
sid = null;
|
||||||
|
if (typeof rid == "undefined")
|
||||||
|
rid = null;
|
||||||
|
callback = newCallback;
|
||||||
|
_attach.apply(conn, [jid, sid, rid, callback, wait, hold, wind]);
|
||||||
|
};
|
||||||
|
|
||||||
|
Strophe.addNamespace('ROSTER_VER', 'urn:xmpp:features:rosterver');
|
||||||
|
Strophe.addNamespace('NICK', 'http://jabber.org/protocol/nick');
|
||||||
|
},
|
||||||
|
/** Function: supportVersioning
|
||||||
|
* return true if roster versioning is enabled on server
|
||||||
|
*/
|
||||||
|
supportVersioning: function()
|
||||||
|
{
|
||||||
|
return (this._connection.features && this._connection.features.getElementsByTagName('ver').length > 0);
|
||||||
|
},
|
||||||
|
/** Function: get
|
||||||
|
* Get Roster on server
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* (Function) userCallback - callback on roster result
|
||||||
|
* (String) ver - current rev of roster
|
||||||
|
* (only used if roster versioning is enabled)
|
||||||
|
* (Array) items - initial items of ver
|
||||||
|
* (only used if roster versioning is enabled)
|
||||||
|
* In browser context you can use sessionStorage
|
||||||
|
* to store your roster in json (JSON.stringify())
|
||||||
|
*/
|
||||||
|
get: function(userCallback, ver, items)
|
||||||
|
{
|
||||||
|
var attrs = {xmlns: Strophe.NS.ROSTER};
|
||||||
|
if (this.supportVersioning())
|
||||||
|
{
|
||||||
|
// empty rev because i want an rev attribute in the result
|
||||||
|
attrs.ver = ver || '';
|
||||||
|
this.items = items || [];
|
||||||
|
}
|
||||||
|
var iq = $iq({type: 'get', 'id' : this._connection.getUniqueId('roster')}).c('query', attrs);
|
||||||
|
return this._connection.sendIQ(iq,
|
||||||
|
this._onReceiveRosterSuccess.bind(this, userCallback),
|
||||||
|
this._onReceiveRosterError.bind(this, userCallback));
|
||||||
|
},
|
||||||
|
/** Function: registerCallback
|
||||||
|
* register callback on roster (presence and iq)
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* (Function) call_back
|
||||||
|
*/
|
||||||
|
registerCallback: function(call_back)
|
||||||
|
{
|
||||||
|
this._callbacks.push(call_back);
|
||||||
|
},
|
||||||
|
/** Function: findItem
|
||||||
|
* Find item by JID
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* (String) jid
|
||||||
|
*/
|
||||||
|
findItem : function(jid)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
for (var i = 0; i < this.items.length; i++)
|
||||||
|
{
|
||||||
|
if (this.items[i] && this.items[i].jid == jid)
|
||||||
|
{
|
||||||
|
return this.items[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e)
|
||||||
|
{
|
||||||
|
Strophe.error(e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
/** Function: removeItem
|
||||||
|
* Remove item by JID
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* (String) jid
|
||||||
|
*/
|
||||||
|
removeItem : function(jid)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < this.items.length; i++)
|
||||||
|
{
|
||||||
|
if (this.items[i] && this.items[i].jid == jid)
|
||||||
|
{
|
||||||
|
this.items.splice(i, 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
/** Function: subscribe
|
||||||
|
* Subscribe presence
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* (String) jid
|
||||||
|
* (String) message (optional)
|
||||||
|
* (String) nick (optional)
|
||||||
|
*/
|
||||||
|
subscribe: function(jid, message, nick) {
|
||||||
|
var pres = $pres({to: jid, type: "subscribe"});
|
||||||
|
if (message && message !== "") {
|
||||||
|
pres.c("status").t(message).up();
|
||||||
|
}
|
||||||
|
if (nick && nick !== "") {
|
||||||
|
pres.c('nick', {'xmlns': Strophe.NS.NICK}).t(nick).up();
|
||||||
|
}
|
||||||
|
this._connection.send(pres);
|
||||||
|
},
|
||||||
|
/** Function: unsubscribe
|
||||||
|
* Unsubscribe presence
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* (String) jid
|
||||||
|
* (String) message
|
||||||
|
*/
|
||||||
|
unsubscribe: function(jid, message)
|
||||||
|
{
|
||||||
|
var pres = $pres({to: jid, type: "unsubscribe"});
|
||||||
|
if (message && message !== "")
|
||||||
|
pres.c("status").t(message);
|
||||||
|
this._connection.send(pres);
|
||||||
|
},
|
||||||
|
/** Function: authorize
|
||||||
|
* Authorize presence subscription
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* (String) jid
|
||||||
|
* (String) message
|
||||||
|
*/
|
||||||
|
authorize: function(jid, message)
|
||||||
|
{
|
||||||
|
var pres = $pres({to: jid, type: "subscribed"});
|
||||||
|
if (message && message !== "")
|
||||||
|
pres.c("status").t(message);
|
||||||
|
this._connection.send(pres);
|
||||||
|
},
|
||||||
|
/** Function: unauthorize
|
||||||
|
* Unauthorize presence subscription
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* (String) jid
|
||||||
|
* (String) message
|
||||||
|
*/
|
||||||
|
unauthorize: function(jid, message)
|
||||||
|
{
|
||||||
|
var pres = $pres({to: jid, type: "unsubscribed"});
|
||||||
|
if (message && message !== "")
|
||||||
|
pres.c("status").t(message);
|
||||||
|
this._connection.send(pres);
|
||||||
|
},
|
||||||
|
/** Function: add
|
||||||
|
* Add roster item
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* (String) jid - item jid
|
||||||
|
* (String) name - name
|
||||||
|
* (Array) groups
|
||||||
|
* (Function) call_back
|
||||||
|
*/
|
||||||
|
add: function(jid, name, groups, call_back)
|
||||||
|
{
|
||||||
|
var iq = $iq({type: 'set'}).c('query', {xmlns: Strophe.NS.ROSTER}).c('item', {jid: jid,
|
||||||
|
name: name});
|
||||||
|
for (var i = 0; i < groups.length; i++)
|
||||||
|
{
|
||||||
|
iq.c('group').t(groups[i]).up();
|
||||||
|
}
|
||||||
|
this._connection.sendIQ(iq, call_back, call_back);
|
||||||
|
},
|
||||||
|
/** Function: update
|
||||||
|
* Update roster item
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* (String) jid - item jid
|
||||||
|
* (String) name - name
|
||||||
|
* (Array) groups
|
||||||
|
* (Function) call_back
|
||||||
|
*/
|
||||||
|
update: function(jid, name, groups, call_back)
|
||||||
|
{
|
||||||
|
var item = this.findItem(jid);
|
||||||
|
if (!item)
|
||||||
|
{
|
||||||
|
throw "item not found";
|
||||||
|
}
|
||||||
|
var newName = name || item.name;
|
||||||
|
var newGroups = groups || item.groups;
|
||||||
|
var iq = $iq({type: 'set'}).c('query', {xmlns: Strophe.NS.ROSTER}).c('item', {jid: item.jid,
|
||||||
|
name: newName});
|
||||||
|
for (var i = 0; i < newGroups.length; i++)
|
||||||
|
{
|
||||||
|
iq.c('group').t(newGroups[i]).up();
|
||||||
|
}
|
||||||
|
return this._connection.sendIQ(iq, call_back, call_back);
|
||||||
|
},
|
||||||
|
/** Function: remove
|
||||||
|
* Remove roster item
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* (String) jid - item jid
|
||||||
|
* (Function) call_back
|
||||||
|
*/
|
||||||
|
remove: function(jid, call_back)
|
||||||
|
{
|
||||||
|
var item = this.findItem(jid);
|
||||||
|
if (!item)
|
||||||
|
{
|
||||||
|
throw "item not found";
|
||||||
|
}
|
||||||
|
var iq = $iq({type: 'set'}).c('query', {xmlns: Strophe.NS.ROSTER}).c('item', {jid: item.jid,
|
||||||
|
subscription: "remove"});
|
||||||
|
this._connection.sendIQ(iq, call_back, call_back);
|
||||||
|
},
|
||||||
|
/** PrivateFunction: _onReceiveRosterSuccess
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
_onReceiveRosterSuccess: function(userCallback, stanza)
|
||||||
|
{
|
||||||
|
this._updateItems(stanza);
|
||||||
|
if (typeof userCallback === "function") {
|
||||||
|
userCallback(this.items);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** PrivateFunction: _onReceiveRosterError
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
_onReceiveRosterError: function(userCallback, stanza)
|
||||||
|
{
|
||||||
|
userCallback(this.items);
|
||||||
|
},
|
||||||
|
/** PrivateFunction: _onReceivePresence
|
||||||
|
* Handle presence
|
||||||
|
*/
|
||||||
|
_onReceivePresence : function(presence)
|
||||||
|
{
|
||||||
|
// TODO: from is optional
|
||||||
|
var jid = presence.getAttribute('from');
|
||||||
|
var from = Strophe.getBareJidFromJid(jid);
|
||||||
|
var item = this.findItem(from);
|
||||||
|
// not in roster
|
||||||
|
if (!item)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
var type = presence.getAttribute('type');
|
||||||
|
if (type == 'unavailable')
|
||||||
|
{
|
||||||
|
delete item.resources[Strophe.getResourceFromJid(jid)];
|
||||||
|
}
|
||||||
|
else if (!type)
|
||||||
|
{
|
||||||
|
// TODO: add timestamp
|
||||||
|
item.resources[Strophe.getResourceFromJid(jid)] = {
|
||||||
|
show : (presence.getElementsByTagName('show').length !== 0) ? Strophe.getText(presence.getElementsByTagName('show')[0]) : "",
|
||||||
|
status : (presence.getElementsByTagName('status').length !== 0) ? Strophe.getText(presence.getElementsByTagName('status')[0]) : "",
|
||||||
|
priority : (presence.getElementsByTagName('priority').length !== 0) ? Strophe.getText(presence.getElementsByTagName('priority')[0]) : ""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Stanza is not a presence notification. (It's probably a subscription type stanza.)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
this._call_backs(this.items, item);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
/** PrivateFunction: _call_backs
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
_call_backs : function(items, item)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < this._callbacks.length; i++) // [].forEach my love ...
|
||||||
|
{
|
||||||
|
this._callbacks[i](items, item);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** PrivateFunction: _onReceiveIQ
|
||||||
|
* Handle roster push.
|
||||||
|
*/
|
||||||
|
_onReceiveIQ : function(iq)
|
||||||
|
{
|
||||||
|
var id = iq.getAttribute('id');
|
||||||
|
var from = iq.getAttribute('from');
|
||||||
|
// Receiving client MUST ignore stanza unless it has no from or from = user's JID.
|
||||||
|
if (from && from !== "" && from != this._connection.jid && from != Strophe.getBareJidFromJid(this._connection.jid))
|
||||||
|
return true;
|
||||||
|
var iqresult = $iq({type: 'result', id: id, from: this._connection.jid});
|
||||||
|
this._connection.send(iqresult);
|
||||||
|
this._updateItems(iq);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
/** PrivateFunction: _updateItems
|
||||||
|
* Update items from iq
|
||||||
|
*/
|
||||||
|
_updateItems : function(iq)
|
||||||
|
{
|
||||||
|
var query = iq.getElementsByTagName('query');
|
||||||
|
if (query.length !== 0)
|
||||||
|
{
|
||||||
|
this.ver = query.item(0).getAttribute('ver');
|
||||||
|
var self = this;
|
||||||
|
Strophe.forEachChild(query.item(0), 'item',
|
||||||
|
function (item)
|
||||||
|
{
|
||||||
|
self._updateItem(item);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
this._call_backs(this.items);
|
||||||
|
},
|
||||||
|
/** PrivateFunction: _updateItem
|
||||||
|
* Update internal representation of roster item
|
||||||
|
*/
|
||||||
|
_updateItem : function(item)
|
||||||
|
{
|
||||||
|
var jid = item.getAttribute("jid");
|
||||||
|
var name = item.getAttribute("name");
|
||||||
|
var subscription = item.getAttribute("subscription");
|
||||||
|
var ask = item.getAttribute("ask");
|
||||||
|
var groups = [];
|
||||||
|
Strophe.forEachChild(item, 'group',
|
||||||
|
function(group)
|
||||||
|
{
|
||||||
|
groups.push(Strophe.getText(group));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (subscription == "remove")
|
||||||
|
{
|
||||||
|
this.removeItem(jid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
item = this.findItem(jid);
|
||||||
|
if (!item)
|
||||||
|
{
|
||||||
|
this.items.push({
|
||||||
|
name : name,
|
||||||
|
jid : jid,
|
||||||
|
subscription : subscription,
|
||||||
|
ask : ask,
|
||||||
|
groups : groups,
|
||||||
|
resources : {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item.name = name;
|
||||||
|
item.subscription = subscription;
|
||||||
|
item.ask = ask;
|
||||||
|
item.groups = groups;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,6 +1,5 @@
|
||||||
<input class="roster-filter" placeholder="{{placeholder}}">
|
<input style="display: none;" class="roster-filter" placeholder="{{placeholder}}">
|
||||||
<select class="filter-type">
|
<select style="display: none;" class="filter-type">
|
||||||
<option value="contacts">{{label_contacts}}</option>
|
<option value="contacts">{{label_contacts}}</option>
|
||||||
<option value="groups">{{label_groups}}</option>
|
<option value="groups">{{label_groups}}</option>
|
||||||
</select>
|
</select>
|
||||||
<dl class="roster-contacts"></dl>
|
|
||||||
|
|
157
tests/main.js
157
tests/main.js
|
@ -1,3 +1,152 @@
|
||||||
|
config = {
|
||||||
|
baseUrl: '.',
|
||||||
|
paths: {
|
||||||
|
"backbone": "components/backbone/backbone",
|
||||||
|
"backbone.browserStorage": "components/backbone.browserStorage/backbone.browserStorage",
|
||||||
|
"backbone.overview": "components/backbone.overview/backbone.overview",
|
||||||
|
"bootstrap": "components/bootstrap/dist/js/bootstrap", // XXX: Only required for https://conversejs.org website
|
||||||
|
"bootstrapJS": "components/bootstrapJS/index", // XXX: Only required for https://conversejs.org website
|
||||||
|
"converse-dependencies": "src/deps-website",
|
||||||
|
"converse-templates": "src/templates",
|
||||||
|
"eventemitter": "components/otr/build/dep/eventemitter",
|
||||||
|
"jquery": "components/jquery/dist/jquery",
|
||||||
|
"jquery-private": "src/jquery-private",
|
||||||
|
"jquery.browser": "components/jquery.browser/index",
|
||||||
|
"jquery.easing": "components/jquery-easing-original/index", // XXX: Only required for https://conversejs.org website
|
||||||
|
"moment": "components/momentjs/moment",
|
||||||
|
"strophe": "components/strophe/strophe",
|
||||||
|
"strophe.disco": "components/strophejs-plugins/disco/strophe.disco",
|
||||||
|
"strophe.muc": "components/strophe.muc/index",
|
||||||
|
"strophe.roster": "src/strophe.roster",
|
||||||
|
"strophe.vcard": "components/strophejs-plugins/vcard/strophe.vcard",
|
||||||
|
"text": 'components/requirejs-text/text',
|
||||||
|
"tpl": 'components/requirejs-tpl-jcbrand/tpl',
|
||||||
|
"typeahead": "components/typeahead.js/index",
|
||||||
|
"underscore": "components/underscore/underscore",
|
||||||
|
"utils": "src/utils",
|
||||||
|
|
||||||
|
// Off-the-record-encryption
|
||||||
|
"bigint": "src/bigint",
|
||||||
|
"crypto": "src/crypto",
|
||||||
|
"crypto.aes": "components/otr/vendor/cryptojs/aes",
|
||||||
|
"crypto.cipher-core": "components/otr/vendor/cryptojs/cipher-core",
|
||||||
|
"crypto.core": "components/otr/vendor/cryptojs/core",
|
||||||
|
"crypto.enc-base64": "components/otr/vendor/cryptojs/enc-base64",
|
||||||
|
"crypto.evpkdf": "components/crypto-js-evanvosberg/src/evpkdf",
|
||||||
|
"crypto.hmac": "components/otr/vendor/cryptojs/hmac",
|
||||||
|
"crypto.md5": "components/crypto-js-evanvosberg/src/md5",
|
||||||
|
"crypto.mode-ctr": "components/otr/vendor/cryptojs/mode-ctr",
|
||||||
|
"crypto.pad-nopadding": "components/otr/vendor/cryptojs/pad-nopadding",
|
||||||
|
"crypto.sha1": "components/otr/vendor/cryptojs/sha1",
|
||||||
|
"crypto.sha256": "components/otr/vendor/cryptojs/sha256",
|
||||||
|
"salsa20": "components/otr/build/dep/salsa20",
|
||||||
|
"otr": "src/otr",
|
||||||
|
|
||||||
|
// Locales paths
|
||||||
|
"locales": "locale/locales",
|
||||||
|
"jed": "components/jed/jed",
|
||||||
|
"af": "locale/af/LC_MESSAGES/af",
|
||||||
|
"de": "locale/de/LC_MESSAGES/de",
|
||||||
|
"en": "locale/en/LC_MESSAGES/en",
|
||||||
|
"es": "locale/es/LC_MESSAGES/es",
|
||||||
|
"fr": "locale/fr/LC_MESSAGES/fr",
|
||||||
|
"he": "locale/he/LC_MESSAGES/he",
|
||||||
|
"hu": "locale/hu/LC_MESSAGES/hu",
|
||||||
|
"id": "locale/id/LC_MESSAGES/id",
|
||||||
|
"it": "locale/it/LC_MESSAGES/it",
|
||||||
|
"ja": "locale/ja/LC_MESSAGES/ja",
|
||||||
|
"nl": "locale/nl/LC_MESSAGES/nl",
|
||||||
|
"pt_BR": "locale/pt_BR/LC_MESSAGES/pt_BR",
|
||||||
|
"ru": "locale/ru/LC_MESSAGES/ru",
|
||||||
|
"zh": "locale/zh/LC_MESSAGES/zh",
|
||||||
|
|
||||||
|
// Templates
|
||||||
|
"action": "src/templates/action",
|
||||||
|
"add_contact_dropdown": "src/templates/add_contact_dropdown",
|
||||||
|
"add_contact_form": "src/templates/add_contact_form",
|
||||||
|
"change_status_message": "src/templates/change_status_message",
|
||||||
|
"chat_status": "src/templates/chat_status",
|
||||||
|
"chatarea": "src/templates/chatarea",
|
||||||
|
"chatbox": "src/templates/chatbox",
|
||||||
|
"chatroom": "src/templates/chatroom",
|
||||||
|
"chatroom_password_form": "src/templates/chatroom_password_form",
|
||||||
|
"chatroom_sidebar": "src/templates/chatroom_sidebar",
|
||||||
|
"chatrooms_tab": "src/templates/chatrooms_tab",
|
||||||
|
"chats_panel": "src/templates/chats_panel",
|
||||||
|
"choose_status": "src/templates/choose_status",
|
||||||
|
"contacts_panel": "src/templates/contacts_panel",
|
||||||
|
"contacts_tab": "src/templates/contacts_tab",
|
||||||
|
"controlbox": "src/templates/controlbox",
|
||||||
|
"controlbox_toggle": "src/templates/controlbox_toggle",
|
||||||
|
"field": "src/templates/field",
|
||||||
|
"form_checkbox": "src/templates/form_checkbox",
|
||||||
|
"form_input": "src/templates/form_input",
|
||||||
|
"form_select": "src/templates/form_select",
|
||||||
|
"group_header": "src/templates/group_header",
|
||||||
|
"info": "src/templates/info",
|
||||||
|
"login_panel": "src/templates/login_panel",
|
||||||
|
"login_tab": "src/templates/login_tab",
|
||||||
|
"message": "src/templates/message",
|
||||||
|
"new_day": "src/templates/new_day",
|
||||||
|
"occupant": "src/templates/occupant",
|
||||||
|
"pending_contact": "src/templates/pending_contact",
|
||||||
|
"pending_contacts": "src/templates/pending_contacts",
|
||||||
|
"requesting_contact": "src/templates/requesting_contact",
|
||||||
|
"requesting_contacts": "src/templates/requesting_contacts",
|
||||||
|
"room_description": "src/templates/room_description",
|
||||||
|
"room_item": "src/templates/room_item",
|
||||||
|
"room_panel": "src/templates/room_panel",
|
||||||
|
"roster": "src/templates/roster",
|
||||||
|
"roster_item": "src/templates/roster_item",
|
||||||
|
"search_contact": "src/templates/search_contact",
|
||||||
|
"select_option": "src/templates/select_option",
|
||||||
|
"status_option": "src/templates/status_option",
|
||||||
|
"toggle_chats": "src/templates/toggle_chats",
|
||||||
|
"toolbar": "src/templates/toolbar",
|
||||||
|
"trimmed_chat": "src/templates/trimmed_chat"
|
||||||
|
},
|
||||||
|
|
||||||
|
map: {
|
||||||
|
// '*' means all modules will get 'jquery-private'
|
||||||
|
// for their 'jquery' dependency.
|
||||||
|
'*': { 'jquery': 'jquery-private' },
|
||||||
|
// 'jquery-private' wants the real jQuery module
|
||||||
|
// though. If this line was not here, there would
|
||||||
|
// be an unresolvable cyclic dependency.
|
||||||
|
'jquery-private': { 'jquery': 'jquery' }
|
||||||
|
},
|
||||||
|
|
||||||
|
tpl: {
|
||||||
|
// Configuration for requirejs-tpl
|
||||||
|
// Use Mustache style syntax for variable interpolation
|
||||||
|
templateSettings: {
|
||||||
|
evaluate : /\{\[([\s\S]+?)\]\}/g,
|
||||||
|
interpolate : /\{\{([\s\S]+?)\}\}/g
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// define module dependencies for modules not using define
|
||||||
|
shim: {
|
||||||
|
'underscore': { exports: '_' },
|
||||||
|
'crypto.aes': { deps: ['crypto.cipher-core'] },
|
||||||
|
'crypto.cipher-core': { deps: ['crypto.enc-base64', 'crypto.evpkdf'] },
|
||||||
|
'crypto.enc-base64': { deps: ['crypto.core'] },
|
||||||
|
'crypto.evpkdf': { deps: ['crypto.md5'] },
|
||||||
|
'crypto.hmac': { deps: ['crypto.core'] },
|
||||||
|
'crypto.md5': { deps: ['crypto.core'] },
|
||||||
|
'crypto.mode-ctr': { deps: ['crypto.cipher-core'] },
|
||||||
|
'crypto.pad-nopadding': { deps: ['crypto.cipher-core'] },
|
||||||
|
'crypto.sha1': { deps: ['crypto.core'] },
|
||||||
|
'crypto.sha256': { deps: ['crypto.core'] },
|
||||||
|
'bigint': { deps: ['crypto'] },
|
||||||
|
'strophe': { exports: 'Strophe' },
|
||||||
|
'strophe.disco': { deps: ['strophe'] },
|
||||||
|
'strophe.muc': { deps: ['strophe'] },
|
||||||
|
'strophe.roster': { deps: ['strophe'] },
|
||||||
|
'strophe.vcard': { deps: ['strophe'] }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Extra test dependencies
|
// Extra test dependencies
|
||||||
config.paths.mock = "tests/mock";
|
config.paths.mock = "tests/mock";
|
||||||
config.paths.test_utils = "tests/utils";
|
config.paths.test_utils = "tests/utils";
|
||||||
|
@ -40,8 +189,6 @@ require([
|
||||||
window.converse_api = converse;
|
window.converse_api = converse;
|
||||||
window.localStorage.clear();
|
window.localStorage.clear();
|
||||||
window.sessionStorage.clear();
|
window.sessionStorage.clear();
|
||||||
// XXX: call this to initialize Strophe plugins
|
|
||||||
new Strophe.Connection('localhost');
|
|
||||||
|
|
||||||
converse.initialize({
|
converse.initialize({
|
||||||
prebind: false,
|
prebind: false,
|
||||||
|
@ -49,7 +196,8 @@ require([
|
||||||
auto_subscribe: false,
|
auto_subscribe: false,
|
||||||
animate: false,
|
animate: false,
|
||||||
connection: mock.mock_connection,
|
connection: mock.mock_connection,
|
||||||
no_trimming: true
|
no_trimming: true,
|
||||||
|
debug: true
|
||||||
}, function (converse) {
|
}, function (converse) {
|
||||||
window.converse = converse;
|
window.converse = converse;
|
||||||
window.crypto = {
|
window.crypto = {
|
||||||
|
@ -68,7 +216,8 @@ require([
|
||||||
"spec/controlbox",
|
"spec/controlbox",
|
||||||
"spec/chatbox",
|
"spec/chatbox",
|
||||||
"spec/chatroom",
|
"spec/chatroom",
|
||||||
"spec/minchats"
|
"spec/minchats",
|
||||||
|
"spec/profiling"
|
||||||
], function () {
|
], function () {
|
||||||
// Make sure this callback is only called once.
|
// Make sure this callback is only called once.
|
||||||
delete converse.callback;
|
delete converse.callback;
|
||||||
|
|
|
@ -36,11 +36,37 @@
|
||||||
'preventDefault': function () {}
|
'preventDefault': function () {}
|
||||||
};
|
};
|
||||||
|
|
||||||
mock.mock_connection = {
|
mock.mock_connection = function () {
|
||||||
'_proto': {},
|
Strophe.Bosh.prototype._processRequest = function () {}; // Don't attempt to send out stanzas
|
||||||
'connected': true,
|
var c = new Strophe.Connection('jasmine tests');
|
||||||
'authenticated': true,
|
c.authenticated = true;
|
||||||
'mock': true,
|
c.connected = true;
|
||||||
|
c.mock = true;
|
||||||
|
c.jid = 'dummy@localhost/resource';
|
||||||
|
c.vcard = {
|
||||||
|
'get': function (callback, jid) {
|
||||||
|
var fullname;
|
||||||
|
if (!jid) {
|
||||||
|
jid = 'dummy@localhost';
|
||||||
|
fullname = 'Max Mustermann' ;
|
||||||
|
} else {
|
||||||
|
var name = jid.split('@')[0].replace(/\./g, ' ').split(' ');
|
||||||
|
var last = name.length-1;
|
||||||
|
name[0] = name[0].charAt(0).toUpperCase()+name[0].slice(1);
|
||||||
|
name[last] = name[last].charAt(0).toUpperCase()+name[last].slice(1);
|
||||||
|
fullname = name.join(' ');
|
||||||
|
}
|
||||||
|
var vcard = $iq().c('vCard').c('FN').t(fullname);
|
||||||
|
callback(vcard.tree());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
c._changeConnectStatus(Strophe.Status.CONNECTED);
|
||||||
|
c.attach(c.jid);
|
||||||
|
return c;
|
||||||
|
}();
|
||||||
|
|
||||||
|
/*
|
||||||
|
{
|
||||||
'muc': {
|
'muc': {
|
||||||
'listRooms': function () {},
|
'listRooms': function () {},
|
||||||
'join': function () {},
|
'join': function () {},
|
||||||
|
@ -49,7 +75,6 @@
|
||||||
'groupchat': function () {return String((new Date()).getTime()); }
|
'groupchat': function () {return String((new Date()).getTime()); }
|
||||||
},
|
},
|
||||||
'service': 'jasmine tests',
|
'service': 'jasmine tests',
|
||||||
'jid': 'dummy@localhost',
|
|
||||||
'addHandler': function (handler, ns, name, type, id, from, options) {
|
'addHandler': function (handler, ns, name, type, id, from, options) {
|
||||||
return function () {};
|
return function () {};
|
||||||
},
|
},
|
||||||
|
@ -87,5 +112,6 @@
|
||||||
'items': function () {}
|
'items': function () {}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
return mock;
|
return mock;
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -8,6 +8,17 @@
|
||||||
});
|
});
|
||||||
}(this, function ($, mock) {
|
}(this, function ($, mock) {
|
||||||
var utils = {};
|
var utils = {};
|
||||||
|
|
||||||
|
utils.createRequest = function (iq) {
|
||||||
|
iq = typeof iq.tree == "function" ? iq.tree() : iq;
|
||||||
|
var req = new Strophe.Request(iq, function() {});
|
||||||
|
req.getResponse = function() {
|
||||||
|
var env = new Strophe.Builder('env', {type: 'mock'}).tree();
|
||||||
|
env.appendChild(iq);
|
||||||
|
return env;
|
||||||
|
};
|
||||||
|
return req;
|
||||||
|
};
|
||||||
|
|
||||||
utils.closeAllChatBoxes = function () {
|
utils.closeAllChatBoxes = function () {
|
||||||
var i, chatbox;
|
var i, chatbox;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user