zotero-better-notes/test/utils/wait.ts

97 lines
2.6 KiB
TypeScript

export async function waitNoMoreThan<T>(
promise: Promise<T>,
timeout: number = 3000,
message: string = "Timeout",
) {
let resolved = false;
return Promise.any([
promise.then((result) => {
resolved = true;
return result;
}),
Zotero.Promise.delay(timeout).then(() => {
if (resolved) return;
throw new Error(message);
}),
]);
}
export async function waitForNotifierEvent(
event: _ZoteroTypes.Notifier.Event,
type: _ZoteroTypes.Notifier.Type,
timeout: number = 3000,
) {
if (!event) throw new Error("event not provided");
let resolved = false;
return waitNoMoreThan(
new Promise((resolve, reject) => {
const notifierID = Zotero.Notifier.registerObserver(
{
notify: function (ev, type, ids, extraData) {
if (ev == event) {
Zotero.Notifier.unregisterObserver(notifierID);
resolved = true;
resolve({
ids: ids,
extraData: extraData,
});
}
},
},
[type],
"test",
101,
);
}),
timeout,
);
}
export function waitForTabSelectEvent(timeout: number = 3000) {
return waitForNotifierEvent("select", "tab", timeout);
}
/**
* Waits for a window with a specific URL to open. Returns a promise for the window, and
* optionally passes the window to a callback immediately for use with modal dialogs,
* which prevent async code from continuing
*/
export async function waitForWindow(uri: string, timeout: number = 3000) {
return waitNoMoreThan(
new Promise<Window>((resolve, reject) => {
const loadObserver = function (ev: Event) {
ev.originalTarget?.removeEventListener("load", loadObserver, false);
const href = (ev.target as Window)?.location.href;
Zotero.debug("Window opened: " + href);
if (href != uri) {
Zotero.debug(`Ignoring window ${href} in waitForWindow()`);
return;
}
Services.ww.unregisterNotification(winObserver);
const win = ev.target?.ownerGlobal;
// Give window code time to run on load
win?.setTimeout(function () {
resolve(win);
});
};
const winObserver = {
observe: function (subject: Window, topic: string, data: any) {
if (topic != "domwindowopened") return;
subject.addEventListener("load", loadObserver, false);
},
} as nsIObserver;
Services.ww.registerNotification(winObserver);
}),
timeout,
);
}
export async function waitForNoteWindow() {
return await waitForWindow("chrome://zotero/content/note.xhtml");
}