[SOLVED] Control/automate an Electron application with Puppeteer?

Is it possible to use Puppeteer to control/automate/test an Electron application?

In other words, I have an app running in Electron, and I want to script user interactions on it.

This would be similar to using Spectron, but instead using Puppeteer.

Can it be done? Can Puppeteer be somehow attached to Electron’s underlying Chrome process?

Puppeteer is a Node library which provides a high-level API to control headless Chrome or Chromium over the DevTools Protocol. It can also be configured to use full (non-headless) Chrome or Chromium.

According to its documentation, it should be able to.

Yeah, seems possible. I haven’t found any examples or steps listed anywhere though. Gotta figure out how to connect it to Electron devtools. Hmmm…

Looks like this article shows how to connect Puppeteer to an existing Chrome window that has remote debugging enabled. https://medium.com/@jaredpotter1/connecting-puppeteer-to-existing-chrome-window-8a10828149e0

Mmm, and here’s how to pass the remote debugging option from Electron to Chrome, https://electronjs.org/docs/api/chrome-command-line-switches, then we should be able to connect Puppeteer to the debugging URL like in the previous article.

Puppeteer is an interesting tip. I’m learning.

I have been following this video … from your first link above.

https://youtu.be/lhZOFUY1weo

and here …

https://electronjs.org/apps/puppetry

I have one issue: I need to find how to get the remote debugging URL from within Electron, then after that I think it’ll be easy to connect Puppeteer. I asked about that here: How do I get Chrome's remote devtools debugging URL?

Alright, figured out how to get the WebSocket debugger URL (in the previous comment’s linked thread), and connected Puppeteer:

import {app, BrowserWindow, ...} from "electron"
import fetch from 'node-fetch'

// IMPORTANT! make sure you get the correct version puppeteer or
// puppeteer-core for the version of Chrome that is running in Electron!
import * as puppeteer from 'puppeteer'

app.commandLine.appendSwitch('remote-debugging-port', '8315')

async function test() {
    const response = await fetch(`http://localhost:8315/json/list?t=${Math.random()}`)
    const debugEndpoints = await response.json()
    
    let webSocketDebuggerUrl = ''
    
    for (const debugEndpoint of debugEndpoints) {
        if (debugEndpoint.title === 'Saffron') {
            webSocketDebuggerUrl = debugEndpoint.webSocketDebuggerUrl
            break
        }
    }
    
    const browser = await puppeteer.connect({
        browserWSEndpoint: webSocketDebuggerUrl
    })
    
    // use puppeteer APIs now!
}

// ... make your window, etc, the usual, and then: ...

  // wait for the window to open/load, then connect Puppeteer to it:
  mainWindow.webContents.on("did-finish-load", () => { 
    test()
  })
1 Like

Thanks for sharing your final code solution @trusktr, that helped me a ton!

1 Like