In [1]:
const {Builder} = require('selenium-webdriver');
const CRI = require('chrome-remote-interface'); // https://github.com/cyrus-and/chrome-remote-interface
In [ ]:
driver = new Builder().forBrowser('chrome').build();
In [ ]:
// https://bugs.chromium.org/p/chromedriver/issues/detail?id=878
driver.get('chrome://version');
var port;
driver.findElement({id: 'command_line'}).then(async (element) => {
const commandLine = await element.getText()
const commands = commandLine.split(' ');
const debuggerPort = commands.find((item) => item.startsWith('--remote-debugging-port'));
port = debuggerPort.replace('--remote-debugging-port=', '')
})
In [4]:
var devOptions = {"port": port};
In [ ]:
var sessions = [];
var loadingComplete = false;
CRI(devOptions, (client) => {
const {Network, Page, Target, Runtime} = client;
const disconnect = async () => {
if (loadingComplete && sessions.length > 2){
await Network.emulateNetworkConditions({
offline: true,
latency: 0,
downloadThroughput: 0,
uploadThroughput: 0,
connectionType: "none"
});
for (var session of sessions){
if (session.includes('sub')){
const values = session.split('sub');
console.log(`\n\n ${values[0]} - ${values[1]}`);
await Target.sendMessageToTarget({
message:`{
\"id\":410,
\"method\":\"Target.sendMessageToTarget\",
\"params\":{
\"message\":\"{
\\\"id\\\":12,
\\\"method\\\":\\\"Network.emulateNetworkConditions\\\",
\\\"params\\\":{
\\\"offline\\\":true,
\\\"latency\\\":0,
\\\"downloadThroughput\\\":0,
\\\"uploadThroughput\\\":0,
\\\"connectionType\\\":\\\"none\\\"
}
}\",
\"sessionId\":\"${values[1]}\"}}`,
"sessionId": values[0]
});
} else {
console.log(`\n\n ${session}\n\n`);
await Target.sendMessageToTarget({
"sessionId": session,
message: `{
"id":412,
"method":"Network.emulateNetworkConditions",
"params":{
"offline":true,
"latency":0,
"downloadThroughput":0,
"uploadThroughput":0,
"connectionType":"none"
}
}`
});
}
}
}
else {
console.log(`\n\n ${loadingComplete}, ${sessions} \n\n`)
}
};
Target.receivedMessageFromTarget(async (params) => {
if (params.message.startsWith('{"method":"Target.attachedToTarget"')) {
const message = JSON.parse(params.message);
const sessionId = message.params.sessionId;
sessions.push(`${params.sessionId}sub${sessionId}`);
disconnect();
console.log("\n\nFound the dedicated Worker: ", sessionId)
console.log(message.params, "\n\n")
} else {
console.log('receivedMessageFromTarget: =>', params)
}
});
Target.attachedToTarget(async (params) => {
const targetId = params.targetInfo.targetId;
const sessionId = params.sessionId;
sessions.push(sessionId);
const workerType = params.targetInfo.type;
const title = params.targetInfo.title;
console.log(`\n\n${sessionId}, ${workerType}, ${title}\n\n`);
disconnect();
if (workerType === 'service_worker' || workerType === 'worker') {
if (workerType === 'service_worker') swSessionId = sessionId;
await Target.sendMessageToTarget({
message:`{
"id":63,
"method":"Target.setAutoAttach",
"params":{
"autoAttach":true,
"waitForDebuggerOnStart":true
}
}`,
"sessionId": sessionId});
await Target.sendMessageToTarget({
message:`{"id":65,"method":"Runtime.runIfWaitingForDebugger"}`,
"sessionId": sessionId});
}
});
Promise.all([
Network.enable({"maxPostDataSize":65536}),
Page.enable()
]).then( async () => {
await Target.setAutoAttach({autoAttach:true, waitForDebuggerOnStart:true})
await Runtime.runIfWaitingForDebugger();
await driver.get('http://staging.com/myawesomeapp');
await driver.findElement({id: 'email'}).sendKeys(credentials.email);
await driver.findElement({id: "continue"}).click();
await driver.findElement({id: 'password'}).sendKeys(credentials.password);
await driver.findElement({css: 'button[value="signin"]'}).click();
// ... load the ServiceWorker here
loadingComplete = true;
disconnect();
}).catch((err) => {
console.error(`ERROR: ${err.message}`);
client.close();
});
}).on('error', (err) => {
console.error('Cannot connect to remote endpoint:', err);
});
In [ ]:
driver.quit();