Commit ac643ae6 authored by JC Brand's avatar JC Brand

Refactor views to use Backbone.OrderedListView

parent 102f39ed
...@@ -73,21 +73,25 @@ ...@@ -73,21 +73,25 @@
spyOn(_converse.chatboxviews, 'trimChats'); spyOn(_converse.chatboxviews, 'trimChats');
expect($("#conversejs .chatbox").length).toBe(1); // Controlbox is open expect($("#conversejs .chatbox").length).toBe(1); // Controlbox is open
var online_contacts = _converse.rosterview.$el.find('.roster-group .current-xmpp-contact a.open-chat'); test_utils.waitUntil(function () {
expect(online_contacts.length).toBe(15); return _converse.rosterview.$el.find('.roster-group li').length;
for (i=0; i<online_contacts.length; i++) { }, 700).then(function () {
$el = $(online_contacts[i]); var online_contacts = _converse.rosterview.$el.find('.roster-group .current-xmpp-contact a.open-chat');
jid = $el.text().trim().replace(/ /g,'.').toLowerCase() + '@localhost'; expect(online_contacts.length).toBe(15);
$el.click(); for (i=0; i<online_contacts.length; i++) {
chatboxview = _converse.chatboxviews.get(jid); $el = $(online_contacts[i]);
expect(_converse.chatboxes.length).toEqual(i+2); jid = $el.text().trim().replace(/ /g,'.').toLowerCase() + '@localhost';
expect(_converse.chatboxviews.trimChats).toHaveBeenCalled(); $el.click();
// Check that new chat boxes are created to the left of the chatboxview = _converse.chatboxviews.get(jid);
// controlbox (but to the right of all existing chat boxes) expect(_converse.chatboxes.length).toEqual(i+2);
expect($("#conversejs .chatbox").length).toBe(i+2); expect(_converse.chatboxviews.trimChats).toHaveBeenCalled();
expect($("#conversejs .chatbox")[1].id).toBe(chatboxview.model.get('box_id')); // Check that new chat boxes are created to the left of the
} // controlbox (but to the right of all existing chat boxes)
done(); expect($("#conversejs .chatbox").length).toBe(i+2);
expect($("#conversejs .chatbox")[1].id).toBe(chatboxview.model.get('box_id'));
}
done();
});
})); }));
it("can be trimmed to conserve space", it("can be trimmed to conserve space",
...@@ -109,10 +113,10 @@ ...@@ -109,10 +113,10 @@
spyOn(trimmed_chatboxes, 'removeChat').and.callThrough(); spyOn(trimmed_chatboxes, 'removeChat').and.callThrough();
expect($("#conversejs .chatbox").length).toBe(1); // Controlbox is open expect($("#conversejs .chatbox").length).toBe(1); // Controlbox is open
_converse.rosterview.update(); // XXX: Hack to make sure $roster element is attaced. _converse.rosterview.update(); // XXX: Hack to make sure $roster element is attached.
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length; return _converse.rosterview.$el.find('.roster-group li').length;
}, 300).then(function () { }, 700).then(function () {
// Test that they can be maximized again // Test that they can be maximized again
var online_contacts = _converse.rosterview.$el.find('.roster-group .current-xmpp-contact a.open-chat'); var online_contacts = _converse.rosterview.$el.find('.roster-group .current-xmpp-contact a.open-chat');
expect(online_contacts.length).toBe(15); expect(online_contacts.length).toBe(15);
...@@ -836,10 +840,9 @@ ...@@ -836,10 +840,9 @@
}).c('body').t('Message: '+i).up() }).c('body').t('Message: '+i).up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
} }
test_utils.waitUntil(function () { return test_utils.waitUntil(function () {
return chatboxview.$content.scrollTop(); return chatboxview.$content.scrollTop();
}, 1000) }, 1000).then(function () {
.then(function () {
return test_utils.waitUntil(function () { return test_utils.waitUntil(function () {
return !chatboxview.model.get('auto_scrolled'); return !chatboxview.model.get('auto_scrolled');
}, 500); }, 500);
...@@ -872,7 +875,7 @@ ...@@ -872,7 +875,7 @@
chatboxview.$content.scrollTop(chatboxview.$content[0].scrollHeight); chatboxview.$content.scrollTop(chatboxview.$content[0].scrollHeight);
return test_utils.waitUntil(function () { return test_utils.waitUntil(function () {
return !chatboxview.$('.new-msgs-indicator').is(':visible'); return !chatboxview.$('.new-msgs-indicator').is(':visible');
}, 500); }, 700);
}).then(done); }).then(done);
})); }));
...@@ -1541,7 +1544,7 @@ ...@@ -1541,7 +1544,7 @@
view.model.maximize(); view.model.maximize();
return test_utils.waitUntil(function () { return test_utils.waitUntil(function () {
return view.model.get('chat_state') === 'active'; return view.model.get('chat_state') === 'active';
}, 500); }, 700);
}).then(function () { }).then(function () {
expect(_converse.connection.send).toHaveBeenCalled(); expect(_converse.connection.send).toHaveBeenCalled();
var calls = _.filter(_converse.connection.send.calls.all(), function (call) { var calls = _.filter(_converse.connection.send.calls.all(), function (call) {
...@@ -1693,9 +1696,8 @@ ...@@ -1693,9 +1696,8 @@
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length; return _converse.rosterview.$el.find('.roster-group li').length;
}, 300) }, 700).then(function () {
.then(function () {
_converse.TIMEOUTS.PAUSED = 200; // Make the timeout shorter so that we can test _converse.TIMEOUTS.PAUSED = 200; // Make the timeout shorter so that we can test
contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
...@@ -1715,7 +1717,7 @@ ...@@ -1715,7 +1717,7 @@
return test_utils.waitUntil(function () { return test_utils.waitUntil(function () {
return view.model.get('chat_state') === 'paused'; return view.model.get('chat_state') === 'paused';
}, 500); }, 500);
}).then(function () { }).then(function () {
expect(_converse.connection.send).toHaveBeenCalled(); expect(_converse.connection.send).toHaveBeenCalled();
var calls = _.filter(_converse.connection.send.calls.all(), function (call) { var calls = _.filter(_converse.connection.send.calls.all(), function (call) {
return call.args[0] instanceof Strophe.Builder; return call.args[0] instanceof Strophe.Builder;
......
...@@ -182,14 +182,14 @@ ...@@ -182,14 +182,14 @@
var promise = test_utils.waitUntil(function () { var promise = test_utils.waitUntil(function () {
return $roster.find('li:visible').length === 15; return $roster.find('li:visible').length === 15;
}, 500).then(function (contacts) { }, 600).then(function (contacts) {
expect($roster.find('ul.roster-group-contacts:visible').length).toBe(5); expect($roster.find('ul.roster-group-contacts:visible').length).toBe(5);
$filter.val("candice"); $filter.val("candice");
$filter.trigger('keydown'); $filter.trigger('keydown');
return test_utils.waitUntil(function () { return test_utils.waitUntil(function () {
return $roster.find('li:visible').length === 1; return $roster.find('li:visible').length === 1;
}, 500); }, 600);
}).then(function (contacts) { }).then(function (contacts) {
// Only one roster contact is now visible // Only one roster contact is now visible
expect($roster.find('li:visible').length).toBe(1); expect($roster.find('li:visible').length).toBe(1);
...@@ -203,7 +203,7 @@ ...@@ -203,7 +203,7 @@
$filter.trigger('keydown'); $filter.trigger('keydown');
return test_utils.waitUntil(function () { return test_utils.waitUntil(function () {
return $roster.find('li:visible').length === 5; return $roster.find('li:visible').length === 5;
}, 500) }, 600)
}).then(function (contacts) { }).then(function (contacts) {
// Five roster contact is now visible // Five roster contact is now visible
expect($roster.find('li:visible').length).toBe(5); expect($roster.find('li:visible').length).toBe(5);
...@@ -220,7 +220,7 @@ ...@@ -220,7 +220,7 @@
$filter.trigger('keydown'); $filter.trigger('keydown');
return test_utils.waitUntil(function () { return test_utils.waitUntil(function () {
return $roster.find('li:visible').length === 0; return $roster.find('li:visible').length === 0;
}, 500) }, 600)
}).then(function () { }).then(function () {
expect($roster.find('ul.roster-group-contacts:visible a.group-toggle').length).toBe(0); expect($roster.find('ul.roster-group-contacts:visible a.group-toggle').length).toBe(0);
$filter = _converse.rosterview.$('.roster-filter'); $filter = _converse.rosterview.$('.roster-filter');
...@@ -228,7 +228,7 @@ ...@@ -228,7 +228,7 @@
$filter.trigger('keydown'); $filter.trigger('keydown');
return test_utils.waitUntil(function () { return test_utils.waitUntil(function () {
return $roster.find('li:visible').length === 15; return $roster.find('li:visible').length === 15;
}, 500) }, 600)
}).then(function () { }).then(function () {
expect($roster.find('ul.roster-group-contacts:visible').length).toBe(5); expect($roster.find('ul.roster-group-contacts:visible').length).toBe(5);
_converse.roster_groups = false; _converse.roster_groups = false;
...@@ -253,14 +253,14 @@ ...@@ -253,14 +253,14 @@
$type.val('groups'); $type.val('groups');
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return $roster.find('li:visible').length === 15; return $roster.find('li:visible').length === 15;
}, 500).then(function () { }, 600).then(function () {
expect($roster.find('div.roster-group:visible a.group-toggle').length).toBe(5); expect($roster.find('div.roster-group:visible a.group-toggle').length).toBe(5);
$filter.val("colleagues"); $filter.val("colleagues");
$filter.trigger('keydown'); $filter.trigger('keydown');
return test_utils.waitUntil(function () { return test_utils.waitUntil(function () {
return $roster.find('div.roster-group:not(.collapsed) a.group-toggle').length === 1; return $roster.find('div.roster-group:not(.collapsed) a.group-toggle').length === 1;
}, 500); }, 600);
}).then(function () { }).then(function () {
expect(_.trim($roster.find('div.roster-group:not(.collapsed) a').eq(0).text())).toBe('colleagues'); expect(_.trim($roster.find('div.roster-group:not(.collapsed) a').eq(0).text())).toBe('colleagues');
expect($roster.find('div.roster-group:not(.collapsed) li:visible').length).toBe(3); expect($roster.find('div.roster-group:not(.collapsed) li:visible').length).toBe(3);
...@@ -281,7 +281,7 @@ ...@@ -281,7 +281,7 @@
$filter.trigger('keydown'); $filter.trigger('keydown');
return test_utils.waitUntil(function () { return test_utils.waitUntil(function () {
return $roster.find('div.roster-group.collapsed a.group-toggle').length === 0; return $roster.find('div.roster-group.collapsed a.group-toggle').length === 0;
}, 500); }, 600);
}).then(function () { }).then(function () {
expect($roster.find('div.roster-group:not(collapsed)').length).toBe(5); expect($roster.find('div.roster-group:not(collapsed)').length).toBe(5);
expect($roster.find('div.roster-group:not(collapsed) li').length).toBe(15); expect($roster.find('div.roster-group:not(collapsed) li').length).toBe(15);
...@@ -418,8 +418,8 @@ ...@@ -418,8 +418,8 @@
}); });
} }
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('li:visible').length; return _converse.rosterview.$el.find('li:visible').length === 30;
}, 500).then(function () { }, 600).then(function () {
// Check that usernames appear alphabetically per group // Check that usernames appear alphabetically per group
_.each(groups, function (name) { _.each(groups, function (name) {
var $contacts = _converse.rosterview.$('.roster-group[data-group="'+name+'"] li'); var $contacts = _converse.rosterview.$('.roster-group[data-group="'+name+'"] li');
...@@ -528,7 +528,7 @@ ...@@ -528,7 +528,7 @@
_addContacts(_converse); _addContacts(_converse);
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('li').length; return _converse.rosterview.$el.find('li').length;
}, 500).then(function () { }, 700).then(function () {
expect(_converse.rosterview.$el.is(':visible')).toEqual(true); expect(_converse.rosterview.$el.is(':visible')).toEqual(true);
expect(_converse.rosterview.update).toHaveBeenCalled(); expect(_converse.rosterview.update).toHaveBeenCalled();
expect(_converse.rosterview.$el.find('li:visible').length).toBe(3); expect(_converse.rosterview.$el.find('li:visible').length).toBe(3);
...@@ -575,13 +575,12 @@ ...@@ -575,13 +575,12 @@
}); });
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return _converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')").length; return _converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')").length;
}, 500) }, 700).then(function () {
.then(function () {
_converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')") _converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')")
.parent().siblings('.remove-xmpp-contact').click(); .parent().siblings('.remove-xmpp-contact').click();
return test_utils.waitUntil(function () { return test_utils.waitUntil(function () {
return _converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')").length === 0 return _converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')").length === 0
}, 500) }, 700)
}).then(function () { }).then(function () {
expect(window.confirm).toHaveBeenCalled(); expect(window.confirm).toHaveBeenCalled();
expect(_converse.connection.sendIQ).toHaveBeenCalled(); expect(_converse.connection.sendIQ).toHaveBeenCalled();
...@@ -609,9 +608,9 @@ ...@@ -609,9 +608,9 @@
if (typeof callback === "function") { return callback(); } if (typeof callback === "function") { return callback(); }
}); });
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return _converse.rosterview.get('Pending contacts').$el.is(':visible'); var $pending_contacts = _converse.rosterview.get('Pending contacts').$el;
}, 500) return $pending_contacts.is(':visible') && $pending_contacts.find('li:visible').length;
.then(function () { }, 700).then(function () {
_converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')") _converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')")
.parent().siblings('.remove-xmpp-contact').click(); .parent().siblings('.remove-xmpp-contact').click();
expect(window.confirm).toHaveBeenCalled(); expect(window.confirm).toHaveBeenCalled();
...@@ -644,6 +643,7 @@ ...@@ -644,6 +643,7 @@
function (done, _converse) { function (done, _converse) {
var i, t; var i, t;
test_utils.openControlBox();
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
spyOn(_converse.rosterview, 'update').and.callThrough(); spyOn(_converse.rosterview, 'update').and.callThrough();
for (i=0; i<mock.pend_names.length; i++) { for (i=0; i<mock.pend_names.length; i++) {
...@@ -655,18 +655,25 @@ ...@@ -655,18 +655,25 @@
}); });
expect(_converse.rosterview.update).toHaveBeenCalled(); expect(_converse.rosterview.update).toHaveBeenCalled();
} }
// Check that they are sorted alphabetically return test_utils.waitUntil(function () {
t = _.reduce(_converse.rosterview.get('Pending contacts').$el.find('.pending-xmpp-contact span'), function (result, value) { return _converse.rosterview.get('Pending contacts').$el.find('li:visible').length;
return result + _.trim(value.textContent); }, 700).then(function () {
}, ''); // Check that they are sorted alphabetically
expect(t).toEqual(mock.pend_names.slice(0,i+1).sort().join('')); t = _.reduce(_converse.rosterview.get('Pending contacts').$el.find('.pending-xmpp-contact span'),
done(); function (result, value) {
return result + _.trim(value.textContent);
}, '');
expect(t).toEqual(mock.pend_names.slice(0,i+1).sort().join(''));
done();
});
})); }));
}); });
describe("Existing Contacts", function () { describe("Existing Contacts", function () {
var _addContacts = function (_converse) { var _addContacts = function (_converse) {
test_utils.createContacts(_converse, 'current').openControlBox().openContactsPanel(_converse); test_utils.createContacts(_converse, 'current')
.openControlBox()
.openContactsPanel(_converse);
}; };
it("can be collapsed under their own header", it("can be collapsed under their own header",
...@@ -717,6 +724,7 @@ ...@@ -717,6 +724,7 @@
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched'], {},
function (done, _converse) { function (done, _converse) {
test_utils.openControlBox();
spyOn(_converse.rosterview, 'update').and.callThrough(); spyOn(_converse.rosterview, 'update').and.callThrough();
for (var i=0; i<mock.cur_names.length; i++) { for (var i=0; i<mock.cur_names.length; i++) {
_converse.roster.create({ _converse.roster.create({
...@@ -729,11 +737,13 @@ ...@@ -729,11 +737,13 @@
} }
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('li').length; return _converse.rosterview.$el.find('li').length;
}).then(function () { }, 600).then(function () {
// Check that they are sorted alphabetically // Check that they are sorted alphabetically
var t = _.reduce(_converse.rosterview.$('.roster-group').find('.current-xmpp-contact.offline a.open-chat'), function (result, value) { var t = _.reduce(_converse.rosterview.$('.roster-group')
return result + _.trim(value.textContent); .find('.current-xmpp-contact.offline a.open-chat'),
}, ''); function (result, value) {
return result + _.trim(value.textContent);
}, '');
expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join('')); expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
done(); done();
}); });
...@@ -781,9 +791,8 @@ ...@@ -781,9 +791,8 @@
fullname: name fullname: name
}); });
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length; return _converse.rosterview.$el.find('.roster-group li').length;
}, 500) }, 700).then(function () {
.then(function () {
spyOn(window, 'confirm').and.returnValue(true); spyOn(window, 'confirm').and.returnValue(true);
spyOn(contact, 'removeFromRoster'); spyOn(contact, 'removeFromRoster');
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback) {
...@@ -808,9 +817,8 @@ ...@@ -808,9 +817,8 @@
_addContacts(_converse); _addContacts(_converse);
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length; return _converse.rosterview.$el.find('.roster-group li').length;
}, 500) }, 700).then(function () {
.then(function () {
var jid, t; var jid, t;
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
spyOn(_converse.rosterview, 'update').and.callThrough(); spyOn(_converse.rosterview, 'update').and.callThrough();
...@@ -836,9 +844,8 @@ ...@@ -836,9 +844,8 @@
_addContacts(_converse); _addContacts(_converse);
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length; return _converse.rosterview.$el.find('.roster-group li').length;
}, 500) }, 700).then(function () {
.then(function () {
var jid, t; var jid, t;
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
spyOn(_converse.rosterview, 'update').and.callThrough(); spyOn(_converse.rosterview, 'update').and.callThrough();
...@@ -865,9 +872,8 @@ ...@@ -865,9 +872,8 @@
_addContacts(_converse); _addContacts(_converse);
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length; return _converse.rosterview.$el.find('.roster-group li').length;
}, 500) }, 700).then(function () {
.then(function () {
var jid, t; var jid, t;
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
spyOn(_converse.rosterview, 'update').and.callThrough(); spyOn(_converse.rosterview, 'update').and.callThrough();
...@@ -894,9 +900,8 @@ ...@@ -894,9 +900,8 @@
_addContacts(_converse); _addContacts(_converse);
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length; return _converse.rosterview.$el.find('.roster-group li').length;
}, 500) }, 700).then(function () {
.then(function () {
var jid, t; var jid, t;
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
spyOn(_converse.rosterview, 'update').and.callThrough(); spyOn(_converse.rosterview, 'update').and.callThrough();
...@@ -923,7 +928,7 @@ ...@@ -923,7 +928,7 @@
_addContacts(_converse); _addContacts(_converse);
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length; return _converse.rosterview.$el.find('.roster-group li').length;
}, 500) }, 500)
.then(function () { .then(function () {
var jid, t; var jid, t;
...@@ -952,8 +957,8 @@ ...@@ -952,8 +957,8 @@
_addContacts(_converse); _addContacts(_converse);
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length; return _converse.rosterview.$el.find('.roster-group li').length;
}, 500).then(function () { }, 700).then(function () {
var i, jid; var i, jid;
for (i=0; i<3; 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';
...@@ -1071,13 +1076,17 @@ ...@@ -1071,13 +1076,17 @@
fullname: mock.req_names[i] fullname: mock.req_names[i]
}); });
} }
expect(_converse.rosterview.update).toHaveBeenCalled(); test_utils.waitUntil(function () {
// Check that they are sorted alphabetically return _converse.rosterview.get('Contact requests').$el.find('li').length;
children = _converse.rosterview.get('Contact requests').$el.find('.requesting-xmpp-contact span'); }, 700).then(function () {
names = []; expect(_converse.rosterview.update).toHaveBeenCalled();
children.each(addName); // Check that they are sorted alphabetically
expect(names.join('')).toEqual(mock.req_names.slice(0,mock.req_names.length+1).sort().join('')); children = _converse.rosterview.get('Contact requests').$el.find('.requesting-xmpp-contact span');
done(); names = [];
children.each(addName);
expect(names.join('')).toEqual(mock.req_names.slice(0,mock.req_names.length+1).sort().join(''));
done();
});
})); }));
it("do not have a header if there aren't any", it("do not have a header if there aren't any",
...@@ -1096,9 +1105,8 @@ ...@@ -1096,9 +1105,8 @@
fullname: name fullname: name
}); });
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length; return _converse.rosterview.$el.find('.roster-group li').length;
}, 500) }, 700).then(function () {
.then(function () {
expect(_converse.rosterview.get('Contact requests').$el.is(':visible')).toEqual(true); expect(_converse.rosterview.get('Contact requests').$el.is(':visible')).toEqual(true);
_converse.rosterview.$el.find(".req-contact-name:contains('"+name+"')") _converse.rosterview.$el.find(".req-contact-name:contains('"+name+"')")
.parent().siblings('.request-actions') .parent().siblings('.request-actions')
...@@ -1116,8 +1124,8 @@ ...@@ -1116,8 +1124,8 @@
test_utils.createContacts(_converse, 'requesting').openControlBox(); test_utils.createContacts(_converse, 'requesting').openControlBox();
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length; return _converse.rosterview.$el.find('.roster-group li').length;
}, 500).then(function () { }, 700).then(function () {
checkHeaderToggling.apply( checkHeaderToggling.apply(
_converse, _converse,
[_converse.rosterview.get('Contact requests').$el] [_converse.rosterview.get('Contact requests').$el]
...@@ -1132,9 +1140,8 @@ ...@@ -1132,9 +1140,8 @@
test_utils.createContacts(_converse, 'requesting').openControlBox(); test_utils.createContacts(_converse, 'requesting').openControlBox();
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length; return _converse.rosterview.$el.find('.roster-group li').length;
}, 500) }, 700).then(function () {
.then(function () {
// TODO: Testing can be more thorough here, the user is // TODO: Testing can be more thorough here, the user is
// actually not accepted/authorized because of // actually not accepted/authorized because of
// mock_connection. // mock_connection.
...@@ -1161,9 +1168,8 @@ ...@@ -1161,9 +1168,8 @@
test_utils.createContacts(_converse, 'requesting').openControlBox(); test_utils.createContacts(_converse, 'requesting').openControlBox();
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length; return _converse.rosterview.$el.find('.roster-group li').length;
}, 500) }, 700).then(function () {
.then(function () {
_converse.rosterview.update(); // XXX: Hack to make sure $roster element is attaced. _converse.rosterview.update(); // XXX: Hack to make sure $roster element is attaced.
var name = mock.req_names.sort()[1]; var name = mock.req_names.sort()[1];
var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost'; var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
...@@ -1193,7 +1199,7 @@ ...@@ -1193,7 +1199,7 @@
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return $('a:contains("Contact requests")').length; return $('a:contains("Contact requests")').length;
}).then(function () { }, 700).then(function () {
expect(_converse.roster.pluck('jid').length).toBe(1); expect(_converse.roster.pluck('jid').length).toBe(1);
expect(_.includes(_converse.roster.pluck('jid'), 'data@enterprise')).toBeTruthy(); expect(_.includes(_converse.roster.pluck('jid'), 'data@enterprise')).toBeTruthy();
// Taken from the spec // Taken from the spec
...@@ -1265,9 +1271,8 @@ ...@@ -1265,9 +1271,8 @@
test_utils.createContacts(_converse, 'all').openControlBox(); test_utils.createContacts(_converse, 'all').openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length; return _converse.rosterview.$el.find('.roster-group li').length;
}, 500) }, 700).then(function () {
.then(function () {
var jid, name, i; var jid, name, i;
for (i=0; i<mock.cur_names.length; i++) { for (i=0; i<mock.cur_names.length; i++) {
name = mock.cur_names[i]; name = mock.cur_names[i];
...@@ -1324,8 +1329,8 @@ ...@@ -1324,8 +1329,8 @@
fullname: mock.pend_names[0] fullname: mock.pend_names[0]
}); });
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length; return _converse.rosterview.$el.find('.roster-group li').length;
}, 500).then(function () { }, 700).then(function () {
// Checking that only one entry is created because both JID is same (Case sensitive check) // Checking that only one entry is created because both JID is same (Case sensitive check)
expect(_converse.rosterview.$el.find('li:visible').length).toBe(1); expect(_converse.rosterview.$el.find('li:visible').length).toBe(1);
expect(_converse.rosterview.update).toHaveBeenCalled(); expect(_converse.rosterview.update).toHaveBeenCalled();
......
...@@ -228,11 +228,11 @@ ...@@ -228,11 +228,11 @@
expect(_converse.roster.updateContact).toHaveBeenCalled(); expect(_converse.roster.updateContact).toHaveBeenCalled();
// Check that the user is now properly shown as a pending // Check that the user is now properly shown as a pending
// contact in the roster. // contact in the roster.
var $header = $('a:contains("Pending contacts")');
return test_utils.waitUntil(function () { return test_utils.waitUntil(function () {
return $('a:contains("Pending contacts")').length && $header.is(":visible"); var $header = $('a:contains("Pending contacts")');
}, 300); var $contacts = $header.parent().find('li');
return $contacts.length;
}, 600);
}).then(function () { }).then(function () {
var $header = $('a:contains("Pending contacts")'); var $header = $('a:contains("Pending contacts")');
var $contacts = $header.parent().find('li'); var $contacts = $header.parent().find('li');
...@@ -297,10 +297,16 @@ ...@@ -297,10 +297,16 @@
// The contact should now be visible as an existing // The contact should now be visible as an existing
// contact (but still offline). // contact (but still offline).
$header = $('a:contains("My contacts")'); return test_utils.waitUntil(function () {
var $header = $('a:contains("My contacts")');
var $contacts = $header.parent().find('li');
return $contacts.length;
}, 600);
}).then(function () {
var $header = $('a:contains("My contacts")');
expect($header.length).toBe(1); expect($header.length).toBe(1);
expect($header.is(":visible")).toBeTruthy(); expect($header.is(":visible")).toBeTruthy();
$contacts = $header.parent().find('li'); var $contacts = $header.parent().find('li');
expect($contacts.length).toBe(1); expect($contacts.length).toBe(1);
// Check that it has the right classes and text // Check that it has the right classes and text
expect($contacts.hasClass('to')).toBeTruthy(); expect($contacts.hasClass('to')).toBeTruthy();
...@@ -482,10 +488,12 @@ ...@@ -482,10 +488,12 @@
sent_IQ = iq; sent_IQ = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
return test_utils.waitUntil(function () {
var $header = $('a:contains("My contacts")');
var $contacts = $header.parent().find('li');
return $contacts.length;
}, 600).then(function () {
test_utils.waitUntil(function () {
return $('a:contains("My contacts")').length;
}).then(function () {
var $header = $('a:contains("My contacts")'); var $header = $('a:contains("My contacts")');
// remove the first user // remove the first user
$($header.parent().find('li .remove-xmpp-contact').get(0)).click(); $($header.parent().find('li .remove-xmpp-contact').get(0)).click();
...@@ -547,9 +555,11 @@ ...@@ -547,9 +555,11 @@
'xmlns': Strophe.NS.NICK, 'xmlns': Strophe.NS.NICK,
}).t('Clint Contact'); }).t('Clint Contact');
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
test_utils.waitUntil(function () { return test_utils.waitUntil(function () {
return $('a:contains("Contact requests")').length; var $header = $('a:contains("Contact requests")');
}).then(function () { var $contacts = $header.parent().find('li');
return $contacts.length;
}, 600).then(function () {
expect(_converse.emit).toHaveBeenCalledWith('contactRequest', jasmine.any(Object)); expect(_converse.emit).toHaveBeenCalledWith('contactRequest', jasmine.any(Object));
var $header = $('a:contains("Contact requests")'); var $header = $('a:contains("Contact requests")');
expect($header.length).toBe(1); expect($header.length).toBe(1);
......
...@@ -22,6 +22,7 @@ require.config({ ...@@ -22,6 +22,7 @@ require.config({
"backbone.browserStorage": "node_modules/backbone.browserStorage/backbone.browserStorage", "backbone.browserStorage": "node_modules/backbone.browserStorage/backbone.browserStorage",
"backbone.noconflict": "src/backbone.noconflict", "backbone.noconflict": "src/backbone.noconflict",
"backbone.overview": "node_modules/backbone.overview/backbone.overview", "backbone.overview": "node_modules/backbone.overview/backbone.overview",
"backbone.orderedlistview": "node_modules/backbone.overview/backbone.orderedlistview",
"backbone.vdomview": "node_modules/backbone.vdomview/backbone.vdomview", "backbone.vdomview": "node_modules/backbone.vdomview/backbone.vdomview",
"emojione": "node_modules/emojione/lib/js/emojione", "emojione": "node_modules/emojione/lib/js/emojione",
"es6-promise": "node_modules/es6-promise/dist/es6-promise.auto", "es6-promise": "node_modules/es6-promise/dist/es6-promise.auto",
......
...@@ -16,8 +16,7 @@ ...@@ -16,8 +16,7 @@
"strophe", "strophe",
"pluggable", "pluggable",
"backbone.noconflict", "backbone.noconflict",
"backbone.browserStorage", "backbone.browserStorage"
"backbone.overview",
], factory); ], factory);
}(this, function (sizzle, Promise, _, polyfill, i18n, utils, moment, Strophe, pluggable, Backbone) { }(this, function (sizzle, Promise, _, polyfill, i18n, utils, moment, Strophe, pluggable, Backbone) {
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
"awesomplete", "awesomplete",
"converse-chatview", "converse-chatview",
"converse-disco", "converse-disco",
"backbone.overview",
"backbone.orderedlistview",
"backbone.vdomview" "backbone.vdomview"
], factory); ], factory);
}(this, function ( }(this, function (
...@@ -2213,16 +2215,17 @@ ...@@ -2213,16 +2215,17 @@
}, },
}); });
_converse.ChatRoomOccupantsView = Backbone.Overview.extend({ _converse.ChatRoomOccupantsView = Backbone.OrderedListView.extend({
tagName: 'div', tagName: 'div',
className: 'occupants', className: 'occupants',
listItems: 'model',
sortEvent: 'change:role',
listSelector: '.occupant-list',
ItemView: _converse.ChatRoomOccupantView,
initialize () { initialize () {
this.model.on("add", this.onOccupantAdded, this); Backbone.OrderedListView.prototype.initialize.apply(this, arguments);
this.model.on("change:role", (occupant) => {
this.model.sort();
this.positionOccupant(occupant);
});
this.chatroomview = this.model.chatroomview; this.chatroomview = this.model.chatroomview;
this.chatroomview.model.on('change:open', this.renderInviteWidget, this); this.chatroomview.model.on('change:open', this.renderInviteWidget, this);
...@@ -2247,9 +2250,7 @@ ...@@ -2247,9 +2250,7 @@
this.model.fetch({ this.model.fetch({
'add': true, 'add': true,
'silent': true, 'silent': true,
'success': () => { 'success': this.sortAndPositionAllItems.bind(this)
this.model.each(this.onOccupantAdded.bind(this));
}
}); });
}, },
...@@ -2353,57 +2354,12 @@ ...@@ -2353,57 +2354,12 @@
this.debouncedRenderRoomFeatures(); this.debouncedRenderRoomFeatures();
}, },
setOccupantsHeight () { setOccupantsHeight () {
const el = this.el.querySelector('.chatroom-features'); const el = this.el.querySelector('.chatroom-features');
this.el.querySelector('.occupant-list').style.cssText = this.el.querySelector('.occupant-list').style.cssText =
`height: calc(100% - ${el.offsetHeight}px - 5em);`; `height: calc(100% - ${el.offsetHeight}px - 5em);`;
}, },
positionOccupant (occupant) {
/* Positions an occupant correctly in the list of
* occupants.
*
* IMPORTANT: there's an important implicit assumption being
* made here. And that is that initially this method gets called
* for each occupant in the right positional order.
*
* In other words, it gets called for the 0th, then the
* 1st, then the 2nd, 3rd and so on.
*
* That's why we call it in the "success" handler after
* fetching the occupants, so that we know we have ALL of
* them and that they're sorted.
*/
const view = this.get(occupant.get('id'));
view.render();
const list = this.el.querySelector('.occupant-list');
const index = this.model.indexOf(view.model);
if (index === 0) {
list.insertAdjacentElement('afterbegin', view.el);
} else if (index === (this.model.length-1)) {
list.insertAdjacentElement('beforeend', view.el);
} else {
const neighbour_el = list.querySelector('li:nth-child('+index+')');
neighbour_el.insertAdjacentElement('afterend', view.el);
}
return view;
},
onOccupantAdded (item) {
let view = this.get(item.get('id'));
if (!view) {
view = this.add(
item.get('id'),
new _converse.ChatRoomOccupantView({model: item})
);
} else {
view.model = item;
view.initialize();
}
this.positionOccupant(item);
},
parsePresence (pres) { parsePresence (pres) {
const id = Strophe.getResourceFromJid(pres.getAttribute("from")); const id = Strophe.getResourceFromJid(pres.getAttribute("from"));
const data = { const data = {
......
...@@ -285,8 +285,12 @@ ...@@ -285,8 +285,12 @@
this.model.on("reset", this.reset, this); this.model.on("reset", this.reset, this);
_converse.on('rosterGroupsFetched', this.positionFetchedGroups, this); _converse.on('rosterGroupsFetched', this.positionFetchedGroups, this);
_converse.on('rosterContactsFetched', () => { _converse.on('rosterContactsFetched', () => {
_converse.roster.each(this.onContactAdded.bind(this)); _converse.roster.each((contact) => {
this.addRosterContact(contact, {'silent': true});
});
this.update(); this.update();
this.updateFilter();
this.trigger('rosterContactsFetchedAndProcessed');
}); });
this.createRosterFilter(); this.createRosterFilter();
}, },
...@@ -474,11 +478,11 @@ ...@@ -474,11 +478,11 @@
return this.model.create({name, id: b64_sha1(name)}); return this.model.create({name, id: b64_sha1(name)});
}, },
addContactToGroup (contact, name) { addContactToGroup (contact, name, options) {
this.getGroup(name).contacts.add(contact); this.getGroup(name).contacts.add(contact, options);
}, },
addExistingContact (contact) { addExistingContact (contact, options) {
let groups; let groups;
if (_converse.roster_groups) { if (_converse.roster_groups) {
groups = contact.get('groups'); groups = contact.get('groups');
...@@ -488,17 +492,17 @@ ...@@ -488,17 +492,17 @@
} else { } else {
groups = [HEADER_CURRENT_CONTACTS]; groups = [HEADER_CURRENT_CONTACTS];
} }
_.each(groups, _.bind(this.addContactToGroup, this, contact)); _.each(groups, _.bind(this.addContactToGroup, this, contact, _, options));
}, },
addRosterContact (contact) { addRosterContact (contact, options) {
if (contact.get('subscription') === 'both' || contact.get('subscription') === 'to') { if (contact.get('subscription') === 'both' || contact.get('subscription') === 'to') {
this.addExistingContact(contact); this.addExistingContact(contact, options);
} else { } else {
if ((contact.get('ask') === 'subscribe') || (contact.get('subscription') === 'from')) { if ((contact.get('ask') === 'subscribe') || (contact.get('subscription') === 'from')) {
this.addContactToGroup(contact, HEADER_PENDING_CONTACTS); this.addContactToGroup(contact, HEADER_PENDING_CONTACTS, options);
} else if (contact.get('requesting') === true) { } else if (contact.get('requesting') === true) {
this.addContactToGroup(contact, HEADER_REQUESTING_CONTACTS); this.addContactToGroup(contact, HEADER_REQUESTING_CONTACTS, options);
} }
} }
return this; return this;
...@@ -670,22 +674,34 @@ ...@@ -670,22 +674,34 @@
}); });
_converse.RosterGroupView = Backbone.Overview.extend({ _converse.RosterGroupView = Backbone.OrderedListView.extend({
tagName: 'div', tagName: 'div',
className: 'roster-group', className: 'roster-group',
events: { events: {
"click a.group-toggle": "toggle" "click a.group-toggle": "toggle"
}, },
listItems: 'model.contacts',
sortEvent: 'change:chat_status',
listSelector: '.roster-group-contacts',
ItemView: _converse.RosterContactView,
initialize () { initialize () {
this.sortEventually = _.debounce(this.sortAndPositionAll, 500); Backbone.OrderedListView.prototype.initialize.apply(this, arguments);
this.model.contacts.on("add", this.onContactAdded, this);
this.model.contacts.on("change:subscription", this.onContactSubscriptionChange, this); this.model.contacts.on("change:subscription", this.onContactSubscriptionChange, this);
this.model.contacts.on("change:requesting", this.onContactRequestChange, this); this.model.contacts.on("change:requesting", this.onContactRequestChange, this);
this.model.contacts.on("change:chat_status", this.sortEventually, this);
this.model.contacts.on("destroy", this.onRemove, this); this.model.contacts.on("destroy", this.onRemove, this);
this.model.contacts.on("remove", this.onRemove, this); this.model.contacts.on("remove", this.onRemove, this);
_converse.roster.on('change:groups', this.onContactGroupChange, this); _converse.roster.on('change:groups', this.onContactGroupChange, this);
// This event gets triggered once *all* contacts (i.e. not
// just this group's) have been fetched from browser
// storage or the XMPP server and once they've been
// assigned to their various groups.
_converse.rosterview.on(
'rosterContactsFetchedAndProcessed',
this.sortAndPositionAllItems.bind(this)
);
}, },
render () { render () {
...@@ -700,49 +716,19 @@ ...@@ -700,49 +716,19 @@
return this; return this;
}, },
createContactView (contact) { createItemView (contact) {
const contact_view = new _converse.RosterContactView({model: contact}); const contact_view =
this.add(contact.get('id'), contact_view); Backbone.OrderedListView.prototype.createItemView.apply(this, arguments);
contact_view.render();
return contact_view;
},
onContactAdded (contact) {
const contact_view = this.positionContact(contact);
if (contact_view.mayBeShown()) { if (contact_view.mayBeShown()) {
if (this.model.get('state') === _converse.CLOSED) { if (this.model.get('state') === _converse.CLOSED) {
u.hideElement(contact_view.el); u.hideElement(contact_view.el);
u.showElement(this.el);
} else { } else {
u.showElement(contact_view.el); u.showElement(contact_view.el);
u.showElement(this.el);
} }
u.showElement(this.el);
} }
}, },
positionContact (contact) {
/* Place the contact's DOM element in the correct alphabetical
* position amongst the other contacts in this group.
*/
const view = this.get(contact.get('id')) || this.createContactView(contact);
const list = this.contacts_el;
const index = this.model.contacts.indexOf(contact);
if (index === 0) {
list.insertAdjacentElement('afterbegin', view.el);
} else if (index === (this.model.contacts.length-1)) {
list.insertAdjacentElement('beforeend', view.el);
} else {
const neighbour_el = list.querySelector('li:nth-child('+index+')');
neighbour_el.insertAdjacentElement('afterend', view.el);
}
return view;
},
sortAndPositionAll () {
this.model.contacts.sort();
this.model.contacts.each(this.positionContact.bind(this));
},
show () { show () {
u.showElement(this.el); u.showElement(this.el);
_.each(this.getAll(), (contact_view) => { _.each(this.getAll(), (contact_view) => {
...@@ -851,7 +837,7 @@ ...@@ -851,7 +837,7 @@
if (in_this_group && !in_this_overview) { if (in_this_group && !in_this_overview) {
this.model.contacts.remove(cid); this.model.contacts.remove(cid);
} else if (!in_this_group && in_this_overview) { } else if (!in_this_group && in_this_overview) {
this.onContactAdded(contact); this.items.trigger('add', contact);
} }
}, },
......
...@@ -106,6 +106,7 @@ ...@@ -106,6 +106,7 @@
'bosh_service_url': 'localhost', 'bosh_service_url': 'localhost',
'connection': connection, 'connection': connection,
'animate': false, 'animate': false,
'use_emojione': false,
'no_trimming': true, 'no_trimming': true,
'auto_login': true, 'auto_login': true,
'jid': 'dummy@localhost', 'jid': 'dummy@localhost',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment