converse.js
Version:
Browser based XMPP chat client
335 lines (300 loc) • 15.2 kB
JavaScript
describe('An incoming presence with a XEP-0153 vcard:update element', function () {
beforeAll(() => jasmine.addMatchers({ toEqualStanza: jasmine.toEqualStanza }));
it(
'will cause a VCard avatar to be replaced',
mock.initConverse(['chatBoxesFetched'], { no_vcard_mocks: true }, async function (_converse) {
const { api } = _converse;
const { u, sizzle } = _converse.env;
await mock.waitForRoster(_converse, 'current', 1);
mock.openControlBox(_converse);
const contact_jid = mock.cur_names[0].replace(/ /g, '.').toLowerCase() + '@montague.lit';
const IQ_stanzas = _converse.api.connection.get().IQ_stanzas;
while (IQ_stanzas.length) IQ_stanzas.pop();
_converse.api.connection.get()._dataRecv(
mock.createRequest(
stx`<presence xmlns="jabber:client"
to="${_converse.session.get('jid')}"
from="${contact_jid}/resource">
<x xmlns='vcard-temp:x:update'>
<photo>01b87fcd030b72895ff8e88db57ec525450f000d</photo>
</x>
</presence>`
)
);
const sent_stanza = await u.waitUntil(
() => IQ_stanzas.filter((s) => sizzle('vCard', s).length).pop(),
1000
);
expect(sent_stanza).toEqualStanza(stx`
<iq type="get"
to="mercutio@montague.lit"
xmlns="jabber:client"
id="${sent_stanza.getAttribute('id')}">
<vCard xmlns="vcard-temp"/>
</iq>`);
const response = await fetch('/base/logo/conversejs-filled-192.png');
const blob = await response.blob();
const arrayBuffer = await blob.arrayBuffer();
const byteArray = new Uint8Array(arrayBuffer);
const base64Image = btoa(String.fromCharCode(...byteArray));
_converse.api.connection.get()._dataRecv(
mock.createRequest(stx`
<iq from='${contact_jid}'
xmlns="jabber:client"
to='${_converse.session.get('jid')}'
type='result'
id='${sent_stanza.getAttribute('id')}'>
<vCard xmlns='vcard-temp'>
<BDAY>1476-06-09</BDAY>
<ADR>
<CTRY>Italy</CTRY>
<LOCALITY>Verona</LOCALITY>
<HOME/>
</ADR>
<NICKNAME/>
<N><GIVEN>Mercutio</GIVEN><FAMILY>Capulet</FAMILY></N>
<EMAIL><USERID>mercutio@shakespeare.lit</USERID></EMAIL>
<PHOTO>
<TYPE>${blob.type}</TYPE>
<BINVAL>${base64Image}</BINVAL>
</PHOTO>
</vCard>
</iq>`)
);
const { vcard } = await api.contacts.get(contact_jid);
await u.waitUntil(() => vcard.get('image_hash') === '6d52ba485d3fd69c96b8d424ceaf8082a7a00e51');
while (IQ_stanzas.length) IQ_stanzas.pop();
_converse.api.connection.get()._dataRecv(
mock.createRequest(
stx`<presence xmlns="jabber:client"
to="${_converse.session.get('jid')}"
from="${contact_jid}/resource">
<x xmlns='vcard-temp:x:update'>
<photo>6d52ba485d3fd69c96b8d424ceaf8082a7a00e51</photo>
</x>
</presence>`
)
);
return new Promise((resolve) => {
setTimeout(() => {
expect(IQ_stanzas.filter((s) => sizzle('vCard', s).length).length).toBe(0);
resolve();
}, 251);
});
})
);
it(
'will cause a VCard avatar to be removed',
mock.initConverse(['chatBoxesFetched'], { no_vcard_mocks: true }, async function (_converse) {
const { api } = _converse;
const { u, sizzle } = _converse.env;
await mock.waitForRoster(_converse, 'current', 1);
mock.openControlBox(_converse);
const contact_jid = mock.cur_names[0].replace(/ /g, '.').toLowerCase() + '@montague.lit';
const own_jid = _converse.session.get('jid');
const IQ_stanzas = _converse.api.connection.get().IQ_stanzas;
let sent_stanza = await u.waitUntil(() => IQ_stanzas.filter((s) => sizzle(`vCard`, s).length).pop(), 500);
_converse.api.connection.get()._dataRecv(
mock.createRequest(stx`
<iq from='${own_jid}'
xmlns="jabber:client"
to='${_converse.session.get('jid')}'
type='result'
id='${sent_stanza.getAttribute('id')}'>
<vCard xmlns='vcard-temp'></vCard>
</iq>`)
);
sent_stanza = await u.waitUntil(() =>
IQ_stanzas.filter((s) => sizzle(`iq[to="${contact_jid}"] vCard`, s).length).pop()
);
expect(sent_stanza).toEqualStanza(stx`
<iq type="get"
to="mercutio@montague.lit"
xmlns="jabber:client"
id="${sent_stanza.getAttribute('id')}">
<vCard xmlns="vcard-temp"/>
</iq>`);
const response = await fetch('/base/logo/conversejs-filled-192.png');
const blob = await response.blob();
const arrayBuffer = await blob.arrayBuffer();
const byteArray = new Uint8Array(arrayBuffer);
const base64Image = btoa(String.fromCharCode(...byteArray));
_converse.api.connection.get()._dataRecv(
mock.createRequest(stx`
<iq from='${contact_jid}'
xmlns="jabber:client"
to='${_converse.session.get('jid')}'
type='result'
id='${sent_stanza.getAttribute('id')}'>
<vCard xmlns='vcard-temp'>
<BDAY>1476-06-09</BDAY>
<CTRY>Italy</CTRY>
<LOCALITY>Verona</LOCALITY>
<N><GIVEN>Mercutio</GIVEN><FAMILY>Capulet</FAMILY></N>
<EMAIL><USERID>mercutio@shakespeare.lit</USERID></EMAIL>
<PHOTO>
<TYPE>${blob.type}</TYPE>
<BINVAL>${base64Image}</BINVAL>
</PHOTO>
</vCard>
</iq>`)
);
const contact = await api.contacts.get(contact_jid);
await u.waitUntil(() => contact.vcard.get('image'));
expect(contact.vcard.get('image')).toEqual(base64Image);
while (IQ_stanzas.length) IQ_stanzas.pop();
_converse.api.connection.get()._dataRecv(
mock.createRequest(
stx`<presence xmlns="jabber:client"
to="${_converse.session.get('jid')}"
from="${contact_jid}/resource">
<x xmlns='vcard-temp:x:update'>
<photo></photo>
</x>
</presence>`
)
);
sent_stanza = await u.waitUntil(() => IQ_stanzas.filter((s) => sizzle('vCard', s).length).pop(), 500);
expect(sent_stanza).toEqualStanza(stx`
<iq type="get"
to="mercutio@montague.lit"
xmlns="jabber:client"
id="${sent_stanza.getAttribute('id')}">
<vCard xmlns="vcard-temp"/>
</iq>`);
_converse.api.connection.get()._dataRecv(
mock.createRequest(stx`
<iq from='${contact_jid}'
xmlns="jabber:client"
to='${_converse.session.get('jid')}'
type='result'
id='${sent_stanza.getAttribute('id')}'>
<vCard xmlns='vcard-temp'>
<BDAY>1476-06-09</BDAY>
<CTRY>Italy</CTRY>
<LOCALITY>Verona</LOCALITY>
<N><GIVEN>Mercutio</GIVEN><FAMILY>Capulet</FAMILY></N>
<EMAIL><USERID>mercutio@shakespeare.lit</USERID></EMAIL>
<PHOTO></PHOTO>
</vCard>
</iq>`)
);
await u.waitUntil(() => !contact.vcard.get('image'));
expect(contact.vcard.get('image_hash')).toBeUndefined();
})
);
});
describe('An outgoing presence with a XEP-0153 vcard:update element', function () {
beforeAll(() => jasmine.addMatchers({ toEqualStanza: jasmine.toEqualStanza }));
it(
'is sent when the user updates their VCard avatar',
mock.initConverse(['chatBoxesFetched'], { no_vcard_mocks: true }, async function (_converse) {
const { api } = _converse;
const { u, sizzle } = _converse.env;
await mock.waitForRoster(_converse, 'current', 0);
mock.openControlBox(_converse);
const own_jid = _converse.session.get('jid');
const own_bare_jid = _converse.session.get('bare_jid');
const IQ_stanzas = _converse.api.connection.get().IQ_stanzas;
let sent_stanza = await u.waitUntil(() => IQ_stanzas.filter((s) => sizzle(`vCard`, s).length).pop(), 500);
_converse.api.connection.get()._dataRecv(
mock.createRequest(stx`
<iq from='${own_jid}'
xmlns="jabber:client"
to='${_converse.session.get('jid')}'
type='result'
id='${sent_stanza.getAttribute('id')}'>
<vCard xmlns='vcard-temp'></vCard>
</iq>`)
);
const vcard = await u.waitUntil(() => _converse.state.vcards.get(own_bare_jid));
expect(vcard.get('image_hash')).not.toBeDefined();
const vcard_updated = await u.waitUntil(() => vcard.get('vcard_updated'));
while (IQ_stanzas.length) IQ_stanzas.pop();
const response = await fetch('/base/logo/conversejs-filled-192.png');
const blob = await response.blob();
const arrayBuffer = await blob.arrayBuffer();
const byteArray = new Uint8Array(arrayBuffer);
const hash_ab = await crypto.subtle.digest('SHA-1', byteArray);
const image_hash = u.arrayBufferToHex(hash_ab);
const base64Image = btoa(String.fromCharCode(...byteArray));
// Call the API to set a new avatar
api.vcard.set(own_bare_jid, {
image: base64Image,
image_type: blob.type,
});
sent_stanza = await u.waitUntil(() => IQ_stanzas.filter((s) => sizzle(`vCard`, s).length).pop(), 500);
expect(sent_stanza).toEqualStanza(stx`
<iq type="set" to="${own_bare_jid}" xmlns="jabber:client" id="${sent_stanza.getAttribute('id')}">
<vCard xmlns="vcard-temp">
<FN/><NICKNAME/><URL/><ROLE/><EMAIL><INTERNET/><PREF/><USERID/></EMAIL><PHOTO><TYPE>image/png</TYPE>
<BINVAL>${base64Image}</BINVAL></PHOTO>
</vCard>
</iq>`);
// Check optimistic save
expect(vcard.get('image')).toBe(base64Image);
expect(vcard.get('image_hash')).toBe(image_hash);
expect(vcard.get('image_type')).toBe(blob.type);
expect(vcard.get('vcard_updated')).toBe(vcard_updated); // didn't change
while (IQ_stanzas.length) IQ_stanzas.pop();
// Some servers send their own update presence, before sending the
// return IQ. This should not create a new VCard get request
_converse.api.connection.get()._dataRecv(
mock.createRequest(
stx`<presence xmlns="jabber:client"
to="${_converse.session.get('jid')}"
from="${own_jid}">
<x xmlns='vcard-temp:x:update'>
<photo>${image_hash}</photo>
</x>
</presence>`
)
);
_converse.api.connection.get()._dataRecv(
mock.createRequest(stx`
<iq from='${own_bare_jid}'
xmlns="jabber:client"
to='${own_jid}'
type='result'
id='${sent_stanza.getAttribute('id')}'></iq>`)
);
// A new get IQ is sent out to fetch the latest VCard
sent_stanza = await u.waitUntil(
() => IQ_stanzas.filter((s) => sizzle('vCard', s).length).pop(),
1000
);
expect(sent_stanza).toEqualStanza(stx`
<iq type="get" xmlns="jabber:client" id="${sent_stanza.getAttribute('id')}">
<vCard xmlns="vcard-temp"/>
</iq>`);
_converse.api.connection.get()._dataRecv(
mock.createRequest(stx`
<iq from='${own_bare_jid}'
xmlns="jabber:client"
to='${own_jid}'
type='result'
id='${sent_stanza.getAttribute('id')}'>
<vCard xmlns='vcard-temp'>
<BDAY>1476-06-09</BDAY>
<ADR>
<CTRY>Italy</CTRY>
<LOCALITY>Verona</LOCALITY>
<HOME/>
</ADR>
<NICKNAME/>
<N><GIVEN>Romeo</GIVEN><FAMILY>Montague</FAMILY></N>
<EMAIL><USERID>romeo@shakespeare.lit</USERID></EMAIL>
<PHOTO>
<TYPE>${blob.type}</TYPE>
<BINVAL>${base64Image}</BINVAL>
</PHOTO>
</vCard>
</iq>`)
);
await u.waitUntil(() => vcard.get('vcard_updated'));
expect(vcard.get('image')).toBe(base64Image);
expect(vcard.get('image_hash')).toBe(image_hash);
expect(vcard.get('image_type')).toBe(blob.type);
})
);
});