diff options
Diffstat (limited to 'testing/web-platform/tests/speculation-rules/prerender/resources/deferred-promise-utils.js')
-rw-r--r-- | testing/web-platform/tests/speculation-rules/prerender/resources/deferred-promise-utils.js | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/testing/web-platform/tests/speculation-rules/prerender/resources/deferred-promise-utils.js b/testing/web-platform/tests/speculation-rules/prerender/resources/deferred-promise-utils.js new file mode 100644 index 0000000000..19bc981a2a --- /dev/null +++ b/testing/web-platform/tests/speculation-rules/prerender/resources/deferred-promise-utils.js @@ -0,0 +1,74 @@ +/** + * This file co-works with a html file and utils.js to test a promise that + * should be deferred during prerendering. + * + * Usage example: + * Suppose the html is "prerender-promise-test.html" + * On prerendering page, prerender-promise-test.html?prerendering: + * const prerenderEventCollector = new PrerenderEventCollector(); + * const promise = {a promise that should be deferred during prerendering}; + * prerenderEventCollector.start(promise, {promise name}); + * + * On the initiator page, prerender-promise-test.html: + * execute + * `loadInitiatorPage();` + */ + +// Collects events that happen relevant to a prerendering page. +// An event is added when: +// 1. start() is called. +// 2. a prerenderingchange event is dispatched on this document. +// 3. the promise passed to start() is resolved. +// 4. addEvent() is called manually. +class PrerenderEventCollector { + constructor() { + this.eventsSeen_ = []; + new PrerenderChannel('close').addEventListener('message', () => { + window.close(); + }); + } + + // Adds an event to `eventsSeen_` along with the prerendering state of the + // page. + addEvent(eventMessage) { + this.eventsSeen_.push( + {event: eventMessage, prerendering: document.prerendering}); + } + + // Starts collecting events until the promise resolves. Triggers activation by + // telling the initiator page that it is ready for activation. + async start(promise, promiseName) { + assert_true(document.prerendering); + this.addEvent(`started waiting ${promiseName}`); + promise + .then( + () => { + this.addEvent(`finished waiting ${promiseName}`); + }, + (error) => { + if (error instanceof Error) + error = error.name; + this.addEvent(`${promiseName} rejected: ${error}`); + }) + .finally(() => { + // Used to communicate with the main test page. + const testChannel = new PrerenderChannel('test-channel'); + // Send the observed events back to the main test page. + testChannel.postMessage(this.eventsSeen_); + testChannel.close(); + }); + document.addEventListener('prerenderingchange', () => { + this.addEvent('prerendering change'); + }); + + // Post a task to give the implementation a chance to fail in case it + // resolves a promise without waiting for activation. + setTimeout(() => { + // Used to communicate with the initiator page. + const prerenderChannel = new PrerenderChannel('prerender-channel'); + // Inform the initiator page that this page is ready to be activated. + prerenderChannel.postMessage('readyToActivate'); + prerenderChannel.close(); + }, 0); + } +} |