Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jcbrand committed Jan 4, 2025
1 parent 37058db commit f5aa730
Show file tree
Hide file tree
Showing 19 changed files with 252 additions and 136 deletions.
1 change: 1 addition & 0 deletions karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ module.exports = function(config) {
},
{ pattern: "src/shared/tests/mock.js", type: 'module' },

{ pattern: "src/headless/plugins/blocking/tests/blocking.js", type: 'module' },
{ pattern: "src/headless/plugins/bookmarks/tests/bookmarks.js", type: 'module' },
{ pattern: "src/headless/plugins/bookmarks/tests/deprecated.js", type: 'module' },
{ pattern: "src/headless/plugins/caps/tests/caps.js", type: 'module' },
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/headless/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"pluggable.js": "3.0.1",
"sizzle": "^2.3.5",
"sprintf-js": "^1.1.2",
"strophe.js": "strophe/strophejs#9b643a43b5cd79f0d8a2e0015e9d2c0d0fec8578",
"strophe.js": "strophe/strophejs#b4f3369ba07dee4f04750de6709ea8ebe8adf9a5",
"urijs": "^1.19.10"
},
"devDependencies": {}
Expand Down
22 changes: 12 additions & 10 deletions src/headless/plugins/blocking/collection.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { getOpenPromise } from '@converse/openpromise';
import { Collection } from '@converse/skeletor';
import log from '../../log.js';
import _converse from '../../shared/_converse.js';
import { initStorage } from '../../utils/storage.js';
import api from '../../shared/api/index.js';
import converse from '../../shared/api/public.js';
import { Collection } from '@converse/skeletor';
import BlockedEntity from './model.js';

const { stx, u } = converse.env;
Expand All @@ -19,11 +20,13 @@ class Blocklist extends Collection {
}

