Selaa lähdekoodia

modtools: Better error reporting

JC Brand 5 vuotta sitten
vanhempi
commit
e2fbfa7470
2 muutettua tiedostoa jossa 100 lisäystä ja 45 poistoa
  1. 83 34
      spec/modtools.js
  2. 17 11
      src/modals/moderator-tools.js

+ 83 - 34
spec/modtools.js

@@ -7,6 +7,18 @@ const sizzle = converse.env.sizzle;
 const Strophe = converse.env.Strophe;
 const u = converse.env.utils;
 
+
+async function openModtools (view) {
+    const textarea = view.el.querySelector('.chat-textarea');
+    textarea.value = '/modtools';
+    const enter = { 'target': textarea, 'preventDefault': function preventDefault () {}, 'keyCode': 13 };
+    view.onKeyDown(enter);
+    await u.waitUntil(() => view.showModeratorToolsModal.calls.count());
+    const modal = view.modtools_modal;
+    await u.waitUntil(() => u.isVisible(modal.el), 1000);
+    return modal;
+}
+
 describe("The groupchat moderator tool", function () {
 
     it("allows you to set affiliations and roles",
@@ -28,14 +40,7 @@ describe("The groupchat moderator tool", function () {
         const view = _converse.chatboxviews.get(muc_jid);
         await u.waitUntil(() => (view.model.occupants.length === 5), 1000);
 
-        const textarea = view.el.querySelector('.chat-textarea');
-        textarea.value = '/modtools';
-        const enter = { 'target': textarea, 'preventDefault': function preventDefault () {}, 'keyCode': 13 };
-        view.onKeyDown(enter);
-        await u.waitUntil(() => view.showModeratorToolsModal.calls.count());
-
-        const modal = view.modtools_modal;
-        await u.waitUntil(() => u.isVisible(modal.el), 1000);
+        const modal = await openModtools(view);
         let tab = modal.el.querySelector('#affiliations-tab');
         // Clear so that we don't match older stanzas
         _converse.connection.IQ_stanzas = [];
@@ -156,16 +161,9 @@ describe("The groupchat moderator tool", function () {
         const view = _converse.chatboxviews.get(muc_jid);
         await u.waitUntil(() => (view.model.occupants.length === 6), 1000);
 
-        const textarea = view.el.querySelector('.chat-textarea');
-        textarea.value = '/modtools';
-        const enter = { 'target': textarea, 'preventDefault': function preventDefault () {}, 'keyCode': 13 };
-        view.onKeyDown(enter);
-        await u.waitUntil(() => view.showModeratorToolsModal.calls.count());
-
-        const modal = view.modtools_modal;
-        await u.waitUntil(() => u.isVisible(modal.el), 1000);
         // Clear so that we don't match older stanzas
         _converse.connection.IQ_stanzas = [];
+        const modal = await openModtools(view);
         const select = modal.el.querySelector('.select-affiliation');
         expect(select.value).toBe('owner');
         select.value = 'member';
@@ -328,15 +326,7 @@ describe("The groupchat moderator tool", function () {
         await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo', [], members);
         const view = _converse.chatboxviews.get(muc_jid);
         await u.waitUntil(() => (view.model.occupants.length === 5));
-
-        const textarea = view.el.querySelector('.chat-textarea');
-        textarea.value = '/modtools';
-        const enter = { 'target': textarea, 'preventDefault': function preventDefault () {}, 'keyCode': 13 };
-        view.onKeyDown(enter);
-        await u.waitUntil(() => view.showModeratorToolsModal.calls.count());
-
-        const modal = view.modtools_modal;
-        await u.waitUntil(() => u.isVisible(modal.el), 1000);
+        const modal = await openModtools(view);
         const tab = modal.el.querySelector('#affiliations-tab');
         // Clear so that we don't match older stanzas
         _converse.connection.IQ_stanzas = [];
@@ -371,6 +361,73 @@ describe("The groupchat moderator tool", function () {
         done();
     }));
 
+    it("shows an error message if a particular affiliation may not be set",
+        mock.initConverse(
+            ['rosterGroupsFetched'], {},
+            async function (done, _converse) {
+
+        spyOn(_converse.ChatRoomView.prototype, 'showModeratorToolsModal').and.callThrough();
+        const muc_jid = 'lounge@montague.lit';
+        const members = [
+            {'jid': 'gower@shakespeare.lit', 'nick': 'gower', 'affiliation': 'member'},
+            {'jid': 'romeo@montague.lit', 'nick': 'romeo', 'affiliation': 'owner'},
+        ];
+        await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo', [], members);
+        const view = _converse.chatboxviews.get(muc_jid);
+        await u.waitUntil(() => (view.model.occupants.length === 2));
+        const modal = await openModtools(view);
+        // Clear so that we don't match older stanzas
+        _converse.connection.IQ_stanzas = [];
+
+        const tab = modal.el.querySelector('#affiliations-tab');
+        tab.click();
+        const select = modal.el.querySelector('.select-affiliation');
+        select.value = 'member';
+        const button = modal.el.querySelector('.btn-primary[name="users_with_affiliation"]');
+        button.click();
+        await u.waitUntil(() => !modal.loading_users_with_affiliation);
+        const user_els = modal.el.querySelectorAll('.list-group--users > li');
+        expect(user_els.length).toBe(1);
+
+        const toggle = user_els[0].querySelector('.list-group-item:nth-child(3n) .toggle-form');
+        const form = user_els[0].querySelector('.list-group-item:nth-child(3n) .affiliation-form');
+        expect(u.hasClass('hidden', form)).toBeTruthy();
+        toggle.click();
+        expect(u.hasClass('hidden', form)).toBeFalsy();
+        const change_affiliation_dropdown = form.querySelector('.select-affiliation');
+        expect(change_affiliation_dropdown.value).toBe('member');
+        change_affiliation_dropdown.value = 'admin';
+        const input = form.querySelector('input[name="reason"]');
+        input.value = "You're an admin now";
+        const submit = form.querySelector('.btn-primary');
+        submit.click();
+
+        const sent_IQ = _converse.connection.IQ_stanzas.pop();
+        expect(Strophe.serialize(sent_IQ)).toBe(
+            `<iq id="${sent_IQ.getAttribute('id')}" to="lounge@montague.lit" type="set" xmlns="jabber:client">`+
+                `<query xmlns="http://jabber.org/protocol/muc#admin">`+
+                    `<item affiliation="admin" jid="gower@shakespeare.lit">`+
+                        `<reason>You&apos;re an admin now</reason>`+
+                    `</item>`+
+                `</query>`+
+            `</iq>`);
+
+        const error = u.toStanza(
+            `<iq from="${muc_jid}"
+                 id="${sent_IQ.getAttribute('id')}"
+                 type="error"
+                 to="${_converse.jid}">
+
+                 <error type="cancel">
+                    <not-allowed xmlns="${Strophe.NS.STANZAS}"/>
+                 </error>
+            </iq>`);
+        _converse.connection._dataRecv(mock.createRequest(error));
+
+        done();
+    }));
+
+
     it("doesn't allow admins to make more admins",
         mock.initConverse(
             ['rosterGroupsFetched'], {},
@@ -386,15 +443,7 @@ describe("The groupchat moderator tool", function () {
         await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo', [], members);
         const view = _converse.chatboxviews.get(muc_jid);
         await u.waitUntil(() => (view.model.occupants.length === 3));
-
-        const textarea = view.el.querySelector('.chat-textarea');
-        textarea.value = '/modtools';
-        const enter = { 'target': textarea, 'preventDefault': function preventDefault () {}, 'keyCode': 13 };
-        view.onKeyDown(enter);
-        await u.waitUntil(() => view.showModeratorToolsModal.calls.count());
-
-        const modal = view.modtools_modal;
-        await u.waitUntil(() => u.isVisible(modal.el), 1000);
+        const modal = await openModtools(view);
         const tab = modal.el.querySelector('#affiliations-tab');
         // Clear so that we don't match older stanzas
         _converse.connection.IQ_stanzas = [];

+ 17 - 11
src/modals/moderator-tools.js

@@ -147,7 +147,7 @@ export default BootstrapModal.extend({
         this.model.set({'affiliation': affiliation});
     },
 
-    assignAffiliation (ev) {
+    async assignAffiliation (ev) {
         ev.stopPropagation();
         ev.preventDefault();
         const data = new FormData(ev.target);
@@ -157,17 +157,23 @@ export default BootstrapModal.extend({
             'reason': data.get('reason')
         }
         const current_affiliation = this.model.get('affiliation');
-        this.chatroomview.model.setAffiliation(affiliation, [attrs])
-            .then(async () => {
-                this.alert(__('Affiliation changed'), 'primary');
-                await this.chatroomview.model.occupants.fetchMembers()
-                this.model.set({'affiliation': null}, {'silent': true});
-                this.model.set({'affiliation': current_affiliation});
-            })
-            .catch(err => {
+        try {
+            await this.chatroomview.model.setAffiliation(affiliation, [attrs]);
+        } catch (e) {
+            if (e === null) {
+                this.alert(__('Timeout error while trying to set the affiliation'), 'danger');
+            } else if (sizzle(`not-allowed[xmlns="${Strophe.NS.STANZAS}"]`, e).length) {
+                this.alert(__('Sorry, you\'re not allowed to make that change'), 'danger');
+            } else {
                 this.alert(__('Sorry, something went wrong while trying to set the affiliation'), 'danger');
-                log.error(err);
-            });
+            }
+            log.error(e);
+            return;
+        }
+        this.alert(__('Affiliation changed'), 'primary');
+        await this.chatroomview.model.occupants.fetchMembers()
+        this.model.set({'affiliation': null}, {'silent': true});
+        this.model.set({'affiliation': current_affiliation});
     },
 
     assignRole (ev) {