Skip to content

Instantly share code, notes, and snippets.

@zackster
Created January 31, 2020 16:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zackster/483b0269ac95392277735de6fc266e77 to your computer and use it in GitHub Desktop.
Save zackster/483b0269ac95392277735de6fc266e77 to your computer and use it in GitHub Desktop.
Setting up spectron to work with multiple loading windows
/* eslint-disable no-param-reassign */
const { default: PQueue } = require('p-queue');
const clc = require('cli-color');
const electronPath = require('electron'); // Require Electron from the binaries included in node_modules.
const { Application } = require('spectron');
const path = require('path');
const { execSync } = require('child_process');
async function waitForWindowsChange(browser) {
const handles0 = await browser.windowHandles().then((h) => h.value);
const ch0 = handles0.sort().toString();
console.log('initial handles0', handles0.toString());
let handles = [];
await browser.waitUntil(async () => {
handles = await browser.windowHandles().then((h) => h.value);
const ch = handles.sort().toString();
const res = ch !== ch0;
if (res) {
console.log('windows changed', ch);
} else {
console.log('waiting for windows change', ch);
}
return res;
}, 40 * 1000);
return { handles0, handles };
}
async function switchToMainWindow(browser, handles) {
let found = false;
const queue = new PQueue({ concurrency: 1 });
handles.forEach((h) => {
queue.add(async () => {
if (found) {
return;
}
await browser.window(h); // switch to window
const ch = (await browser.windowHandle()).value;
const url = (await browser.execute(() => window.location.href)).value;
if (
url.startsWith('devtools://') ||
url.startsWith('chrome-extension://') ||
url.endsWith('loading.html')
) {
console.log('not a main window', ch, url);
} else {
found = ch;
console.log('found it', found, url);
}
});
});
await new Promise((resolve, reject) => {
queue.onIdle().then(() => {
if (found) {
resolve();
} else {
reject(new Error("couldn't switch to main window"));
}
});
});
if (handles.length > 1) {
await browser.window(found); // switch to window
}
}
function logTime(msg, ...stuff) {
console.log(clc.yellow(msg), ...stuff.map((s) => clc.yellow(s)));
}
async function handleInitialWindows(t) {
const { browser } = t.context;
const { handles } = await waitForWindowsChange(browser);
t.context.timings.mainShown = new Date();
logTime(
'"loading" screen time where user sees "Please be patient" window: about',
`${t.context.timings.mainShown - t.context.timings.appStarted}ms`
);
await switchToMainWindow(browser, handles);
t.context.timings.switchedToMain = new Date();
logTime(
'switch to main win time: about',
`${t.context.timings.switchedToMain - t.context.timings.mainShown}ms`
);
}
function commonSetup(test) {
test.beforeEach(async (t) => {
t.context.app = new Application({
path: electronPath,
args: [path.join(__dirname, '..')],
env: {
ELECTRON_ENABLE_LOGGING: true,
ELECTRON_ENABLE_STACK_DUMPING: true,
NODE_ENV: 'development',
USE_TEST_DATA: '1'
},
waitTimeout: 10e3,
chromeDriverLogPath: '../chromedriverlog.txt'
});
console.log('beforeEach almost complete');
t.context.timings = { start: new Date() };
await t.context.app.start();
t.context.timings.appStarted = new Date();
logTime(
'Time to start app: about',
`${t.context.timings.appStarted - t.context.timings.start}ms`
);
t.context.browser = t.context.app.client;
await handleInitialWindows(t);
});
test.afterEach.always(async (t) => {
await t.context.app.stop();
});
}
module.exports = { commonSetup, logTime };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment