Skip to content

Commit

Permalink
Use iframes instead of tabs (#2928)
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffposnick committed Aug 25, 2021
1 parent 16fa3de commit 2b4e88b
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 118 deletions.
75 changes: 75 additions & 0 deletions infra/testing/webdriver/IframeManager.js
@@ -0,0 +1,75 @@
/*
Copyright 2021 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/

const PREFIX = 'iframe-';
const waitUntil = require('../wait-until');

class Client {
constructor(driver, id) {
this._driver = driver;
this._id = id;
}

async executeAsyncScript(code) {
const value = await this._driver.executeAsyncScript((id, code, cb) => {
const iframe = document.querySelector(`#${id}`);
Promise.resolve(iframe.contentWindow.eval(code))
.then((value) => cb(value))
.catch((err) => cb(err.toString()));
}, this._id, code);

return value;
}

async wait(code) {
await waitUntil(() => this.executeAsyncScript(code));
}

remove() {
this._driver.executeScript((id) => {
const el = document.querySelector(`#${id}`);
document.body.removeChild(el);
}, this._id);
}
}

/**
* Wraps methods in the underlying webdriver API to create, switch between,
* and close tabs in a browser.
*/
class IframeManager {
/**
* @param {WebDriver} driver
*
* @private
*/
constructor(driver) {
this._driver = driver;
this._clients = new Set();
}

async createIframeClient(url) {
const iframeId = await this._driver.executeAsyncScript((url, prefix, cb) => {
const el = document.createElement('iframe');
if (!('iframeCount' in window)) {
window.iframeCount = 1;
}
const id = `${prefix}${window.iframeCount++}`;
el.addEventListener('load', () => {
cb(id);
});
el.src = url;
el.id = id;
document.body.appendChild(el);
}, url, PREFIX);

return new Client(this._driver, iframeId);
}
}

module.exports = {IframeManager};
49 changes: 0 additions & 49 deletions infra/testing/webdriver/TabManager.js

This file was deleted.

47 changes: 10 additions & 37 deletions test/workbox-broadcast-update/integration/test-all.js
Expand Up @@ -9,13 +9,13 @@
const expect = require('chai').expect;

const {runUnitTests} = require('../../../infra/testing/webdriver/runUnitTests');
const {TabManager} = require('../../../infra/testing/webdriver/TabManager');
const {IframeManager} = require('../../../infra/testing/webdriver/IframeManager');
const activateAndControlSW = require('../../../infra/testing/activate-and-control');
const cleanSWEnv = require('../../../infra/testing/clean-sw');
const templateData = require('../../../infra/testing/server/template-data');

// Store local references of these globals.
const {webdriver, server, seleniumBrowser} = global.__workbox;
const {webdriver, server} = global.__workbox;

describe(`[workbox-broadcast-update]`, function() {
it(`passes all SW unit tests`, async function() {
Expand Down Expand Up @@ -122,13 +122,7 @@ describe(`[workbox-broadcast-update] Plugin`, function() {
});

it(`should broadcast a message to all open window clients by default`, async function() {
// This test doesn't work in Safari:
// https://github.com/GoogleChrome/workbox/issues/2755
if (seleniumBrowser.getId() === 'safari') {
this.skip();
}

const tabManager = new TabManager(webdriver);
const iframeManager = new IframeManager(webdriver);

templateData.assign({
title: 'Broadcast Cache Update Test',
Expand All @@ -152,15 +146,11 @@ describe(`[workbox-broadcast-update] Plugin`, function() {
}, dynamicPageURL);
});

// Update the template data, then open a new tab to trigger the update.
// Update the template data and open an iframe to trigger the cache update.
templateData.assign({
body: 'Third test, with an updated body.',
});

await tabManager.openTab(dynamicPageURL);

// Go back to the initial tab to assert the message was received there.
await tabManager.closeOpenedTabs();
await iframeManager.createIframeClient(dynamicPageURL);

await webdriver.wait(() => {
return webdriver.executeScript(() => {
Expand All @@ -183,34 +173,19 @@ describe(`[workbox-broadcast-update] Plugin`, function() {
});

it(`should only broadcast a message to the client that made the request when notifyAllClients is false`, async function() {
// This test doesn't work in Safari:
// https://github.com/GoogleChrome/workbox/issues/2755
if (seleniumBrowser.getId() === 'safari') {
this.skip();
}

const url = `${apiURL}?notifyAllClientsTest`;
const tabManager = new TabManager(webdriver);
const iframeManager = new IframeManager(webdriver);

await webdriver.get(testingURL);
await webdriver.executeAsyncScript((url, cb) => {
fetch(url).then(() => cb()).catch((err) => cb(err.message));
}, url);

await tabManager.openTab(testingURL);
await webdriver.executeAsyncScript((url, cb) => {
fetch(url).then(() => cb()).catch((err) => cb(err.message));
}, url);

await webdriver.wait(() => {
return webdriver.executeScript(() => {
return window.__messages.length > 0;
});
});
const iframeClient = await iframeManager.createIframeClient(testingURL);
await iframeClient.executeAsyncScript(`fetch(${JSON.stringify(url)})`);
await iframeClient.wait('window.__messages.length > 0');

const populatedMessages = await webdriver.executeScript(() => {
return window.__messages;
});
const populatedMessages = await iframeClient.executeAsyncScript('window.__messages');
expect(populatedMessages).to.eql([{
type: 'CACHE_UPDATED',
meta: 'workbox-broadcast-update',
Expand All @@ -220,8 +195,6 @@ describe(`[workbox-broadcast-update] Plugin`, function() {
},
}]);

await tabManager.closeOpenedTabs();

const unpopulatedMessages = await webdriver.executeScript(() => {
return window.__messages;
});
Expand Down
44 changes: 12 additions & 32 deletions test/workbox-window/integration/test-all.js
Expand Up @@ -10,13 +10,13 @@ const {expect} = require('chai');

const {executeAsyncAndCatch} = require('../../../infra/testing/webdriver/executeAsyncAndCatch');
const {runUnitTests} = require('../../../infra/testing/webdriver/runUnitTests');
const {TabManager} = require('../../../infra/testing/webdriver/TabManager');
const {IframeManager} = require('../../../infra/testing/webdriver/IframeManager');
const {unregisterAllSWs} = require('../../../infra/testing/webdriver/unregisterAllSWs');
const {windowLoaded} = require('../../../infra/testing/webdriver/windowLoaded');
const templateData = require('../../../infra/testing/server/template-data');

// Store local references of these globals.
const {webdriver, server, seleniumBrowser} = global.__workbox;
const {webdriver, server} = global.__workbox;

const testServerOrigin = server.getAddress();
const testPath = `${testServerOrigin}/test/workbox-window/static/`;
Expand Down Expand Up @@ -160,14 +160,7 @@ describe(`[workbox-window] Workbox`, function() {
});

it(`reports all events for an external SW registration`, async function() {
// This test doesn't work in Safari or Firefox:
// https://github.com/GoogleChrome/workbox/issues/2755
if (seleniumBrowser.getId() === 'safari' ||
seleniumBrowser.getId() === 'firefox') {
this.skip();
}

const tabManager = new TabManager(webdriver);
const iframeManager = new IframeManager(webdriver);

await executeAsyncAndCatch(async (cb) => {
try {
Expand Down Expand Up @@ -200,30 +193,17 @@ describe(`[workbox-window] Workbox`, function() {
// Update the version in sw.js to trigger a new installation.
templateData.assign({version: '2'});

const secondTabPath = `${testPath}?second`;
await tabManager.openTab(secondTabPath);
await windowLoaded();

const location = await executeAsyncAndCatch(async (cb) => {
try {
const wb = new Workbox('sw-clients-claim.js.njk');

await wb.register();

// Resolve this execution block once the updated SW is in control.
await window.activatedAndControlling(wb);
cb(location.href);
} catch (error) {
cb({error: error.stack});
}
});
const secondPath = `${testPath}?second`;
const iframeClient = await iframeManager.createIframeClient(secondPath);
const location = await iframeClient.executeAsyncScript(`
const wb = new Workbox('sw-clients-claim.js.njk');
wb.register()
.then(() => window.activatedAndControlling(wb))
.then(() => location.href);
`);

// Just confirm we're operating on the page we expect.
expect(location).to.eql(secondTabPath);

// Close the second tab and switch back to the first tab before
// executing the following block.
await tabManager.closeOpenedTabs();
expect(location).to.eql(secondPath);

const result = await executeAsyncAndCatch(async (cb) => {
cb({
Expand Down

0 comments on commit 2b4e88b

Please sign in to comment.