Skip to content

Instantly share code, notes, and snippets.

@heyMP
Last active May 24, 2024 16:26
Show Gist options
  • Save heyMP/d38b9b5378032a27efcc455d88a5fc2a to your computer and use it in GitHub Desktop.
Save heyMP/d38b9b5378032a27efcc455d88a5fc2a to your computer and use it in GitHub Desktop.
Playwright stream events from browser.
/**
* An async queue that can stream existing values
* and stream new values as they are added using
* async generators and async iterators.
*
* @example
*
* const counter = new AsyncQueue<number>();
* counter.add(1);
* counter.add(2);
* counter.add(3);
* setTimeout(() => counter.add(4), 1000);
* for await (const value of counter) {
* console.log(value);
* if (value === 4) break;
* }
*/
export class AsyncQueue<T> extends EventTarget {
queue: T[] = [];
abortController = new AbortController();
constructor(initialValue?: T[]) {
super();
if (initialValue) {
this.queue = initialValue;
}
}
/**
* @param value
*/
add(value: T) {
this.queue.push(value);
this.dispatchEvent(new CustomEvent('updated', {detail: value}));
}
dispose() {
this.abortController.abort();
}
/**
* Async generator that yields the current value of the Signal and waits for the next update
*
* @example
* for await (const value of queue.stream()) {
* }
*/
async *stream() {
for (const i of this.queue) {
yield i;
}
while (true) {
yield new Promise((resolve) =>
this.addEventListener('updated', (e) => {
if (!(e instanceof CustomEvent)) return;
resolve(e.detail);
}, {once: true, signal: this.abortController.signal}),
);
}
}
/**
* Async iterator that yields the current value
*
* @example
* for await (const value of queue) {
* }
*/
[Symbol.asyncIterator]() {
return this.stream();
}
}
import {BrowserContext, Page} from '@playwright/test';
import { AsyncQueue } from './AsyncQueue'
export async function monitorOidcManagerEvents(page: Page) {
const oidcEventQueue = new AsyncQueue<CustomEvent>();
const callback = (e: CustomEvent) => {
oidcEventQueue.add(e);
};
await page.exposeFunction('oidcEventQueue', callback);
await page.addInitScript(async () => {
window.addEventListener('oidc-manager-registered', () => {
console.log('oidc-manager-registered');
window.oidcManager.addEventListener('message', (e: any) => {
// @ts-ignore
window.oidcManagerEvents = window.oidcManagerEvents || [];
// @ts-ignore
window.oidcEventQueue(e);
});
});
});
return oidcEventQueue;
}
import {Page, expect, test} from '@playwright/test';
import {
monitorOidcManagerEvents,
} from './helpers';
test('verify login_required event is published', async ({page,context}) => {
const oidcEventQueue = await monitorOidcManagerEvents(page);
const oidcEventLoginEvent = await waitForOidcManagerEvent(page, (e) =>
e?.detail?.error?.includes?.('login_required')
);
await page.goto('https://www.redhat.com/en');
expect(await oidcEventLoginEvent.promise).toBeTruthy();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment