Browse Source

Turn caps plugin into folder.

Move more test files to plugins
JC Brand 4 years ago
parent
commit
1fc44b9d8e

+ 1 - 0
dev.html

@@ -38,6 +38,7 @@
         theme: 'concord',
         theme: 'concord',
         view_mode: 'fullscreen',
         view_mode: 'fullscreen',
         websocket_url: 'wss://conversejs.org/xmpp-websocket',
         websocket_url: 'wss://conversejs.org/xmpp-websocket',
+        // websocket_url: 'ws://chat.example.org:5380/xmpp-websocket',
         whitelisted_plugins: ['converse-debug'],
         whitelisted_plugins: ['converse-debug'],
     });
     });
 </script>
 </script>

+ 9 - 7
karma.conf.js

@@ -25,26 +25,24 @@ module.exports = function(config) {
       { pattern: "node_modules/sinon/pkg/sinon.js", type: 'module' },
       { pattern: "node_modules/sinon/pkg/sinon.js", type: 'module' },
       { pattern: "spec/mock.js", type: 'module' },
       { pattern: "spec/mock.js", type: 'module' },
 
 
-      { pattern: "spec/converse.js", type: 'module' },
-      { pattern: "spec/corrections.js", type: 'module' },
       { pattern: "spec/emojis.js", type: 'module' },
       { pattern: "spec/emojis.js", type: 'module' },
-      { pattern: "spec/eventemitter.js", type: 'module' },
       { pattern: "spec/http-file-upload.js", type: 'module' },
       { pattern: "spec/http-file-upload.js", type: 'module' },
       { pattern: "spec/markers.js", type: 'module' },
       { pattern: "spec/markers.js", type: 'module' },
-      { pattern: "spec/presence.js", type: 'module' },
       { pattern: "spec/protocol.js", type: 'module' },
       { pattern: "spec/protocol.js", type: 'module' },
       { pattern: "spec/push.js", type: 'module' },
       { pattern: "spec/push.js", type: 'module' },
       { pattern: "spec/retractions.js", type: 'module' },
       { pattern: "spec/retractions.js", type: 'module' },
-      { pattern: "spec/styling.js", type: 'module' },
-      { pattern: "spec/unfurls.js", type: 'module' },
       { pattern: "spec/user-details-modal.js", type: 'module' },
       { pattern: "spec/user-details-modal.js", type: 'module' },
       { pattern: "spec/utils.js", type: 'module' },
       { pattern: "spec/utils.js", type: 'module' },
       { pattern: "spec/xmppstatus.js", type: 'module' },
       { pattern: "spec/xmppstatus.js", type: 'module' },
+      { pattern: "src/headless/plugins/caps/tests/caps.js", type: 'module' },
       { pattern: "src/headless/plugins/chat/tests/api.js", type: 'module' },
       { pattern: "src/headless/plugins/chat/tests/api.js", type: 'module' },
       { pattern: "src/headless/plugins/disco/tests/disco.js", type: 'module' },
       { pattern: "src/headless/plugins/disco/tests/disco.js", type: 'module' },
       { pattern: "src/headless/plugins/muc/tests/affiliations.js", type: 'module' },
       { pattern: "src/headless/plugins/muc/tests/affiliations.js", type: 'module' },
       { pattern: "src/headless/plugins/ping/tests/ping.js", type: 'module' },
       { pattern: "src/headless/plugins/ping/tests/ping.js", type: 'module' },
+      { pattern: "src/headless/plugins/roster/tests/presence.js", type: 'module' },
       { pattern: "src/headless/plugins/smacks/tests/smacks.js", type: 'module' },
       { pattern: "src/headless/plugins/smacks/tests/smacks.js", type: 'module' },
+      { pattern: "src/headless/tests/converse.js", type: 'module' },
+      { pattern: "src/headless/tests/eventemitter.js", type: 'module' },
       { pattern: "src/plugins/bookmark-views/tests/bookmarks.js", type: 'module' },
       { pattern: "src/plugins/bookmark-views/tests/bookmarks.js", type: 'module' },
       { pattern: "src/plugins/chatview/tests/chatbox.js", type: 'module' },
       { pattern: "src/plugins/chatview/tests/chatbox.js", type: 'module' },
       { pattern: "src/plugins/chatview/tests/corrections.js", type: 'module' },
       { pattern: "src/plugins/chatview/tests/corrections.js", type: 'module' },
@@ -73,11 +71,15 @@ module.exports = function(config) {
       { pattern: "src/plugins/muc-views/tests/muclist.js", type: 'module' },
       { pattern: "src/plugins/muc-views/tests/muclist.js", type: 'module' },
       { pattern: "src/plugins/muc-views/tests/rai.js", type: 'module' },
       { pattern: "src/plugins/muc-views/tests/rai.js", type: 'module' },
       { pattern: "src/plugins/muc-views/tests/styling.js", type: 'module' },
       { pattern: "src/plugins/muc-views/tests/styling.js", type: 'module' },
+      { pattern: "src/plugins/muc-views/tests/unfurls.js", type: 'module' },
       { pattern: "src/plugins/muc-views/tests/xss.js", type: 'module' },
       { pattern: "src/plugins/muc-views/tests/xss.js", type: 'module' },
       { pattern: "src/plugins/notifications/tests/notification.js", type: 'module' },
       { pattern: "src/plugins/notifications/tests/notification.js", type: 'module' },
       { pattern: "src/plugins/omemo/tests/omemo.js", type: 'module' },
       { pattern: "src/plugins/omemo/tests/omemo.js", type: 'module' },
       { pattern: "src/plugins/register/tests/register.js", type: 'module' },
       { pattern: "src/plugins/register/tests/register.js", type: 'module' },
-      { pattern: "src/plugins/rosterview/tests/roster.js", type: 'module' }
+      { pattern: "src/plugins/rootview/tests/root.js", type: 'module' },
+      { pattern: "src/plugins/rosterview/tests/presence.js", type: 'module' },
+      { pattern: "src/plugins/rosterview/tests/roster.js", type: 'module' },
+      { pattern: "src/shared/chat/tests/styling.js", type: 'module' },
     ],
     ],
 
 
     proxies: {
     proxies: {

+ 3 - 2
src/headless/core.js

@@ -202,7 +202,7 @@ export const api = _converse.api = {
                 await _converse.setUserJID(api.settings.get("jid"));
                 await _converse.setUserJID(api.settings.get("jid"));
             }
             }
 
 
-            if (_converse.connection.reconnecting) {
+            if (_converse.connection?.reconnecting) {
                 _converse.connection.debouncedReconnect();
                 _converse.connection.debouncedReconnect();
             } else {
             } else {
                 return _converse.connection.reconnect();
                 return _converse.connection.reconnect();
@@ -987,6 +987,8 @@ async function initSession (jid) {
     const bare_jid = Strophe.getBareJidFromJid(jid).toLowerCase();
     const bare_jid = Strophe.getBareJidFromJid(jid).toLowerCase();
     const id = `converse.session-${bare_jid}`;
     const id = `converse.session-${bare_jid}`;
     if (_converse.session?.get('id') !== id) {
     if (_converse.session?.get('id') !== id) {
+        initPersistentStorage();
+
         _converse.session = new Model({ id });
         _converse.session = new Model({ id });
         initStorage(_converse.session, id, is_shared_session ? "persistent" : "session");
         initStorage(_converse.session, id, is_shared_session ? "persistent" : "session");
         await new Promise(r => _converse.session.fetch({'success': r, 'error': r}));
         await new Promise(r => _converse.session.fetch({'success': r, 'error': r}));
@@ -998,7 +1000,6 @@ async function initSession (jid) {
             _converse.session.save({id});
             _converse.session.save({id});
         }
         }
         saveJIDtoSession(jid);
         saveJIDtoSession(jid);
-        initPersistentStorage();
         /**
         /**
          * Triggered once the user's session has been initialized. The session is a
          * Triggered once the user's session has been initialized. The session is a
          * cache which stores information about the user's current session.
          * cache which stores information about the user's current session.

+ 1 - 1
src/headless/headless.js

@@ -5,7 +5,7 @@
 import "./plugins/adhoc.js";        // XEP-0050 Ad Hoc Commands
 import "./plugins/adhoc.js";        // XEP-0050 Ad Hoc Commands
 import "./plugins/bookmarks/index.js";   // XEP-0199 XMPP Ping
 import "./plugins/bookmarks/index.js";   // XEP-0199 XMPP Ping
 import "./plugins/bosh.js";         // XEP-0206 BOSH
 import "./plugins/bosh.js";         // XEP-0206 BOSH
-import "./plugins/caps.js";         // XEP-0115 Entity Capabilities
+import "./plugins/caps/index.js";         // XEP-0115 Entity Capabilities
 import "./plugins/carbons.js";      // XEP-0280 Message Carbons
 import "./plugins/carbons.js";      // XEP-0280 Message Carbons
 import "./plugins/chat/index.js";   // RFC-6121 Instant messaging
 import "./plugins/chat/index.js";   // RFC-6121 Instant messaging
 import "./plugins/chatboxes/index.js";
 import "./plugins/chatboxes/index.js";

+ 27 - 0
src/headless/plugins/caps/index.js

@@ -0,0 +1,27 @@
+/**
+ * @copyright 2020, the Converse.js contributors
+ * @license Mozilla Public License (MPLv2)
+ */
+import { _converse, converse } from '@converse/headless/core';
+import { createCapsNode } from './utils.js';
+
+const { Strophe } = converse.env;
+
+Strophe.addNamespace('CAPS', "http://jabber.org/protocol/caps");
+
+
+converse.plugins.add('converse-caps', {
+
+    overrides: {
+        // Overrides mentioned here will be picked up by converse.js's
+        // plugin architecture they will replace existing methods on the
+        // relevant objects or classes.
+        XMPPStatus: {
+            constructPresence () {
+                const presence = this.__super__.constructPresence.apply(this, arguments);
+                presence.root().cnode(createCapsNode(_converse)).up();
+                return presence;
+            }
+        }
+    }
+});

+ 66 - 0
src/headless/plugins/caps/tests/caps.js

@@ -0,0 +1,66 @@
+/*global mock */
+
+
+const original_timeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
+
+describe("A sent presence stanza", function () {
+
+    beforeEach(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = 7000));
+    afterEach(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = original_timeout));
+
+    it("includes a entity capabilities node",
+            mock.initConverse([], {}, async (done, _converse) => {
+
+        await mock.waitForRoster(_converse, 'current', 0);
+        _converse.api.disco.own.identities.clear();
+        _converse.api.disco.own.features.clear();
+
+        _converse.api.disco.own.identities.add("client", "pc", "Exodus 0.9.1");
+        _converse.api.disco.own.features.add("http://jabber.org/protocol/caps");
+        _converse.api.disco.own.features.add("http://jabber.org/protocol/disco#info");
+        _converse.api.disco.own.features.add("http://jabber.org/protocol/disco#items");
+        _converse.api.disco.own.features.add("http://jabber.org/protocol/muc");
+
+        const presence = _converse.xmppstatus.constructPresence();
+        expect(presence.toLocaleString()).toBe(
+            `<presence xmlns="jabber:client">`+
+                `<priority>0</priority>`+
+                `<c hash="sha-1" node="https://conversejs.org" ver="QgayPKawpkPSDYmwT/WM94uAlu0=" xmlns="http://jabber.org/protocol/caps"/>`+
+            `</presence>`)
+        done();
+    }));
+
+    it("has a given priority", mock.initConverse(['statusInitialized'], {}, (done, _converse) => {
+        const { api } = _converse;
+        let pres = _converse.xmppstatus.constructPresence('online', null, 'Hello world');
+        expect(pres.toLocaleString()).toBe(
+            `<presence xmlns="jabber:client">`+
+                `<status>Hello world</status>`+
+                `<priority>0</priority>`+
+                `<c hash="sha-1" node="https://conversejs.org" ver="PxXfr6uz8ClMWIga0OB/MhKNH/M=" xmlns="http://jabber.org/protocol/caps"/>`+
+            `</presence>`
+        );
+        api.settings.set('priority', 2);
+        pres = _converse.xmppstatus.constructPresence('away', null, 'Going jogging');
+        expect(pres.toLocaleString()).toBe(
+            `<presence xmlns="jabber:client">`+
+                `<show>away</show>`+
+                `<status>Going jogging</status>`+
+                `<priority>2</priority>`+
+                `<c hash="sha-1" node="https://conversejs.org" ver="PxXfr6uz8ClMWIga0OB/MhKNH/M=" xmlns="http://jabber.org/protocol/caps"/>`+
+            `</presence>`
+        );
+
+        api.settings.set('priority', undefined);
+        pres = _converse.xmppstatus.constructPresence('dnd', null, 'Doing taxes');
+        expect(pres.toLocaleString()).toBe(
+            `<presence xmlns="jabber:client">`+
+                `<show>dnd</show>`+
+                `<status>Doing taxes</status>`+
+                `<priority>0</priority>`+
+                `<c hash="sha-1" node="https://conversejs.org" ver="PxXfr6uz8ClMWIga0OB/MhKNH/M=" xmlns="http://jabber.org/protocol/caps"/>`+
+            `</presence>`
+        );
+        done();
+    }));
+});

+ 2 - 25
src/headless/plugins/caps.js → src/headless/plugins/caps/utils.js

@@ -1,15 +1,8 @@
-/**
- * @module converse-caps
- * @copyright 2020, the Converse.js contributors
- * @license Mozilla Public License (MPLv2)
- */
 import SHA1 from 'strophe.js/src/sha1';
 import SHA1 from 'strophe.js/src/sha1';
-import { converse } from "@converse/headless/core";
+import { converse } from '@converse/headless/core';
 
 
 const { Strophe, $build } = converse.env;
 const { Strophe, $build } = converse.env;
 
 
-Strophe.addNamespace('CAPS', "http://jabber.org/protocol/caps");
-
 function propertySort (array, property) {
 function propertySort (array, property) {
     return array.sort((a, b) => { return a[property] > b[property] ? -1 : 1 });
     return array.sort((a, b) => { return a[property] > b[property] ? -1 : 1 });
 }
 }
@@ -30,7 +23,7 @@ function generateVerificationString (_converse) {
     return SHA1.b64_sha1(S);
     return SHA1.b64_sha1(S);
 }
 }
 
 
-function createCapsNode (_converse) {
+export function createCapsNode (_converse) {
     return $build("c", {
     return $build("c", {
         'xmlns': Strophe.NS.CAPS,
         'xmlns': Strophe.NS.CAPS,
         'hash': "sha-1",
         'hash': "sha-1",
@@ -38,19 +31,3 @@ function createCapsNode (_converse) {
         'ver': generateVerificationString(_converse)
         'ver': generateVerificationString(_converse)
     }).nodeTree;
     }).nodeTree;
 }
 }
-
-converse.plugins.add('converse-caps', {
-
-    overrides: {
-        // Overrides mentioned here will be picked up by converse.js's
-        // plugin architecture they will replace existing methods on the
-        // relevant objects or classes.
-        XMPPStatus: {
-            constructPresence () {
-                const presence = this.__super__.constructPresence.apply(this, arguments);
-                presence.root().cnode(createCapsNode(this.__super__._converse)).up();
-                return presence;
-            }
-        }
-    }
-});

+ 0 - 109
spec/presence.js → src/headless/plugins/roster/tests/presence.js

@@ -2,115 +2,6 @@
 
 
 // See: https://xmpp.org/rfcs/rfc3921.html
 // See: https://xmpp.org/rfcs/rfc3921.html
 
 
-const original_timeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
-
-describe("A sent presence stanza", function () {
-
-    beforeEach(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = 7000));
-    afterEach(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = original_timeout));
-
-    it("includes a entity capabilities node",
-            mock.initConverse([], {}, async (done, _converse) => {
-
-        await mock.waitForRoster(_converse, 'current', 0);
-        _converse.api.disco.own.identities.clear();
-        _converse.api.disco.own.features.clear();
-
-        _converse.api.disco.own.identities.add("client", "pc", "Exodus 0.9.1");
-        _converse.api.disco.own.features.add("http://jabber.org/protocol/caps");
-        _converse.api.disco.own.features.add("http://jabber.org/protocol/disco#info");
-        _converse.api.disco.own.features.add("http://jabber.org/protocol/disco#items");
-        _converse.api.disco.own.features.add("http://jabber.org/protocol/muc");
-
-        const presence = _converse.xmppstatus.constructPresence();
-        expect(presence.toLocaleString()).toBe(
-            `<presence xmlns="jabber:client">`+
-                `<priority>0</priority>`+
-                `<c hash="sha-1" node="https://conversejs.org" ver="QgayPKawpkPSDYmwT/WM94uAlu0=" xmlns="http://jabber.org/protocol/caps"/>`+
-            `</presence>`)
-        done();
-    }));
-
-    it("has a given priority", mock.initConverse(['statusInitialized'], {}, (done, _converse) => {
-        const { api } = _converse;
-        let pres = _converse.xmppstatus.constructPresence('online', null, 'Hello world');
-        expect(pres.toLocaleString()).toBe(
-            `<presence xmlns="jabber:client">`+
-                `<status>Hello world</status>`+
-                `<priority>0</priority>`+
-                `<c hash="sha-1" node="https://conversejs.org" ver="PxXfr6uz8ClMWIga0OB/MhKNH/M=" xmlns="http://jabber.org/protocol/caps"/>`+
-            `</presence>`
-        );
-        api.settings.set('priority', 2);
-        pres = _converse.xmppstatus.constructPresence('away', null, 'Going jogging');
-        expect(pres.toLocaleString()).toBe(
-            `<presence xmlns="jabber:client">`+
-                `<show>away</show>`+
-                `<status>Going jogging</status>`+
-                `<priority>2</priority>`+
-                `<c hash="sha-1" node="https://conversejs.org" ver="PxXfr6uz8ClMWIga0OB/MhKNH/M=" xmlns="http://jabber.org/protocol/caps"/>`+
-            `</presence>`
-        );
-
-        api.settings.set('priority', undefined);
-        pres = _converse.xmppstatus.constructPresence('dnd', null, 'Doing taxes');
-        expect(pres.toLocaleString()).toBe(
-            `<presence xmlns="jabber:client">`+
-                `<show>dnd</show>`+
-                `<status>Doing taxes</status>`+
-                `<priority>0</priority>`+
-                `<c hash="sha-1" node="https://conversejs.org" ver="PxXfr6uz8ClMWIga0OB/MhKNH/M=" xmlns="http://jabber.org/protocol/caps"/>`+
-            `</presence>`
-        );
-        done();
-    }));
-
-    it("includes the saved status message",
-        mock.initConverse([], {}, async (done, _converse) => {
-
-        const { u, Strophe } = converse.env;
-        mock.openControlBox(_converse);
-        spyOn(_converse.connection, 'send').and.callThrough();
-
-        const cbview = _converse.chatboxviews.get('controlbox');
-        const change_status_el = await u.waitUntil(() => cbview.querySelector('.change-status'));
-        change_status_el.click()
-        let modal = _converse.api.modal.get('modal-status-change');
-        await u.waitUntil(() => u.isVisible(modal.el), 1000);
-        const msg = 'My custom status';
-        modal.el.querySelector('input[name="status_message"]').value = msg;
-        modal.el.querySelector('[type="submit"]').click();
-
-        const sent_stanzas = _converse.connection.sent_stanzas;
-        let sent_presence = await u.waitUntil(() => sent_stanzas.filter(s => Strophe.serialize(s).match('presence')).pop());
-        expect(Strophe.serialize(sent_presence))
-            .toBe(`<presence xmlns="jabber:client">`+
-                    `<status>My custom status</status>`+
-                    `<priority>0</priority>`+
-                    `<c hash="sha-1" node="https://conversejs.org" ver="PxXfr6uz8ClMWIga0OB/MhKNH/M=" xmlns="http://jabber.org/protocol/caps"/>`+
-                    `</presence>`)
-        await u.waitUntil(() => modal.el.getAttribute('aria-hidden') === "true");
-        await u.waitUntil(() => !u.isVisible(modal.el));
-
-        cbview.querySelector('.change-status').click()
-        modal = _converse.api.modal.get('modal-status-change');
-        await u.waitUntil(() => modal.el.getAttribute('aria-hidden') === "false", 1000);
-        modal.el.querySelector('label[for="radio-busy"]').click(); // Change status to "dnd"
-        modal.el.querySelector('[type="submit"]').click();
-        await u.waitUntil(() => sent_stanzas.filter(s => Strophe.serialize(s).match('presence')).length === 2);
-        sent_presence = sent_stanzas.filter(s => Strophe.serialize(s).match('presence')).pop();
-        expect(Strophe.serialize(sent_presence))
-            .toBe(
-                `<presence xmlns="jabber:client">`+
-                    `<show>dnd</show>`+
-                    `<status>My custom status</status>`+
-                    `<priority>0</priority>`+
-                    `<c hash="sha-1" node="https://conversejs.org" ver="PxXfr6uz8ClMWIga0OB/MhKNH/M=" xmlns="http://jabber.org/protocol/caps"/>`+
-                `</presence>`)
-        done();
-    }));
-});
-
 describe("A received presence stanza", function () {
 describe("A received presence stanza", function () {
 
 
     it("has its priority taken into account",
     it("has its priority taken into account",

+ 1 - 1
src/headless/shared/utils.js

@@ -16,7 +16,7 @@ export function createStore (id, store) {
     const name = store || getDefaultStore();
     const name = store || getDefaultStore();
     const s = _converse.storage[name];
     const s = _converse.storage[name];
     if (typeof s === 'undefined') {
     if (typeof s === 'undefined') {
-        throw new TypeError(`createStore: Could not find store for %{id}`);
+        throw new TypeError(`createStore: Could not find store for ${id}`);
     }
     }
     return new Storage(id, s, api.settings.get('persistent_store') === 'IndexedDB');
     return new Storage(id, s, api.settings.get('persistent_store') === 'IndexedDB');
 }
 }

+ 0 - 12
spec/converse.js → src/headless/tests/converse.js

@@ -1,19 +1,7 @@
 /* global mock, converse */
 /* global mock, converse */
 
 
-const u = converse.env.utils;
-
 describe("Converse", function() {
 describe("Converse", function() {
 
 
-    it("Can be inserted into a custom element after having been initialized",
-            mock.initConverse([], {'root': new DocumentFragment()}, async (done, _converse) => {
-
-        expect(document.body.querySelector('#conversejs')).toBe(null);
-        expect(_converse.root.firstElementChild.nodeName.toLowerCase()).toBe('converse-root');
-        document.body.appendChild(document.createElement('converse-root'));
-        await u.waitUntil(() => document.body.querySelector('#conversejs') !== null);
-        done();
-    }));
-
     describe("Authentication", function () {
     describe("Authentication", function () {
 
 
         it("needs either a bosh_service_url a websocket_url or both", mock.initConverse(async (done, _converse) => {
         it("needs either a bosh_service_url a websocket_url or both", mock.initConverse(async (done, _converse) => {

+ 0 - 0
spec/eventemitter.js → src/headless/tests/eventemitter.js


+ 0 - 0
spec/unfurls.js → src/plugins/muc-views/tests/unfurls.js


+ 16 - 0
src/plugins/rootview/tests/root.js

@@ -0,0 +1,16 @@
+/* global mock, converse */
+
+const u = converse.env.utils;
+
+describe("Converse", function() {
+
+    it("Can be inserted into a converse-root custom element after having been initialized",
+            mock.initConverse([], {'root': new DocumentFragment()}, async (done, _converse) => {
+
+        expect(document.body.querySelector('#conversejs')).toBe(null);
+        expect(_converse.root.firstElementChild.nodeName.toLowerCase()).toBe('converse-root');
+        document.body.appendChild(document.createElement('converse-root'));
+        await u.waitUntil(() => document.body.querySelector('#conversejs') !== null);
+        done();
+    }));
+});

+ 54 - 0
src/plugins/rosterview/tests/presence.js

@@ -0,0 +1,54 @@
+/*global mock, converse */
+
+const original_timeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
+
+describe("A sent presence stanza", function () {
+
+    beforeEach(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = 7000));
+    afterEach(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = original_timeout));
+
+    it("includes the saved status message",
+        mock.initConverse([], {}, async (done, _converse) => {
+
+        const { u, Strophe } = converse.env;
+        mock.openControlBox(_converse);
+        spyOn(_converse.connection, 'send').and.callThrough();
+
+        const cbview = _converse.chatboxviews.get('controlbox');
+        const change_status_el = await u.waitUntil(() => cbview.querySelector('.change-status'));
+        change_status_el.click()
+        let modal = _converse.api.modal.get('modal-status-change');
+        await u.waitUntil(() => u.isVisible(modal.el), 1000);
+        const msg = 'My custom status';
+        modal.el.querySelector('input[name="status_message"]').value = msg;
+        modal.el.querySelector('[type="submit"]').click();
+
+        const sent_stanzas = _converse.connection.sent_stanzas;
+        let sent_presence = await u.waitUntil(() => sent_stanzas.filter(s => Strophe.serialize(s).match('presence')).pop());
+        expect(Strophe.serialize(sent_presence))
+            .toBe(`<presence xmlns="jabber:client">`+
+                    `<status>My custom status</status>`+
+                    `<priority>0</priority>`+
+                    `<c hash="sha-1" node="https://conversejs.org" ver="PxXfr6uz8ClMWIga0OB/MhKNH/M=" xmlns="http://jabber.org/protocol/caps"/>`+
+                    `</presence>`)
+        await u.waitUntil(() => modal.el.getAttribute('aria-hidden') === "true");
+        await u.waitUntil(() => !u.isVisible(modal.el));
+
+        cbview.querySelector('.change-status').click()
+        modal = _converse.api.modal.get('modal-status-change');
+        await u.waitUntil(() => modal.el.getAttribute('aria-hidden') === "false", 1000);
+        modal.el.querySelector('label[for="radio-busy"]').click(); // Change status to "dnd"
+        modal.el.querySelector('[type="submit"]').click();
+        await u.waitUntil(() => sent_stanzas.filter(s => Strophe.serialize(s).match('presence')).length === 2);
+        sent_presence = sent_stanzas.filter(s => Strophe.serialize(s).match('presence')).pop();
+        expect(Strophe.serialize(sent_presence))
+            .toBe(
+                `<presence xmlns="jabber:client">`+
+                    `<show>dnd</show>`+
+                    `<status>My custom status</status>`+
+                    `<priority>0</priority>`+
+                    `<c hash="sha-1" node="https://conversejs.org" ver="PxXfr6uz8ClMWIga0OB/MhKNH/M=" xmlns="http://jabber.org/protocol/caps"/>`+
+                `</presence>`)
+        done();
+    }));
+});

+ 0 - 0
spec/styling.js → src/shared/chat/tests/styling.js


+ 1 - 1
webpack.html

@@ -30,7 +30,7 @@
             modtools_disable_assign: ['owner', 'moderator', 'participant', 'visitor'],
             modtools_disable_assign: ['owner', 'moderator', 'participant', 'visitor'],
             modtools_disable_query: ['moderator', 'participant', 'visitor'],
             modtools_disable_query: ['moderator', 'participant', 'visitor'],
             enable_smacks: true,
             enable_smacks: true,
-            // connection_options: { 'worker': '/dist/shared-connection-worker.js' },
+            connection_options: { 'worker': '/dist/shared-connection-worker.js' },
             persistent_store: 'IndexedDB',
             persistent_store: 'IndexedDB',
             message_archiving: 'always',
             message_archiving: 'always',
             muc_domain: 'conference.chat.example.org',
             muc_domain: 'conference.chat.example.org',