async initialize() {
await this.fetchBlocklist();

const { session } = _converse;
const cache_key = `converse.blocklist-${session.get('bare_jid')}`;
this.fetched_flag = cache_key + 'fetched';
this.fetched_flag = `${cache_key}-fetched`;
initStorage(this, cache_key);

await this.fetchBlocklist();

/**
* Triggered once the {@link Blocklist} collection
* has been created and cached blocklist have been fetched.
Expand Down Expand Up @@ -69,12 +72,11 @@ class Blocklist extends Collection {
* @param {Element} iq
*/
async onBlocklistReceived(deferred, iq) {
Array.from(iq.querySelectorAll('blocklist item'))
.forEach((item) => {
const jid = item.getAttribute('jid');
const blocked = this.get(jid);
blocked ? blocked.save({ jid }) : this.create({ jid });
});
Array.from(iq.querySelectorAll('blocklist item')).forEach((item) => {
const jid = item.getAttribute('jid');
const blocked = this.get(jid);
blocked ? blocked.save({ jid }) : this.create({ jid });
});

window.sessionStorage.setItem(this.fetched_flag, 'true');
if (deferred !== undefined) {
Expand Down
57 changes: 49 additions & 8 deletions src/headless/plugins/blocking/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,63 @@
import _converse from '../../shared/_converse.js';
import api from '../../shared/api/index.js';
import converse from '../../shared/api/public.js';
import log from '../../log.js';
import Blocklist from './collection.js';
import BlockedEntity from './model.js';

const { Strophe } = converse.env;
const { Strophe, sizzle } = converse.env;

Strophe.addNamespace('BLOCKING', "urn:xmpp:blocking");
Strophe.addNamespace('BLOCKING', 'urn:xmpp:blocking');

converse.plugins.add('converse-blocking', {
dependencies: ["converse-disco"],
dependencies: ['converse-disco'],

initialize () {
const exports = { Blocklist, BlockedEntity };
initialize() {
const exports = { Blocklist, BlockedEntity };
Object.assign(_converse.exports, exports);

api.listen.on('discoInitialized', () => {
_converse.state.blocklist = new _converse.exports.Blocklist();
api.promises.add(['blocklistInitialized']);

api.listen.on('connected', () => {
const connection = api.connection.get();
connection.addHandler(
/** @param {Element} stanza */ (stanza) => {
const bare_jid = _converse.session.get('bare_jid');
const from = stanza.getAttribute('from');
if (Strophe.getBareJidFromJid(from ?? bare_jid) != bare_jid) {
log.warn(`Received a blocklist push stanza from a suspicious JID ${from}`);
return true;
}

sizzle(`block[xmlns="${Strophe.NS.BLOCKING}"] item`, stanza).forEach(
/** @param {Element} item */ (item) => {
const jid = item.getAttribute('jid');
const { state } = _converse;
state.blocklist?.create({ jid });
}
);
return true;
},
Strophe.NS.BLOCKING,
'iq',
'set'
);
});

api.listen.on('clearSession', () => {
const { state } = _converse;
if (state.blocklist) {
state.blocklist.clearStore({ 'silent': true });
window.sessionStorage.removeItem(state.blocklist.fetched_flag);
delete state.blocklist;
}
});

api.listen.on('discoInitialized', async () => {
const domain = _converse.session.get('domain');
if (await api.disco.supports(Strophe.NS.BLOCKING, domain)) {
_converse.state.blocklist = new _converse.exports.Blocklist();
}
});
}
},
});
95 changes: 95 additions & 0 deletions src/headless/plugins/blocking/tests/blocking.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*global mock, converse */
const { u, stx } = converse.env;

describe('A block list', function () {
beforeEach(() => {
jasmine.addMatchers({ toEqualStanza: jasmine.toEqualStanza });
window.sessionStorage.removeItem('converse.blocklist-romeo@montague.lit-fetched');
});

it(
'is automatically fetched from the server once the user logs in',
mock.initConverse(['discoInitialized'], {}, async function (_converse) {
const { api } = _converse;
await mock.waitUntilDiscoConfirmed(
_converse,
_converse.domain,
[{ 'category': 'server', 'type': 'IM' }],
['urn:xmpp:blocking']
);
await mock.waitForRoster(_converse, 'current', 0);

const IQ_stanzas = _converse.api.connection.get().IQ_stanzas;
const sent_stanza = await u.waitUntil(() => IQ_stanzas.find((s) => s.querySelector('iq blocklist')));

expect(sent_stanza).toEqualStanza(stx`
<iq xmlns="jabber:client" type="get" id="${sent_stanza.getAttribute('id')}">
<blocklist xmlns="urn:xmpp:blocking"/>
</iq>`);

const stanza = stx`
<iq xmlns="jabber:client"
to="${_converse.api.connection.get().jid}"
type="result"
id="${sent_stanza.getAttribute('id')}">
<blocklist xmlns='urn:xmpp:blocking'>
<item jid='iago@shakespeare.lit'/>
<item jid='juliet@capulet.lit'/>
</blocklist>
</iq>`;
_converse.api.connection.get()._dataRecv(mock.createRequest(stanza));

const blocklist = await api.waitUntil('blocklistInitialized');
expect(blocklist.length).toBe(2);
expect(blocklist.models.map((m) => m.get('jid'))).toEqual(['iago@shakespeare.lit', 'juliet@capulet.lit']);
})
);

it(
'is updated when the server sends IQ stanzas',
mock.initConverse(['discoInitialized'], {}, async function (_converse) {
const { api } = _converse;
await mock.waitUntilDiscoConfirmed(
_converse,
_converse.domain,
[{ 'category': 'server', 'type': 'IM' }],
['urn:xmpp:blocking']
);
await mock.waitForRoster(_converse, 'current', 0);

const IQ_stanzas = _converse.api.connection.get().IQ_stanzas;
const sent_stanza = await u.waitUntil(() => IQ_stanzas.find((s) => s.querySelector('iq blocklist')));

const stanza = stx`
<iq xmlns="jabber:client"
to="${_converse.api.connection.get().jid}"
type="result"
id="${sent_stanza.getAttribute('id')}">
<blocklist xmlns='urn:xmpp:blocking'>
<item jid='iago@shakespeare.lit'/>
</blocklist>
</iq>`;
_converse.api.connection.get()._dataRecv(mock.createRequest(stanza));

const blocklist = await api.waitUntil('blocklistInitialized');
expect(blocklist.length).toBe(1);

// The server sends a push IQ stanza
_converse.api.connection.get()._dataRecv(
mock.createRequest(
stx`
<iq xmlns="jabber:client"
to="${_converse.api.connection.get().jid}"
type="set"
id="${u.getUniqueId()}">
<block xmlns='urn:xmpp:blocking'>
<item jid='juliet@capulet.lit'/>
</block>
</iq>`
)
);
await u.waitUntil(() => blocklist.length === 2);
expect(blocklist.models.map((m) => m.get('jid'))).toEqual(['iago@shakespeare.lit', 'juliet@capulet.lit']);
})
);
});
8 changes: 0 additions & 8 deletions src/headless/plugins/disco/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -382,14 +382,6 @@ export default {
return entity.waitUntilFeaturesDiscovered;
},

/**
* @deprecated Use {@link api.disco.refresh} instead.
* @method api.disco.refreshFeatures
*/
refreshFeatures (jid) {
return api.refresh(jid);
},

/**
* Return all the features associated with a disco entity
*
Expand Down
2 changes: 1 addition & 1 deletion src/headless/plugins/disco/entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class DiscoEntity extends Model {
*/
async getFeature (feature) {
await this.waitUntilFeaturesDiscovered;
if (this.features.findWhere({ 'var': feature })) {
if (this.features.findWhere({ var: feature })) {
return this;
}
}
Expand Down
Loading

0 comments on commit f5aa730

Please sign in to comment.