Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #1677 #3584

Merged
merged 1 commit into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/headless/plugins/bookmarks/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const bookmarks = {
/**
* @method api.bookmarks.get
* @param {string} jid - The JID of the bookmark to return.
* @returns {Promise<import('./model').default>}
* @returns {Promise<import('./model').default|undefined>}
*/
async get(jid) {
const bookmarks = await waitUntil('bookmarksInitialized');
Expand Down
22 changes: 12 additions & 10 deletions src/headless/plugins/bookmarks/collection.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Bookmark from './model.js';
import _converse from '../../shared/_converse.js';
import api from '../../shared/api/index.js';
import converse from '../../shared/api/public.js';
import { parseErrorStanza } from '../../shared/parsers.js';
import log from '../../log.js';
import { initStorage } from '../../utils/storage.js';
import { parseStanzaForBookmarks } from './parsers.js';
Expand Down Expand Up @@ -262,29 +263,30 @@ class Bookmarks extends Collection {
* @param {Object} deferred
* @param {Element} iq
*/
onBookmarksReceivedError(deferred, iq) {
const { __ } = _converse;
async onBookmarksReceivedError(deferred, iq) {
if (iq === null) {
const { __ } = _converse;
log.error('Error: timeout while fetching bookmarks');
api.alert('error', __('Timeout Error'), [
__(
'The server did not return your bookmarks within the allowed time. ' +
'You can reload the page to request them again.'
),
]);
} else if (deferred) {
if (iq.querySelector('error[type="cancel"] item-not-found')) {
deferred?.reject(new Error('Could not fetch bookmarks'));

} else {
const { errors } = converse.env;
const e = await parseErrorStanza(iq);
if (e instanceof errors.ItemNotFoundError) {
// Not an exception, the user simply doesn't have any bookmarks.
window.sessionStorage.setItem(this.fetched_flag, 'true');
return deferred.resolve();
deferred?.resolve();
} else {
log.error('Error while fetching bookmarks');
log.error(iq);
return deferred.reject(new Error('Could not fetch bookmarks'));
if (iq) log.error(iq);
deferred?.reject(new Error('Could not fetch bookmarks'));
}
} else {
log.error('Error while fetching bookmarks');
log.error(iq);
}
}

Expand Down
35 changes: 35 additions & 0 deletions src/headless/plugins/bookmarks/tests/bookmarks.js
Original file line number Diff line number Diff line change
Expand Up @@ -443,4 +443,39 @@ describe("A bookmark", function () {
</pubsub>
</iq>`);
}));

it("handles missing bookmarks gracefully when server responds with item-not-found", mock.initConverse(
['chatBoxesFetched'], {}, async (_converse) => {

await mock.waitForRoster(_converse, 'current', 0);
await mock.waitUntilDiscoConfirmed(
_converse, _converse.bare_jid,
[{'category': 'pubsub', 'type': 'pep'}],
['http://jabber.org/protocol/pubsub#publish-options', 'urn:xmpp:bookmarks:1#compat']
);

const IQ_stanzas = _converse.api.connection.get().IQ_stanzas;
const sent_stanza = await u.waitUntil(
() => IQ_stanzas.filter(s => sizzle(`items[node="urn:xmpp:bookmarks:1"]`, s).length).pop());

// Simulate server response with item-not-found error
const error_stanza = stx`
<iq xmlns="jabber:client" type="error"
id="${sent_stanza.getAttribute('id')}"
from="${sent_stanza.getAttribute('to')}"
to="${sent_stanza.getAttribute('from')}">
<pubsub xmlns="http://jabber.org/protocol/pubsub">
<items node="urn:xmpp:bookmarks:1"/>
</pubsub>
<error code="404" type="cancel">
<item-not-found xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
</error>
</iq>`;
_converse.api.connection.get()._dataRecv(mock.createRequest(error_stanza));

const cache_key = `[email protected]`;
const result = await u.waitUntil(() => window.sessionStorage.getItem(cache_key));
expect(result).toBe('true');
})
);
});
10 changes: 5 additions & 5 deletions src/headless/plugins/pubsub/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export default {
config: {
/**
* Fetches the configuration for a PubSub node
* @method _converse.api.pubsub.configure
* @method _converse.api.pubsub.config.get
* @param {string} jid - The JID of the pubsub service where the node resides
* @param {string} node - The node to configure
* @returns {Promise<import('./types').PubSubConfigOptions>}
Expand Down Expand Up @@ -56,7 +56,7 @@ export default {

/**
* Configures a PubSub node
* @method _converse.api.pubsub.configure
* @method _converse.api.pubsub.config.set
* @param {string} jid The JID of the pubsub service where the node resides
* @param {string} node The node to configure
* @param {PubSubConfigOptions} config The configuration options
Expand Down Expand Up @@ -99,7 +99,7 @@ export default {
},

/**
* Publshes an item to a PubSub node
* Publishes an item to a PubSub node
* @method _converse.api.pubsub.publish
* @param {string} jid The JID of the pubsub service where the node resides.
* @param {string} node The node being published to
Expand All @@ -113,8 +113,8 @@ export default {
* @returns {Promise<void|Element>}
*/
async publish(jid, node, item, options, strict_options = true) {
if (!node) throw new Error('api.pubsub.config.publish: node value required');
if (!item) throw new Error('api.pubsub.config.publish: item value required');
if (!node) throw new Error('api.pubsub.publish: node value required');
if (!item) throw new Error('api.pubsub.publish: item value required');

const bare_jid = _converse.session.get('bare_jid');
const entity_jid = jid || bare_jid;
Expand Down
4 changes: 2 additions & 2 deletions src/headless/types/plugins/bookmarks/api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ declare namespace bookmarks {
/**
* @method api.bookmarks.get
* @param {string} jid - The JID of the bookmark to return.
* @returns {Promise<import('./model').default>}
* @returns {Promise<import('./model').default|undefined>}
*/
function get(jid: string): Promise<import("./model").default>;
function get(jid: string): Promise<import("./model").default | undefined>;
}
//# sourceMappingURL=api.d.ts.map
2 changes: 1 addition & 1 deletion src/headless/types/plugins/bookmarks/collection.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ declare class Bookmarks extends Collection {
* @param {Object} deferred
* @param {Element} iq
*/
onBookmarksReceivedError(deferred: any, iq: Element): any;
onBookmarksReceivedError(deferred: any, iq: Element): Promise<void>;
getUnopenedBookmarks(): Promise<any>;
}
import { Collection } from '@converse/skeletor';
Expand Down
6 changes: 3 additions & 3 deletions src/headless/types/plugins/pubsub/api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ declare namespace _default {
namespace config {
/**
* Fetches the configuration for a PubSub node
* @method _converse.api.pubsub.configure
* @method _converse.api.pubsub.config.get
* @param {string} jid - The JID of the pubsub service where the node resides
* @param {string} node - The node to configure
* @returns {Promise<import('./types').PubSubConfigOptions>}
*/
function get(jid: string, node: string): Promise<import("./types").PubSubConfigOptions>;
/**
* Configures a PubSub node
* @method _converse.api.pubsub.configure
* @method _converse.api.pubsub.config.set
* @param {string} jid The JID of the pubsub service where the node resides
* @param {string} node The node to configure
* @param {PubSubConfigOptions} config The configuration options
Expand All @@ -20,7 +20,7 @@ declare namespace _default {
function set(jid: string, node: string, config: import("./types").PubSubConfigOptions): Promise<import("./types").PubSubConfigOptions>;
}
/**
* Publshes an item to a PubSub node
* Publishes an item to a PubSub node
* @method _converse.api.pubsub.publish
* @param {string} jid The JID of the pubsub service where the node resides.
* @param {string} node The node being published to
Expand Down
16 changes: 8 additions & 8 deletions src/shared/tests/mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -737,14 +737,14 @@ function getMockVcardFetcher (settings) {
const vcard_el = vcard.tree();

return {
'stanza': vcard_el,
'fullname': vcard_el.querySelector('FN')?.textContent,
'nickname': vcard_el.querySelector('NICKNAME')?.textContent,
'image': vcard_el.querySelector('PHOTO BINVAL')?.textContent,
'image_type': vcard_el.querySelector('PHOTO TYPE')?.textContent,
'url': vcard_el.querySelector('URL')?.textContent,
'vcard_updated': dayjs().format(),
'vcard_error': undefined
stanza: vcard_el,
fullname: vcard_el.querySelector('FN')?.textContent,
nickname: vcard_el.querySelector('NICKNAME')?.textContent,
image: vcard_el.querySelector('PHOTO BINVAL')?.textContent,
image_type: vcard_el.querySelector('PHOTO TYPE')?.textContent,
url: vcard_el.querySelector('URL')?.textContent,
vcard_updated: dayjs().format(),
vcard_error: undefined
};
}
}
Expand Down
Loading