Add test case for adhoc commands

This commit is contained in:
JC Brand 2022-10-18 10:10:13 +02:00
parent 4531dd4363
commit 83351fb98f
5 changed files with 88 additions and 15 deletions

View File

@ -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' },

View File

@ -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);

View File

@ -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>`
: '' }

View File

@ -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');
}));
});

View File

@ -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,