From 50275cce64b733d72d0c4e3a585c1f6060f7599c Mon Sep 17 00:00:00 2001 From: JC Brand Date: Wed, 2 Nov 2016 20:19:17 +0000 Subject: [PATCH] Remove shared state between tests Only a small subset of tests currently working with this. --- spec/converse.js | 135 +++++++--------- spec/protocol.js | 357 ++++++++++++++++++++++--------------------- src/converse-core.js | 9 ++ tests/main.js | 108 ++++++------- tests/mock.js | 83 ++++++---- tests/utils.js | 19 +-- 6 files changed, 347 insertions(+), 364 deletions(-) diff --git a/spec/converse.js b/spec/converse.js index 07091f650..33ec45582 100644 --- a/spec/converse.js +++ b/spec/converse.js @@ -1,4 +1,3 @@ -/*global converse */ (function (root, factory) { define([ "jquery", @@ -12,10 +11,15 @@ } (this, function ($, _, mock, test_utils) { var b64_sha1 = converse_api.env.b64_sha1; - return describe("Converse", $.proxy(function(mock, test_utils) { + describe("Converse", function() { + + afterEach(function () { + converse_api.user.logout(); + test_utils.clearBrowserStorage(); + }); describe("Authentication", function () { - it("needs either a bosh_service_url a websocket_url or both", function () { + it("needs either a bosh_service_url a websocket_url or both", mock.initConverse(function (converse) { var url = converse.bosh_service_url; var connection = converse.connection; delete converse.bosh_service_url; @@ -24,10 +28,10 @@ new Error("initConnection: you must supply a value for either the bosh_service_url or websocket_url or both.")); converse.bosh_service_url = url; converse.connection = connection; - }); + })); describe("with prebind", function () { - it("needs a jid when also using keepalive", function () { + it("needs a jid when also using keepalive", mock.initConverse(function (converse) { var authentication = converse.authentication; var jid = converse.jid; delete converse.jid; @@ -38,9 +42,9 @@ converse.authentication= authentication; converse.jid = jid; converse.keepalive = false; - }); + })); - it("needs jid, rid and sid values when not using keepalive", function () { + it("needs jid, rid and sid values when not using keepalive", mock.initConverse(function (converse) { var authentication = converse.authentication; var jid = converse.jid; delete converse.jid; @@ -50,13 +54,13 @@ converse.authentication= authentication; converse.bosh_service_url = undefined; converse.jid = jid; - }); + })); }); }); describe("A chat state indication", function () { - it("are sent out when the client becomes or stops being idle", function () { + it("are sent out when the client becomes or stops being idle", mock.initConverse(function (converse) { spyOn(converse, 'sendCSI').andCallThrough(); var sent_stanza; spyOn(converse.connection, 'send').andCallFake(function (stanza) { @@ -85,12 +89,12 @@ // Reset values converse.csi_waiting_time = 0; converse.features['urn:xmpp:csi:0'] = false; - }); + })); }); describe("Automatic status change", function () { - it("happens when the client is idle for long enough", function () { + it("happens when the client is idle for long enough", mock.initConverse(function (converse) { var i = 0; // Usually initialized by registerIntervalHandler converse.idle_seconds = 0; @@ -124,26 +128,21 @@ converse.auto_away = 0; converse.auto_xa = 0; converse.auto_changed_status = false; - }); + })); }); describe("The \"user\" grouping", function () { describe("The \"status\" API", function () { - beforeEach(function () { - test_utils.closeAllChatBoxes(); - test_utils.clearBrowserStorage(); - converse.rosterview.model.reset(); - }); - it("has a method for getting the user's availability", function () { + it("has a method for getting the user's availability", mock.initConverse(function (converse) { converse.xmppstatus.set('status', 'online'); expect(converse_api.user.status.get()).toBe('online'); converse.xmppstatus.set('status', 'dnd'); expect(converse_api.user.status.get()).toBe('dnd'); - }); + })); - it("has a method for setting the user's availability", function () { + it("has a method for setting the user's availability", mock.initConverse(function (converse) { converse_api.user.status.set('away'); expect(converse.xmppstatus.get('status')).toBe('away'); converse_api.user.status.set('dnd'); @@ -155,38 +154,33 @@ expect(_.partial(converse_api.user.status.set, 'invalid')).toThrow( new Error('Invalid availability value. See https://xmpp.org/rfcs/rfc3921.html#rfc.section.2.2.2.1') ); - }); + })); - it("allows setting the status message as well", function () { + it("allows setting the status message as well", mock.initConverse(function (converse) { converse_api.user.status.set('away', "I'm in a meeting"); expect(converse.xmppstatus.get('status')).toBe('away'); expect(converse.xmppstatus.get('status_message')).toBe("I'm in a meeting"); - }); + })); - it("has a method for getting the user's status message", function () { + it("has a method for getting the user's status message", mock.initConverse(function (converse) { converse.xmppstatus.set('status_message', undefined); expect(converse_api.user.status.message.get()).toBe(undefined); converse.xmppstatus.set('status_message', "I'm in a meeting"); expect(converse_api.user.status.message.get()).toBe("I'm in a meeting"); - }); + })); - it("has a method for setting the user's status message", function () { + it("has a method for setting the user's status message", mock.initConverse(function (converse) { converse.xmppstatus.set('status_message', undefined); converse_api.user.status.message.set("I'm in a meeting"); expect(converse.xmppstatus.get('status_message')).toBe("I'm in a meeting"); - }); + })); }); }); - describe("The \"tokens\" API", $.proxy(function () { - beforeEach(function () { - test_utils.closeAllChatBoxes(); - test_utils.clearBrowserStorage(); - converse.rosterview.model.reset(); - test_utils.createContacts('current'); - }); + describe("The \"tokens\" API", function () { - it("has a method for retrieving the next RID", $.proxy(function () { + it("has a method for retrieving the next RID", mock.initConverse(function (converse) { + test_utils.createContacts(converse, 'current'); var old_connection = converse.connection; converse.connection._proto.rid = '1234'; converse.expose_rid_and_sid = false; @@ -197,9 +191,10 @@ expect(converse_api.tokens.get('rid')).toBe(null); // Restore the connection converse.connection = old_connection; - }, converse)); + })); - it("has a method for retrieving the SID", $.proxy(function () { + it("has a method for retrieving the SID", mock.initConverse(function (converse) { + test_utils.createContacts(converse, 'current'); var old_connection = converse.connection; converse.connection._proto.sid = '1234'; converse.expose_rid_and_sid = false; @@ -210,19 +205,14 @@ expect(converse_api.tokens.get('sid')).toBe(null); // Restore the connection converse.connection = old_connection; - }, converse)); - }, converse)); + })); + }); - describe("The \"contacts\" API", $.proxy(function () { - beforeEach($.proxy(function () { - test_utils.closeAllChatBoxes(); - test_utils.clearBrowserStorage(); - converse.rosterview.model.reset(); - test_utils.createContacts('current'); - }, converse)); + describe("The \"contacts\" API", function () { - it("has a method 'get' which returns wrapped contacts", $.proxy(function () { + it("has a method 'get' which returns wrapped contacts", mock.initConverse(function (converse) { // Check that it returns nothing if a non-existing JID is given + test_utils.createContacts(converse, 'current'); expect(converse_api.contacts.get('non-existing@jabber.org')).toBeFalsy(); // Check when a single jid is given var jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; @@ -239,28 +229,23 @@ // Check that all JIDs are returned if you call without any parameters list = converse_api.contacts.get(); expect(list.length).toBe(mock.cur_names.length); - }, converse)); + })); - it("has a method 'add' with which contacts can be added", $.proxy(function () { + it("has a method 'add' with which contacts can be added", mock.initConverse(function (converse) { + test_utils.createContacts(converse, 'current'); var error = new TypeError('contacts.add: invalid jid'); expect(converse_api.contacts.add).toThrow(error); expect(converse_api.contacts.add.bind(converse_api, "invalid jid")).toThrow(error); spyOn(converse.roster, 'addAndSubscribe'); converse_api.contacts.add("newcontact@example.org"); expect(converse.roster.addAndSubscribe).toHaveBeenCalled(); - }, converse)); + })); + }); - }, converse)); + describe("The \"chats\" API", function() { - describe("The \"chats\" API", $.proxy(function() { - beforeEach($.proxy(function () { - test_utils.closeAllChatBoxes(); - test_utils.clearBrowserStorage(); - converse.rosterview.model.reset(); - test_utils.createContacts('current'); - }, converse)); - - it("has a method 'get' which returns a wrapped chat box", function () { + it("has a method 'get' which returns a wrapped chat box", mock.initConverse(function (converse) { + test_utils.createContacts(converse, 'current'); // Test on chat that doesn't exist. expect(converse_api.chats.get('non-existing@jabber.org')).toBeFalsy(); var jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; @@ -271,7 +256,7 @@ var chatboxview = converse.chatboxviews.get(jid); // Test for single JID - test_utils.openChatBoxFor(jid); + test_utils.openChatBoxFor(converse, jid); box = converse_api.chats.get(jid); expect(box instanceof Object).toBeTruthy(); expect(box.get('box_id')).toBe(b64_sha1(jid)); @@ -279,14 +264,15 @@ expect(chatboxview.$el.is(':visible')).toBeTruthy(); // Test for multiple JIDs var jid2 = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost'; - test_utils.openChatBoxFor(jid2); + test_utils.openChatBoxFor(converse, jid2); var list = converse_api.chats.get([jid, jid2]); expect(Array.isArray(list)).toBeTruthy(); expect(list[0].get('box_id')).toBe(b64_sha1(jid)); expect(list[1].get('box_id')).toBe(b64_sha1(jid2)); - }); + })); - it("has a method 'open' which opens and returns a wrapped chat box", function () { + it("has a method 'open' which opens and returns a wrapped chat box", mock.initConverse(function (converse) { + test_utils.createContacts(converse, 'current'); var jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; var chatboxview; waits('300'); // ChatBox.show() is debounced for 250ms @@ -309,18 +295,11 @@ expect(list[0].get('box_id')).toBe(b64_sha1(jid)); expect(list[1].get('box_id')).toBe(b64_sha1(jid2)); }); - }); - }, converse)); + })); + }); - describe("The \"settings\" API", $.proxy(function() { - beforeEach($.proxy(function () { - test_utils.closeAllChatBoxes(); - test_utils.clearBrowserStorage(); - converse.rosterview.model.reset(); - test_utils.createContacts('current'); - }, converse)); - - it("has methods 'get' and 'set' to set configuration settings", $.proxy(function () { + describe("The \"settings\" API", function() { + it("has methods 'get' and 'set' to set configuration settings", mock.initConverse(function (converse) { expect(Object.keys(converse_api.settings)).toEqual(["get", "set"]); expect(converse_api.settings.get("play_sounds")).toBe(false); converse_api.settings.set("play_sounds", true); @@ -331,7 +310,7 @@ expect(typeof converse_api.settings.get("non_existing")).toBe("undefined"); converse_api.settings.set("non_existing", true); expect(typeof converse_api.settings.get("non_existing")).toBe("undefined"); - }, converse)); - }, converse)); - }, converse, mock, test_utils)); + })); + }); + }); })); diff --git a/spec/protocol.js b/spec/protocol.js index 6313dbbd0..ccb63641d 100644 --- a/spec/protocol.js +++ b/spec/protocol.js @@ -1,4 +1,3 @@ -/*global converse */ (function (root, factory) { define([ "jquery", @@ -16,14 +15,17 @@ // See: // https://xmpp.org/rfcs/rfc3921.html - describe("The Protocol", $.proxy(function (mock, test_utils) { - beforeEach(function () { - test_utils.removeControlBox(); - converse.roster.browserStorage._clear(); - test_utils.initConverse(); - }); + describe("The Protocol", function () { + + describe("Integration of Roster Items and Presence Subscriptions", function () { + // Stub the trimChat method. It causes havoc when running with + // phantomJS. + + afterEach(function () { + converse_api.user.logout(); + test_utils.clearBrowserStorage(); + }); - describe("Integration of Roster Items and Presence Subscriptions", $.proxy(function (mock, test_utils) { /* Some level of integration between roster items and presence * subscriptions is normally expected by an instant messaging user * regarding the user's subscriptions to and from other contacts. This @@ -52,26 +54,24 @@ * that session. A client MUST acknowledge each roster push with an IQ * stanza of type "result". */ - beforeEach(function () { - test_utils.closeAllChatBoxes(); - test_utils.openControlBox(); - test_utils.openContactsPanel(); - }); - - it("Subscribe to contact, contact accepts and subscribes back", $.proxy(function () { + it("Subscribe to contact, contact accepts and subscribes back", mock.initConverse(function (converse) { /* The process by which a user subscribes to a contact, including * the interaction between roster items and subscription states. */ var contact, stanza, sent_stanza, IQ_id; - runs($.proxy(function () { - var panel = this.chatboxviews.get('controlbox').contactspanel; + runs(function () { + test_utils.openControlBox(converse); + }); + waits(100); + runs(function () { + var panel = converse.chatboxviews.get('controlbox').contactspanel; spyOn(panel, "addContactFromForm").andCallThrough(); - spyOn(this.roster, "addAndSubscribe").andCallThrough(); - spyOn(this.roster, "addContact").andCallThrough(); - spyOn(this.roster, "sendContactAddIQ").andCallThrough(); - spyOn(this, "getVCard").andCallThrough(); - var sendIQ = this.connection.sendIQ; - spyOn(this.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { + spyOn(converse.roster, "addAndSubscribe").andCallThrough(); + spyOn(converse.roster, "addContact").andCallThrough(); + spyOn(converse.roster, "sendContactAddIQ").andCallThrough(); + spyOn(converse, "getVCard").andCallThrough(); + var sendIQ = converse.connection.sendIQ; + spyOn(converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { sent_stanza = iq; IQ_id = sendIQ.bind(this)(iq, callback, errback); }); @@ -99,7 +99,7 @@ // The form should not be visible anymore. expect($form.is(":visible")).toBeFalsy(); - /* This request consists of sending an IQ + /* converse request consists of sending an IQ * stanza of type='set' containing a element qualified by * the 'jabber:iq:roster' namespace, which in turn contains an * element that defines the new roster item; the @@ -127,7 +127,7 @@ ); /* As a result, the user's server (1) MUST initiate a roster push * for the new roster item to all available resources associated - * with this user that have requested the roster, setting the + * with converse user that have requested the roster, setting the * 'subscription' attribute to a value of "none"; and (2) MUST * reply to the sending resource with an IQ result indicating the * success of the roster set: @@ -157,17 +157,17 @@ 'jid': 'contact@example.org', 'subscription': 'none', 'name': 'contact@example.org'}); - this.connection._dataRecv(test_utils.createRequest(stanza)); + converse.connection._dataRecv(test_utils.createRequest(stanza)); /* * */ stanza = $iq({'type': 'result', 'id':IQ_id}); - this.connection._dataRecv(test_utils.createRequest(stanza)); + converse.connection._dataRecv(test_utils.createRequest(stanza)); // A contact should now have been created - expect(this.roster.get('contact@example.org') instanceof this.RosterContact).toBeTruthy(); + expect(converse.roster.get('contact@example.org') instanceof converse.RosterContact).toBeTruthy(); expect(contact.get('jid')).toBe('contact@example.org'); - expect(this.getVCard).toHaveBeenCalled(); + expect(converse.getVCard).toHaveBeenCalled(); /* To subscribe to the contact's presence information, * the user's client MUST send a presence stanza of @@ -184,7 +184,7 @@ /* As a result, the user's server MUST initiate a second roster * push to all of the user's available resources that have * requested the roster, setting the contact to the pending - * sub-state of the 'none' subscription state; this pending + * sub-state of the 'none' subscription state; converse pending * sub-state is denoted by the inclusion of the ask='subscribe' * attribute in the roster item: * @@ -208,11 +208,11 @@ 'subscription': 'none', 'ask': 'subscribe', 'name': 'contact@example.org'}); - this.connection._dataRecv(test_utils.createRequest(stanza)); + converse.connection._dataRecv(test_utils.createRequest(stanza)); expect(converse.roster.updateContact).toHaveBeenCalled(); - }, this)); + }); waits(50); - runs($.proxy(function () { + runs(function () { // Check that the user is now properly shown as a pending // contact in the roster. var $header = $('a:contains("Pending contacts")'); @@ -223,46 +223,46 @@ spyOn(contact, "ackSubscribe").andCallThrough(); /* Here we assume the "happy path" that the contact - * approves the subscription request - * - * - */ + * approves the subscription request + * + * + */ stanza = $pres({ 'to': converse.bare_jid, 'from': 'contact@example.org', 'type': 'subscribed' }); sent_stanza = ""; // Reset - this.connection._dataRecv(test_utils.createRequest(stanza)); + converse.connection._dataRecv(test_utils.createRequest(stanza)); /* Upon receiving the presence stanza of type "subscribed", - * the user SHOULD acknowledge receipt of that - * subscription state notification by sending a presence - * stanza of type "subscribe". - */ + * the user SHOULD acknowledge receipt of that + * subscription state notification by sending a presence + * stanza of type "subscribe". + */ expect(contact.ackSubscribe).toHaveBeenCalled(); expect(sent_stanza.toLocaleString()).toBe( // Strophe adds the xmlns attr (although not in spec) "" ); /* The user's server MUST initiate a roster push to all of the user's - * available resources that have requested the roster, - * containing an updated roster item for the contact with - * the 'subscription' attribute set to a value of "to"; - * - * - * - * - * MyBuddies - * - * - * - */ + * available resources that have requested the roster, + * containing an updated roster item for the contact with + * the 'subscription' attribute set to a value of "to"; + * + * + * + * + * MyBuddies + * + * + * + */ IQ_id = converse.connection.getUniqueId('roster'); stanza = $iq({'type': 'set', 'id': IQ_id}) .c('query', {'xmlns': 'jabber:iq:roster'}) @@ -270,7 +270,7 @@ 'jid': 'contact@example.org', 'subscription': 'to', 'name': 'contact@example.org'}); - this.connection._dataRecv(test_utils.createRequest(stanza)); + converse.connection._dataRecv(test_utils.createRequest(stanza)); // Check that the IQ set was acknowledged. expect(sent_stanza.toLocaleString()).toBe( // Strophe adds the xmlns attr (although not in spec) "" @@ -292,78 +292,82 @@ expect(contact.get('chat_status')).toBe('offline'); /* - */ + * from='contact@example.org/resource' + * to='user@example.com/resource'/> + */ stanza = $pres({'to': converse.bare_jid, 'from': 'contact@example.org/resource'}); - this.connection._dataRecv(test_utils.createRequest(stanza)); + converse.connection._dataRecv(test_utils.createRequest(stanza)); // Now the contact should also be online. expect(contact.get('chat_status')).toBe('online'); /* Section 8.3. Creating a Mutual Subscription - * - * If the contact wants to create a mutual subscription, - * the contact MUST send a subscription request to the - * user. - * - * - */ + * + * If the contact wants to create a mutual subscription, + * the contact MUST send a subscription request to the + * user. + * + * + */ spyOn(contact, 'authorize').andCallThrough(); - spyOn(this.roster, 'handleIncomingSubscription').andCallThrough(); + spyOn(converse.roster, 'handleIncomingSubscription').andCallThrough(); stanza = $pres({ 'to': converse.bare_jid, 'from': 'contact@example.org/resource', 'type': 'subscribe'}); - this.connection._dataRecv(test_utils.createRequest(stanza)); - expect(this.roster.handleIncomingSubscription).toHaveBeenCalled(); + converse.connection._dataRecv(test_utils.createRequest(stanza)); + expect(converse.roster.handleIncomingSubscription).toHaveBeenCalled(); /* The user's client MUST send a presence stanza of type - * "subscribed" to the contact in order to approve the - * subscription request. - * - * - */ + * "subscribed" to the contact in order to approve the + * subscription request. + * + * + */ expect(contact.authorize).toHaveBeenCalled(); expect(sent_stanza.toLocaleString()).toBe( "" ); /* As a result, the user's server MUST initiate a - * roster push containing a roster item for the - * contact with the 'subscription' attribute set to - * a value of "both". - * - * - * - * - * MyBuddies - * - * - * - */ + * roster push containing a roster item for the + * contact with the 'subscription' attribute set to + * a value of "both". + * + * + * + * + * MyBuddies + * + * + * + */ stanza = $iq({'type': 'set'}).c('query', {'xmlns': 'jabber:iq:roster'}) .c('item', { 'jid': 'contact@example.org', 'subscription': 'both', 'name': 'contact@example.org'}); - this.connection._dataRecv(test_utils.createRequest(stanza)); + converse.connection._dataRecv(test_utils.createRequest(stanza)); expect(converse.roster.updateContact).toHaveBeenCalled(); // The class on the contact will now have switched. expect($contacts.hasClass('to')).toBeFalsy(); expect($contacts.hasClass('both')).toBeTruthy(); - }, this)); - }, converse)); + }); + })); - it("Alternate Flow: Contact Declines Subscription Request", $.proxy(function () { + it("Alternate Flow: Contact Declines Subscription Request", mock.initConverse(function (converse) { /* The process by which a user subscribes to a contact, including * the interaction between roster items and subscription states. */ var contact, stanza, sent_stanza, sent_IQ; - runs($.proxy(function () { + runs(function () { + test_utils.openControlBox(converse); + }); + waits(100); + runs(function () { // Add a new roster contact via roster push stanza = $iq({'type': 'set'}).c('query', {'xmlns': 'jabber:iq:roster'}) .c('item', { @@ -371,69 +375,69 @@ 'subscription': 'none', 'ask': 'subscribe', 'name': 'contact@example.org'}); - this.connection._dataRecv(test_utils.createRequest(stanza)); - }, this)); + converse.connection._dataRecv(test_utils.createRequest(stanza)); + }); waits(50); - runs($.proxy(function () { + runs(function () { // A pending contact should now exist. - contact = this.roster.get('contact@example.org'); - expect(this.roster.get('contact@example.org') instanceof this.RosterContact).toBeTruthy(); + contact = converse.roster.get('contact@example.org'); + expect(converse.roster.get('contact@example.org') instanceof converse.RosterContact).toBeTruthy(); spyOn(contact, "ackUnsubscribe").andCallThrough(); spyOn(converse.connection, 'send').andCallFake(function (stanza) { sent_stanza = stanza; }); - spyOn(this.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { + spyOn(converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { sent_IQ = iq; }); /* We now assume the contact declines the subscription - * requests. - * + * requests. + * /* Upon receiving the presence stanza of type "unsubscribed" - * addressed to the user, the user's server (1) MUST deliver - * that presence stanza to the user and (2) MUST initiate a - * roster push to all of the user's available resources that - * have requested the roster, containing an updated roster - * item for the contact with the 'subscription' attribute - * set to a value of "none" and with no 'ask' attribute: - * - * - * - * - * - * - * MyBuddies - * - * - * - */ + * addressed to the user, the user's server (1) MUST deliver + * that presence stanza to the user and (2) MUST initiate a + * roster push to all of the user's available resources that + * have requested the roster, containing an updated roster + * item for the contact with the 'subscription' attribute + * set to a value of "none" and with no 'ask' attribute: + * + * + * + * + * + * + * MyBuddies + * + * + * + */ // FIXME: also add the stanza = $pres({ 'to': converse.bare_jid, 'from': 'contact@example.org', 'type': 'unsubscribed' }); - this.connection._dataRecv(test_utils.createRequest(stanza)); + converse.connection._dataRecv(test_utils.createRequest(stanza)); /* Upon receiving the presence stanza of type "unsubscribed", - * the user SHOULD acknowledge receipt of that subscription - * state notification through either "affirming" it by - * sending a presence stanza of type "unsubscribe - */ + * the user SHOULD acknowledge receipt of that subscription + * state notification through either "affirming" it by + * sending a presence stanza of type "unsubscribe + */ expect(contact.ackUnsubscribe).toHaveBeenCalled(); expect(sent_stanza.toLocaleString()).toBe( "" ); /* Converse.js will then also automatically remove the - * contact from the user's roster. - */ + * contact from the user's roster. + */ expect(sent_IQ.toLocaleString()).toBe( ""+ ""+ @@ -441,22 +445,23 @@ ""+ "" ); - }, this)); - }, converse)); + }); + })); - it("Unsubscribe to a contact when subscription is mutual", function () { + it("Unsubscribe to a contact when subscription is mutual", mock.initConverse(function (converse) { var sent_IQ, IQ_id, jid = 'annegreet.gomez@localhost'; runs(function () { - test_utils.createContacts('current'); + test_utils.openControlBox(converse); + test_utils.createContacts(converse, 'current'); }); waits(50); runs(function () { spyOn(window, 'confirm').andReturn(true); // We now have a contact we want to remove - expect(this.roster.get(jid) instanceof this.RosterContact).toBeTruthy(); + expect(converse.roster.get(jid) instanceof converse.RosterContact).toBeTruthy(); - var sendIQ = this.connection.sendIQ; - spyOn(this.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { + 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); }); @@ -467,24 +472,24 @@ expect(window.confirm).toHaveBeenCalled(); /* Section 8.6 Removing a Roster Item and Cancelling All - * Subscriptions - * - * First the user is removed from the roster - * Because there may be many steps involved in completely - * removing a roster item and cancelling subscriptions in - * both directions, the roster management protocol includes - * a "shortcut" method for doing so. The process may be - * initiated no matter what the current subscription state - * is by sending a roster set containing an item for the - * contact with the 'subscription' attribute set to a value - * of "remove": - * - * - * - * - * - * - */ + * Subscriptions + * + * First the user is removed from the roster + * Because there may be many steps involved in completely + * removing a roster item and cancelling subscriptions in + * both directions, the roster management protocol includes + * a "shortcut" method for doing so. The process may be + * initiated no matter what the current subscription state + * is by sending a roster set containing an item for the + * contact with the 'subscription' attribute set to a value + * of "remove": + * + * + * + * + * + * + */ expect(sent_IQ.toLocaleString()).toBe( ""+ ""+ @@ -495,21 +500,21 @@ // Receive confirmation from the contact's server // var stanza = $iq({'type': 'result', 'id':IQ_id}); - this.connection._dataRecv(test_utils.createRequest(stanza)); + converse.connection._dataRecv(test_utils.createRequest(stanza)); // Our contact has now been removed - expect(typeof this.roster.get(jid) === "undefined").toBeTruthy(); - }.bind(converse)); - }.bind(converse)); + expect(typeof converse.roster.get(jid) === "undefined").toBeTruthy(); + }); + })); - it("Receiving a subscription request", function () { + it("Receiving a subscription request", mock.initConverse(function (converse) { runs(function () { - test_utils.createContacts('current'); // Create some contacts so that we can test positioning + test_utils.openControlBox(converse); + test_utils.createContacts(converse, 'current'); // Create some contacts so that we can test positioning }); waits(50); runs(function () { spyOn(converse, "emit"); - /* - * @@ -521,15 +526,15 @@ }).c('nick', { 'xmlns': Strophe.NS.NICK, }).t('Clint Contact'); - this.connection._dataRecv(test_utils.createRequest(stanza)); + converse.connection._dataRecv(test_utils.createRequest(stanza)); expect(converse.emit).toHaveBeenCalledWith('contactRequest', jasmine.any(Object)); var $header = $('a:contains("Contact requests")'); expect($header.length).toBe(1); expect($header.is(":visible")).toBeTruthy(); var $contacts = $header.parent().nextUntil('dt', 'dd'); expect($contacts.length).toBe(1); - }.bind(converse)); - }.bind(converse)); - }, converse, mock, test_utils)); - }, converse, mock, test_utils)); + }); + })); + }); + }); })); diff --git a/src/converse-core.js b/src/converse-core.js index c72aa02c4..2c284c0d2 100755 --- a/src/converse-core.js +++ b/src/converse-core.js @@ -1950,6 +1950,15 @@ utils.merge(converse, settings); utils.applyUserSettings(converse, settings, converse.user_settings); }; + + // If initialize gets called a second time (e.g. during tests), then we + // need to re-apply all plugins (for a new converse instance), and we + // therefore need to clear this array that prevents plugins from being + // initialized twice. + // If initialize is called for the first time, then this array is empty + // in any case. + converse.pluggable.initialized_plugins = []; + converse.pluggable.initializePlugins({ 'updateSettings': updateSettings, 'converse': converse diff --git a/tests/main.js b/tests/main.js index f21583c4a..6e0b32a9e 100644 --- a/tests/main.js +++ b/tests/main.js @@ -45,71 +45,49 @@ require([ window.localStorage.clear(); window.sessionStorage.clear(); - converse.initialize({ - i18n: window.locales.en, - auto_subscribe: false, - bosh_service_url: 'localhost', - connection: mock.mock_connection, - animate: false, - no_trimming: true, - auto_login: true, - jid: 'dummy@localhost', - password: 'secret', - debug: true - }).then(function (converse) { - window.converse = converse; - window.crypto = { - getRandomValues: function (buf) { - var i; - for (i=0, len=buf.length; i-1; i--) { chatbox = converse.chatboxes.models[i]; @@ -78,7 +73,7 @@ $('#controlbox').remove(); }; - utils.openContactsPanel = function () { + utils.openContactsPanel = function (converse) { var cbview = converse.chatboxviews.get('controlbox'); var $tabs = cbview.$el.find('#controlbox-tabs'); $tabs.find('li').first().find('a').click(); @@ -100,7 +95,7 @@ return views; }; - utils.openChatBoxFor = function (jid) { + utils.openChatBoxFor = function (converse, jid) { return converse.roster.get(jid).trigger("open"); }; @@ -172,7 +167,7 @@ view.model.messages.browserStorage._clear(); }; - utils.createContacts = function (type, length) { + utils.createContacts = function (converse, type, length) { /* Create current (as opposed to requesting or pending) contacts * for the user's roster. *