Commit b2240cfe authored by JC Brand's avatar JC Brand

Use $.when to keep track of all outgoing promises

Now that we are sending multiple IQ stanzas when setting affiliations.
We now again have a sendAffiliation method, so we use that.
parent f5fbf712
...@@ -1163,11 +1163,59 @@ ...@@ -1163,11 +1163,59 @@
})); }));
it("to make a user an owner", mock.initConverse(function (converse) {
var sent_IQ, IQ_id;
var sendIQ = converse.connection.sendIQ;
spyOn(converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) {
sent_IQ = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback);
});
test_utils.openChatRoom(converse, 'lounge', 'localhost', 'dummy');
var view = converse.chatboxviews.get('lounge@localhost');
spyOn(view, 'onMessageSubmitted').andCallThrough();
spyOn(view, 'setAffiliation').andCallThrough();
spyOn(view, 'showStatusNotification').andCallThrough();
spyOn(view, 'validateRoleChangeCommand').andCallThrough();
view.$el.find('.chat-textarea').text('/owner');
view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13}));
expect(view.onMessageSubmitted).toHaveBeenCalled();
expect(view.validateRoleChangeCommand).toHaveBeenCalled();
expect(view.showStatusNotification).toHaveBeenCalledWith(
"Error: the \"owner\" command takes two arguments, the user's nickname and optionally a reason.",
true
);
expect(view.setAffiliation).not.toHaveBeenCalled();
// Call now with the correct amount of arguments.
// XXX: Calling onMessageSubmitted directly, trying
// again via triggering Event doesn't work for some weird
// reason.
view.onMessageSubmitted('/owner annoyingGuy@localhost You\'re annoying');
expect(view.validateRoleChangeCommand.callCount).toBe(2);
expect(view.showStatusNotification.callCount).toBe(1);
expect(view.setAffiliation).toHaveBeenCalled();
// Check that the member list now gets updated
expect(sent_IQ.toLocaleString()).toBe(
"<iq to='lounge@localhost' type='set' xmlns='jabber:client' id='"+IQ_id+"'>"+
"<query xmlns='http://jabber.org/protocol/muc#admin'>"+
"<item affiliation='owner' jid='annoyingGuy@localhost'>"+
"<reason>You&apos;re annoying</reason>"+
"</item>"+
"</query>"+
"</iq>");
}));
it("to ban a user", mock.initConverse(function (converse) { it("to ban a user", mock.initConverse(function (converse) {
var sent_IQ, IQ_id;
var sendIQ = converse.connection.sendIQ;
spyOn(converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) {
sent_IQ = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback);
});
test_utils.openChatRoom(converse, 'lounge', 'localhost', 'dummy'); test_utils.openChatRoom(converse, 'lounge', 'localhost', 'dummy');
var view = converse.chatboxviews.get('lounge@localhost'); var view = converse.chatboxviews.get('lounge@localhost');
spyOn(view, 'onMessageSubmitted').andCallThrough(); spyOn(view, 'onMessageSubmitted').andCallThrough();
spyOn(view, 'setAffiliations').andCallThrough(); spyOn(view, 'setAffiliation').andCallThrough();
spyOn(view, 'showStatusNotification').andCallThrough(); spyOn(view, 'showStatusNotification').andCallThrough();
spyOn(view, 'validateRoleChangeCommand').andCallThrough(); spyOn(view, 'validateRoleChangeCommand').andCallThrough();
view.$el.find('.chat-textarea').text('/ban'); view.$el.find('.chat-textarea').text('/ban');
...@@ -1178,16 +1226,24 @@ ...@@ -1178,16 +1226,24 @@
"Error: the \"ban\" command takes two arguments, the user's nickname and optionally a reason.", "Error: the \"ban\" command takes two arguments, the user's nickname and optionally a reason.",
true true
); );
expect(view.setAffiliations).not.toHaveBeenCalled(); expect(view.setAffiliation).not.toHaveBeenCalled();
// Call now with the correct amount of arguments. // Call now with the correct amount of arguments.
// XXX: Calling onMessageSubmitted directly, trying // XXX: Calling onMessageSubmitted directly, trying
// again via triggering Event doesn't work for some weird // again via triggering Event doesn't work for some weird
// reason. // reason.
view.onMessageSubmitted('/ban jid This is the reason'); view.onMessageSubmitted('/ban annoyingGuy@localhost You\'re annoying');
expect(view.validateRoleChangeCommand.callCount).toBe(2); expect(view.validateRoleChangeCommand.callCount).toBe(2);
expect(view.showStatusNotification.callCount).toBe(1); expect(view.showStatusNotification.callCount).toBe(1);
expect(view.setAffiliations).toHaveBeenCalled(); expect(view.setAffiliation).toHaveBeenCalled();
// Check that the member list now gets updated
expect(sent_IQ.toLocaleString()).toBe(
"<iq to='lounge@localhost' type='set' xmlns='jabber:client' id='"+IQ_id+"'>"+
"<query xmlns='http://jabber.org/protocol/muc#admin'>"+
"<item affiliation='outcast' jid='annoyingGuy@localhost'>"+
"<reason>You&apos;re annoying</reason>"+
"</item>"+
"</query>"+
"</iq>");
})); }));
}); });
......
...@@ -586,14 +586,52 @@ ...@@ -586,14 +586,52 @@
return delta; return delta;
}, },
setAffiliation: function (affiliation, members) {
/* Send an IQ stanzas to the server to modify one particular
* affiliation for certain members
*
* See: http://xmpp.org/extensions/xep-0045.html#modifymember
*
* Parameters:
* (Object) members: A map of jids, affiliations and
* optionally reasons. Only those entries with the
* same affiliation as being currently set will be
* considered.
*
* Returns:
* A promise which resolves and fails depending on the
* XMPP server response.
*/
var deferred = new $.Deferred();
var iq = $iq({to: this.model.get('jid'), type: "set"})
.c("query", {xmlns: Strophe.NS.MUC_ADMIN});
_.each(members, function (member) {
if (!_.isUndefined(member.affiliation) &&
member.affiliation !== affiliation) {
return;
}
iq.c("item", {
'affiliation': member.affiliation || affiliation,
'jid': member.jid
});
if (!_.isUndefined(member.reason)) {
iq.c("reason", member.reason).up();
}
iq.up();
});
converse.connection.sendIQ(iq, deferred.resolve, deferred.reject);
return deferred;
},
setAffiliations: function (members, onSuccess, onError) { setAffiliations: function (members, onSuccess, onError) {
/* Send an IQ stanza to the server to modify the /* Send IQ stanzas to the server to modify the
* affiliations in this room. * affiliations in this room.
* *
* See: http://xmpp.org/extensions/xep-0045.html#modifymember * See: http://xmpp.org/extensions/xep-0045.html#modifymember
* *
* Parameters: * Parameters:
* (Object) members: A map of jids and affiliations * (Object) members: A map of jids, affiliations and optionally reasons
* (Function) onSuccess: callback for a succesful response * (Function) onSuccess: callback for a succesful response
* (Function) onError: callback for an error response * (Function) onError: callback for an error response
*/ */
...@@ -602,26 +640,9 @@ ...@@ -602,26 +640,9 @@
onSuccess(null); onSuccess(null);
return; return;
} }
var room_jid = this.model.get('jid');
var affiliations = _.uniq(_.pluck(members, 'affiliation')); var affiliations = _.uniq(_.pluck(members, 'affiliation'));
_.each(affiliations, function (affiliation) { var promises = _.map(affiliations, _.partial(this.setAffiliation, _, members), this);
var iq = $iq({to: room_jid, type: "set"}) $.when.apply($, promises).done(onSuccess).fail(onError);
.c("query", {xmlns: Strophe.NS.MUC_ADMIN});
_.each(members, function (member) {
if (member.affiliation !== affiliation) {
return;
}
iq.c("item", {
'affiliation': member.affiliation,
'jid': member.jid
});
if (!_.isUndefined(member.reason)) {
iq.c("reason", member.reason).up();
}
iq.up();
});
converse.connection.sendIQ(iq, onSuccess, onError);
});
}, },
marshallAffiliationIQs: function () { marshallAffiliationIQs: function () {
...@@ -836,21 +857,17 @@ ...@@ -836,21 +857,17 @@
switch (match[1]) { switch (match[1]) {
case 'admin': case 'admin':
if (!this.validateRoleChangeCommand(match[1], args)) { break; } if (!this.validateRoleChangeCommand(match[1], args)) { break; }
this.setAffiliations( this.setAffiliation('admin',
[{'jid': args[0], [{ 'jid': args[0],
'affiliation': 'admin', 'reason': args[1]
'reason': args[1] }]).fail(this.onCommandError.bind(this));
}], undefined, this.onCommandError.bind(this)
);
break; break;
case 'ban': case 'ban':
if (!this.validateRoleChangeCommand(match[1], args)) { break; } if (!this.validateRoleChangeCommand(match[1], args)) { break; }
this.setAffiliations( this.setAffiliation('outcast',
[{'jid': args[0], [{ 'jid': args[0],
'affiliation': 'outcast', 'reason': args[1]
'reason': args[1] }]).fail(this.onCommandError.bind(this));
}], undefined, this.onCommandError.bind(this)
);
break; break;
case 'clear': case 'clear':
this.clearChatRoomMessages(); this.clearChatRoomMessages();
...@@ -894,12 +911,10 @@ ...@@ -894,12 +911,10 @@
break; break;
case 'member': case 'member':
if (!this.validateRoleChangeCommand(match[1], args)) { break; } if (!this.validateRoleChangeCommand(match[1], args)) { break; }
this.setAffiliations( this.setAffiliation('member',
[{'jid': args[0], [{ 'jid': args[0],
'affiliation': 'member', 'reason': args[1]
'reason': args[1] }]).fail(this.onCommandError.bind(this));
}], undefined, this.onCommandError.bind(this)
);
break; break;
case 'nick': case 'nick':
converse.connection.send($pres({ converse.connection.send($pres({
...@@ -910,12 +925,10 @@ ...@@ -910,12 +925,10 @@
break; break;
case 'owner': case 'owner':
if (!this.validateRoleChangeCommand(match[1], args)) { break; } if (!this.validateRoleChangeCommand(match[1], args)) { break; }
this.setAffiliations( this.setAffiliation('owner',
[{'jid': args[0], [{ 'jid': args[0],
'affiliation': 'owner', 'reason': args[1]
'reason': args[1] }]).fail(this.onCommandError.bind(this));
}], undefined, this.onCommandError.bind(this)
);
break; break;
case 'op': case 'op':
if (!this.validateRoleChangeCommand(match[1], args)) { break; } if (!this.validateRoleChangeCommand(match[1], args)) { break; }
...@@ -925,12 +938,10 @@ ...@@ -925,12 +938,10 @@
break; break;
case 'revoke': case 'revoke':
if (!this.validateRoleChangeCommand(match[1], args)) { break; } if (!this.validateRoleChangeCommand(match[1], args)) { break; }
this.setAffiliations( this.setAffiliation('none',
[{'jid': args[0], [{ 'jid': args[0],
'affiliation': 'none', 'reason': args[1]
'reason': args[1] }]).fail(this.onCommandError.bind(this));
}], undefined, this.onCommandError.bind(this)
);
break; break;
case 'topic': case 'topic':
converse.connection.send( converse.connection.send(
......
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