Skip to content

Commit

Permalink
Set auto_register_muc_nickname to true by default and fix tests.
Browse files Browse the repository at this point in the history
Also add tests for registering of nickname with a MUC
  • Loading branch information
jcbrand committed Jan 3, 2025
1 parent 7f0d42c commit 615397b
Show file tree
Hide file tree
Showing 9 changed files with 192 additions and 109 deletions.
13 changes: 7 additions & 6 deletions src/headless/plugins/muc/affiliations/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,17 +91,18 @@ export function setAffiliation (affiliation, muc_jids, members) {

/**
* Send an IQ stanza specifying an affiliation change.
* @param {AFFILIATIONS[number]} affiliation: affiliation (could also be stored on the member object).
* @param {string} muc_jid: The JID of the MUC in which the affiliation should be set.
* @param {object} member: Map containing the member's jid and optionally a reason and affiliation.
* @param {AFFILIATIONS[number]} affiliation - Affiliation (could also be stored on the member object).
* @param {string} muc_jid - The JID of the MUC in which the affiliation should be set.
* @param {object} member - Map containing the member's jid and optionally a reason and affiliation.
*/
function sendAffiliationIQ (affiliation, muc_jid, member) {
affiliation = member.affiliation || affiliation;
const iq = $iq({ to: muc_jid, type: 'set' })
.c('query', { xmlns: Strophe.NS.MUC_ADMIN })
.c('item', {
'affiliation': member.affiliation || affiliation,
'nick': member.nick,
'jid': member.jid
affiliation,
...(affiliation === 'outcast' ? {} : {nick: member.nick }),
jid: member.jid
});
if (member.reason !== undefined) {
iq.c('reason', member.reason);
Expand Down
28 changes: 15 additions & 13 deletions src/headless/plugins/muc/muc.js
Original file line number Diff line number Diff line change
Expand Up @@ -1687,10 +1687,9 @@ class MUC extends ModelWithMessages(ColorAwareModel(ChatBoxBase)) {
let iq, err_msg;
try {
iq = await api.sendIQ(
$iq({
'to': jid,
'type': 'get',
}).c('query', { 'xmlns': Strophe.NS.MUC_REGISTER })
stx`<iq to="${jid}" type="get" xmlns="jabber:client">
<query xmlns="${Strophe.NS.MUC_REGISTER}"/>
</iq>`
);
} catch (e) {
if (sizzle(`not-allowed[xmlns="${Strophe.NS.STANZAS}"]`, e).length) {
Expand All @@ -1707,15 +1706,18 @@ class MUC extends ModelWithMessages(ColorAwareModel(ChatBoxBase)) {
}
try {
await api.sendIQ(
$iq({
'to': jid,
'type': 'set'
}).c('query', { 'xmlns': Strophe.NS.MUC_REGISTER })
.c('x', { 'xmlns': Strophe.NS.XFORM, 'type': 'submit' })
.c('field', { 'var': 'FORM_TYPE' })
.c('value').t('http://jabber.org/protocol/muc#register').up().up()
.c('field', { 'var': 'muc#register_roomnick' })
.c('value').t(nick)
stx`<iq to="${jid}" type="set" xmlns="jabber:client">
<query xmlns="${Strophe.NS.MUC_REGISTER}">
<x xmlns="${Strophe.NS.XFORM}" type="submit">
<field var="FORM_TYPE">
<value>http://jabber.org/protocol/muc#register</value>
</field>
<field var="muc#register_roomnick">
<value>${nick}</value>
</field>
</x>
</query>
</iq>`
);
} catch (e) {
const err = await parseErrorStanza(e);
Expand Down
2 changes: 1 addition & 1 deletion src/headless/plugins/muc/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ converse.plugins.add('converse-muc', {
allow_muc_invitations: true,
auto_join_on_invite: false,
auto_join_rooms: [],
auto_register_muc_nickname: false,
auto_register_muc_nickname: true,
colorize_username: false,
hide_muc_participants: false,
locked_muc_domain: false,
Expand Down
130 changes: 73 additions & 57 deletions src/headless/plugins/muc/tests/registration.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

const { $iq, Strophe, sizzle, u } = converse.env;

describe("Chatrooms", function () {
describe("Groupchats", function () {
beforeAll(() => jasmine.addMatchers({ toEqualStanza: jasmine.toEqualStanza }));

describe("The auto_register_muc_nickname option", function () {

Expand All @@ -11,42 +12,53 @@ describe("Chatrooms", function () {
async function (_converse) {

const muc_jid = 'coven@chat.shakespeare.lit';
const room = await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');

let stanza = await u.waitUntil(() => _converse.api.connection.get().IQ_stanzas.filter(
iq => sizzle(`iq[to="${muc_jid}"][type="get"] query[xmlns="jabber:iq:register"]`, iq).length
).pop());
const IQ_stanzas = _converse.api.connection.get().IQ_stanzas;
let stanza = await u.waitUntil(() => IQ_stanzas.find(
iq => sizzle(`iq[type="get"] query[xmlns="${Strophe.NS.MUC_REGISTER}"]`, iq).length));

expect(Strophe.serialize(stanza))
.toBe(`<iq id="${stanza.getAttribute('id')}" to="${muc_jid}" `+
`type="get" xmlns="jabber:client">`+
`<query xmlns="jabber:iq:register"/></iq>`);
const result = $iq({
'from': room.get('jid'),
'id': stanza.getAttribute('id'),
'to': _converse.bare_jid,
'type': 'result',
}).c('query', {'xmlns': 'jabber:iq:register'})
.c('x', {'xmlns': 'jabber:x:data', 'type': 'form'})
.c('field', {
'label': 'Desired Nickname',
'type': 'text-single',
'var': 'muc#register_roomnick'
}).c('required');
_converse.api.connection.get()._dataRecv(mock.createRequest(result));
stanza = await u.waitUntil(() => _converse.api.connection.get().IQ_stanzas.filter(
iq => sizzle(`iq[to="${muc_jid}"][type="set"] query[xmlns="jabber:iq:register"]`, iq).length
).pop());
expect(stanza).toEqualStanza(
stx`<iq to="${muc_jid}"
type="get"
xmlns="jabber:client"
id="${stanza.getAttribute('id')}"><query xmlns="jabber:iq:register"/></iq>`);

_converse.api.connection.get()._dataRecv(mock.createRequest(
stx`<iq from="${muc_jid}"
id="${stanza.getAttribute('id')}"
to="${_converse.session.get('jid')}"
xmlns="jabber:client"
type="result">
<query xmlns='jabber:iq:register'>
<x xmlns='jabber:x:data' type='form'>
<field
type='hidden'
var='FORM_TYPE'>
<value>http://jabber.org/protocol/muc#register</value>
</field>
<field
label='Desired Nickname'
type='text-single'
var='muc#register_roomnick'>
<required/>
</field>
</x>
</query>
</iq>`));

expect(Strophe.serialize(stanza)).toBe(
`<iq id="${stanza.getAttribute('id')}" to="${muc_jid}" type="set" xmlns="jabber:client">`+
`<query xmlns="jabber:iq:register">`+
`<x type="submit" xmlns="jabber:x:data">`+
`<field var="FORM_TYPE"><value>http://jabber.org/protocol/muc#register</value></field>`+
`<field var="muc#register_roomnick"><value>romeo</value></field>`+
`</x>`+
`</query>`+
`</iq>`);
stanza = await u.waitUntil(() => IQ_stanzas.find(
iq => sizzle(`iq[type="set"] query[xmlns="${Strophe.NS.MUC_REGISTER}"]`, iq).length));

expect(stanza).toEqualStanza(
stx`<iq xmlns="jabber:client" to="${muc_jid}" type="set" id="${stanza.getAttribute('id')}">
<query xmlns="jabber:iq:register">
<x xmlns="jabber:x:data" type="submit">
<field var="FORM_TYPE"><value>http://jabber.org/protocol/muc#register</value></field>
<field var="muc#register_roomnick"><value>romeo</value></field>
</x>
</query>
</iq>`);
}));

it("allows you to automatically deregister your nickname when closing a room",
Expand All @@ -59,18 +71,21 @@ describe("Chatrooms", function () {
let stanza = await u.waitUntil(() => _converse.api.connection.get().IQ_stanzas.filter(
iq => sizzle(`iq[to="${muc_jid}"][type="get"] query[xmlns="jabber:iq:register"]`, iq).length
).pop());
let result = $iq({
'from': room.get('jid'),
'id': stanza.getAttribute('id'),
'to': _converse.bare_jid,
'type': 'result',
}).c('query', {'xmlns': 'jabber:iq:register'})
.c('x', {'xmlns': 'jabber:x:data', 'type': 'form'})
.c('field', {
'label': 'Desired Nickname',
'type': 'text-single',
'var': 'muc#register_roomnick'
}).c('required');
let result = stx`<iq from="${room.get('jid')}"
id="${stanza.getAttribute('id')}"
to="${_converse.bare_jid}"
type="result"
xmlns="jabber:client">
<query xmlns="jabber:iq:register">
<x xmlns="jabber:x:data" type="form">
<field label="Desired Nickname"
type="text-single"
var="muc#register_roomnick">
<required/>
</field>
</x>
</query>
</iq>`;
_converse.api.connection.get()._dataRecv(mock.createRequest(result));
await u.waitUntil(() => _converse.api.connection.get().IQ_stanzas.filter(
iq => sizzle(`iq[to="${muc_jid}"][type="set"] query[xmlns="jabber:iq:register"]`, iq).length
Expand All @@ -82,17 +97,18 @@ describe("Chatrooms", function () {
stanza = await u.waitUntil(() => _converse.api.connection.get().IQ_stanzas.filter(
iq => sizzle(`iq[to="${muc_jid}"][type="set"] query[xmlns="jabber:iq:register"]`, iq).length
).pop());
expect(Strophe.serialize(stanza)).toBe(
`<iq id="${stanza.getAttribute('id')}" to="${muc_jid}" type="set" xmlns="jabber:client">`+
`<query xmlns="jabber:iq:register"><remove/></query>`+
`</iq>`);

result = $iq({
'from': room.get('jid'),
'id': stanza.getAttribute('id'),
'to': _converse.bare_jid,
'type': 'result',
}).c('query', {'xmlns': 'jabber:iq:register'});
expect(stanza).toEqualStanza(
stx`<iq id="${stanza.getAttribute('id')}" to="${muc_jid}" type="set" xmlns="jabber:client">
<query xmlns="jabber:iq:register"><remove/></query>
</iq>`);

result = stx`<iq from="${room.get('jid')}"
id="${stanza.getAttribute('id')}"
to="${_converse.bare_jid}"
type="result"
xmlns="jabber:client">
<query xmlns="jabber:iq:register"></query>
</iq>`;
_converse.api.connection.get()._dataRecv(mock.createRequest(result));

}));
Expand Down
2 changes: 1 addition & 1 deletion src/headless/types/plugins/muc/muc.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ declare class MUC extends MUC_base {
getOwnOccupant(): import("./occupant.js").default;
/**
* Send a presence stanza to update the user's nickname in this MUC.
* @param { String } nick
* @param {String} nick
*/
setNickname(nick: string): Promise<void>;
/**
Expand Down
62 changes: 35 additions & 27 deletions src/plugins/muc-views/tests/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
const { Strophe, Promise, sizzle, stx, u } = converse.env;

describe("Groupchats", function () {
beforeAll(() => jasmine.addMatchers({ toEqualStanza: jasmine.toEqualStanza }));

describe("Each chat groupchat can take special commands", function () {

it("takes /help to show the available commands",
Expand Down Expand Up @@ -142,8 +144,9 @@ describe("Groupchats", function () {
mock.initConverse([], {}, async function (_converse) {

let iq_stanza;
await mock.openAndEnterChatRoom(_converse, 'lounge@muc.montague.lit', 'romeo');
const view = _converse.chatboxviews.get('lounge@muc.montague.lit');
const nick = 'romeo';
const muc_jid = 'lounge@muc.montague.lit';
const muc = await mock.openAndEnterChatRoom(_converse, muc_jid, nick);

/* We don't show join/leave messages for existing occupants. We
* know about them because we receive their presences before we
Expand All @@ -159,8 +162,10 @@ describe("Groupchats", function () {
</x>
</presence>`
));
expect(view.model.occupants.length).toBe(2);

expect(muc.occupants.length).toBe(2);

const view = _converse.chatboxviews.get(muc_jid);
const textarea = await u.waitUntil(() => view.querySelector('.chat-textarea'));
let sent_stanza;
spyOn(_converse.api.connection.get(), 'send').and.callFake((stanza) => {
Expand Down Expand Up @@ -188,14 +193,17 @@ describe("Groupchats", function () {
preventDefault: function preventDefault () {},
keyCode: 13
});
await u.waitUntil(() => Strophe.serialize(sent_stanza) ===
`<iq id="${sent_stanza.getAttribute('id')}" to="lounge@muc.montague.lit" type="set" xmlns="jabber:client">`+
`<query xmlns="http://jabber.org/protocol/muc#admin">`+
`<item affiliation="member" jid="marc@montague.lit">`+
`<reason>Welcome to the club!</reason>`+
`</item>`+
`</query>`+
`</iq>`);

await u.waitUntil(() => sent_stanza.querySelector('item[affiliation="member"]'));

expect(sent_stanza).toEqualStanza(
stx`<iq id="${sent_stanza.getAttribute('id')}" to="lounge@muc.montague.lit" type="set" xmlns="jabber:client">
<query xmlns="http://jabber.org/protocol/muc#admin">
<item affiliation="member" nick="marc" jid="marc@montague.lit">
<reason>Welcome to the club!</reason>
</item>
</query>
</iq>`);

let result = stx`<iq xmlns="jabber:client"
type="result"
Expand Down Expand Up @@ -413,14 +421,14 @@ describe("Groupchats", function () {

await u.waitUntil(() => view.model.validateRoleOrAffiliationChangeArgs.calls.count() === 3);
// Check that the member list now gets updated
expect(Strophe.serialize(sent_IQ)).toBe(
`<iq id="${IQ_id}" to="lounge@montague.lit" type="set" xmlns="jabber:client">`+
`<query xmlns="http://jabber.org/protocol/muc#admin">`+
`<item affiliation="owner" jid="annoyingguy@montague.lit">`+
`<reason>You&apos;re responsible</reason>`+
`</item>`+
`</query>`+
`</iq>`);
expect(sent_IQ).toEqualStanza(
stx`<iq id="${IQ_id}" to="lounge@montague.lit" type="set" xmlns="jabber:client">
<query xmlns="http://jabber.org/protocol/muc#admin">
<item affiliation="owner" nick="annoyingGuy" jid="annoyingguy@montague.lit">
<reason>You&apos;re responsible</reason>
</item>
</query>
</iq>`);

_converse.api.connection.get()._dataRecv(mock.createRequest(
stx`<presence
Expand Down Expand Up @@ -487,14 +495,14 @@ describe("Groupchats", function () {

await u.waitUntil(() => view.model.validateRoleOrAffiliationChangeArgs.calls.count() === 2);
// Check that the member list now gets updated
expect(Strophe.serialize(sent_IQ)).toBe(
`<iq id="${IQ_id}" to="lounge@montague.lit" type="set" xmlns="jabber:client">`+
`<query xmlns="http://jabber.org/protocol/muc#admin">`+
`<item affiliation="outcast" jid="annoyingguy@montague.lit">`+
`<reason>You&apos;re annoying</reason>`+
`</item>`+
`</query>`+
`</iq>`);
expect(sent_IQ).toEqualStanza(
stx`<iq id="${IQ_id}" to="lounge@montague.lit" type="set" xmlns="jabber:client">
<query xmlns="http://jabber.org/protocol/muc#admin">
<item affiliation="outcast" jid="annoyingguy@montague.lit">
<reason>You&apos;re annoying</reason>
</item>
</query>
</iq>`);

_converse.api.connection.get()._dataRecv(mock.createRequest(
stx`<presence
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/muc-views/tests/mentions.js
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ describe("A sent groupchat message", function () {
}));

it("includes a XEP-0372 references to that person",
mock.initConverse([], {}, async function (_converse) {
mock.initConverse([], { auto_register_muc_nickname: false }, async function (_converse) {

const nick = 'romeo';
const muc_jid = 'lounge@montague.lit';
Expand Down
Loading

0 comments on commit 615397b

Please sign in to comment.