Browse Source

Add test case for adhoc commands

JC Brand 2 years ago
parent
commit
83351fb98f

+ 2 - 1
karma.conf.js

@@ -42,8 +42,9 @@ module.exports = function(config) {
       { pattern: "src/headless/tests/converse.js", type: 'module' },
       { pattern: "src/headless/tests/eventemitter.js", type: 'module' },
       { pattern: "src/modals/tests/user-details-modal.js", type: 'module' },
-      { pattern: "src/plugins/bookmark-views/tests/bookmarks.js", type: 'module' },
+      { pattern: "src/plugins/adhoc-views/tests/adhoc.js", type: 'module' },
       { pattern: "src/plugins/bookmark-views/tests/bookmarks-list.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/corrections.js", type: 'module' },
       { pattern: "src/plugins/chatview/tests/emojis.js", type: 'module' },

+ 8 - 6
src/plugins/adhoc-views/adhoc-commands.js

@@ -16,6 +16,7 @@ export default class AdHocCommands extends CustomElement {
             'alert': { type: String },
             'alert_type': { type: String },
             'nonce': { type: String }, // Used to force re-rendering
+            'fetching': { type: Boolean }, // Used to force re-rendering
             'showform': { type: String },
             'view': { type: String },
         }
@@ -24,21 +25,17 @@ export default class AdHocCommands extends CustomElement {
     constructor () {
         super();
         this.view = 'choose-service';
+        this.fetching = false;
         this.showform = '';
         this.commands = [];
     }
 
     render () {
-        return tpl_adhoc({
-            'alert': this.alert,
-            'alert_type': this.alert_type,
-            'commands': this.commands,
-            'fetchCommands': ev => this.fetchCommands(ev),
+        return tpl_adhoc(this, {
             'hideCommandForm': ev => this.hideCommandForm(ev),
             'runCommand': ev => this.runCommand(ev),
             'showform': this.showform,
             'toggleCommandForm': ev => this.toggleCommandForm(ev),
-            'view': this.view,
         });
     }
 
@@ -47,6 +44,8 @@ export default class AdHocCommands extends CustomElement {
         delete this.alert_type;
         delete this.alert;
 
+        this.fetching = true;
+
         const form_data = new FormData(ev.target);
         const jid = form_data.get('jid').trim();
         let supported;
@@ -54,7 +53,10 @@ export default class AdHocCommands extends CustomElement {
             supported = await api.disco.supports(Strophe.NS.ADHOC, jid)
         } catch (e) {
             log.error(e);
+        } finally {
+            this.fetching = false;
         }
+
         if (supported) {
             try {
                 this.commands = await api.adhoc.getCommands(jid);

+ 8 - 7
src/plugins/adhoc-views/templates/ad-hoc.js

@@ -1,10 +1,11 @@
 import tpl_command from './ad-hoc-command.js';
+import tpl_spinner from 'templates/spinner.js';
 import { __ } from 'i18n';
 import { getAutoCompleteList } from '../utils.js';
 import { html } from "lit";
 
 
-export default (o) => {
+export default (el, o) => {
     const i18n_choose_service = __('On which entity do you want to run commands?');
     const i18n_choose_service_instructions = __(
         'Certain XMPP services and entities allow privileged users to execute ad-hoc commands on them.');
@@ -13,8 +14,8 @@ export default (o) => {
     const i18n_jid_placeholder = __('XMPP Address');
     const i18n_no_commands_found = __('No commands found');
     return html`
-        ${ o.alert ? html`<div class="alert alert-${o.alert_type}" role="alert">${o.alert}</div>` : '' }
-        <form class="converse-form" @submit=${o.fetchCommands}>
+        ${ el.alert ? html`<div class="alert alert-${el.alert_type}" role="alert">${el.alert}</div>` : '' }
+        <form class="converse-form" @submit=${el.fetchCommands}>
             <fieldset class="form-group">
                 <label>
                     ${i18n_choose_service}
@@ -27,13 +28,13 @@ export default (o) => {
                 </label>
             </fieldset>
             <fieldset class="form-group">
-                <input type="submit" class="btn btn-primary" value="${i18n_fetch_commands}">
+                ${ el.fetching ? tpl_spinner() : html`<input type="submit" class="btn btn-primary" value="${i18n_fetch_commands}">` }
             </fieldset>
-            ${ o.view === 'list-commands' ? html`
+            ${ el.view === 'list-commands' ? html`
             <fieldset class="form-group">
                 <ul class="list-group">
-                    <li class="list-group-item active">${ o.commands.length ? i18n_commands_found : i18n_no_commands_found }:</li>
-                    ${ o.commands.map(cmd => tpl_command(o, cmd)) }
+                    <li class="list-group-item active">${ el.commands.length ? i18n_commands_found : i18n_no_commands_found }:</li>
+                    ${ el.commands.map(cmd => tpl_command(o, cmd)) }
                 </ul>
             </fieldset>`
             : '' }

+ 69 - 0
src/plugins/adhoc-views/tests/adhoc.js

@@ -0,0 +1,69 @@
+/*global mock, converse */
+
+const { sizzle, u, stx } = converse.env;
+
+describe("Ad-hoc commands", function () {
+
+    fit("can be queried for via a modal", mock.initConverse([], {}, async (_converse) => {
+        const { api } = _converse;
+        const entity_jid = 'muc.montague.lit';
+
+        const modal = await api.modal.show('converse-user-settings-modal');
+        await u.waitUntil(() => u.isVisible(modal));
+        modal.querySelector('#commands-tab').click();
+
+        const adhoc_form = modal.querySelector('converse-adhoc-commands');
+        await u.waitUntil(() => u.isVisible(adhoc_form));
+
+        const input = adhoc_form.querySelector('input[name="jid"]');
+        input.value = entity_jid;
+
+        const submit = adhoc_form.querySelector('input[type="submit"]');
+        submit.click();
+
+        await mock.waitUntilDiscoConfirmed(_converse, entity_jid, [], ['http://jabber.org/protocol/commands'], [], 'info');
+
+        const sel = `iq[to="${entity_jid}"] query[xmlns="http://jabber.org/protocol/disco#items"]`;
+        const iq = await u.waitUntil(() => _converse.connection.IQ_stanzas.filter(iq => sizzle(sel, iq).length).pop());
+
+        _converse.connection._dataRecv(mock.createRequest(stx`
+            <iq type="result"
+                id="${iq.getAttribute("id")}"
+                to="${_converse.jid}"
+                from="${entity_jid}">
+            <query xmlns="http://jabber.org/protocol/disco#items"
+                    node="http://jabber.org/protocol/commands">
+                <item jid="${entity_jid}"
+                    node="list"
+                    name="List Service Configurations"/>
+                <item jid="${entity_jid}"
+                    node="config"
+                    name="Configure Service"/>
+                <item jid="${entity_jid}"
+                    node="reset"
+                    name="Reset Service Configuration"/>
+                <item jid="${entity_jid}"
+                    node="start"
+                    name="Start Service"/>
+                <item jid="${entity_jid}"
+                    node="stop"
+                    name="Stop Service"/>
+                <item jid="${entity_jid}"
+                    node="restart"
+                    name="Restart Service"/>
+            </query>
+        </iq>`));
+
+        const heading = await u.waitUntil(() => adhoc_form.querySelector('.list-group-item.active'));
+        expect(heading.textContent).toBe('Commands found:');
+
+        const items = adhoc_form.querySelectorAll('.list-group-item:not(.active)');
+        expect(items.length).toBe(6);
+        expect(items[0].textContent.trim()).toBe('List Service Configurations');
+        expect(items[1].textContent.trim()).toBe('Configure Service');
+        expect(items[2].textContent.trim()).toBe('Reset Service Configuration');
+        expect(items[3].textContent.trim()).toBe('Start Service');
+        expect(items[4].textContent.trim()).toBe('Stop Service');
+        expect(items[5].textContent.trim()).toBe('Restart Service');
+    }));
+});

+ 1 - 1
src/shared/tests/mock.js

@@ -640,7 +640,7 @@ async function _initConverse (settings) {
         'enable_smacks': false,
         'i18n': 'en',
         'persistent_store': 'localStorage',
-        'loglevel': 'warn',
+        'loglevel': 'debug',
         'no_trimming': true,
         'play_sounds': false,
         'use_emojione': false,