How to automate ElectronJS app

electron browser automation
electron app unit tests
electron performance testing
electron apps
spectron mac
spectron headless
electron api
electron documentation

We're looking to develop an ElectronJS app for particular website automation at our desk job, which includes common tasks like login, form filling, report downloading etc.

We've tried basic tutorial of ElectronJS, Spectron, NightmareJS, Puppeteer etc and all of them work fine separately, but very less documentation (although open github issues) are available on integration of each other.

We want to achieve following:

  • Login state (session) should not be deleted on ElectronJS app closing and should be available on restart of app.
  • Few menu buttons which initiates some automation tasks like download, form fill etc on existing browserWindow

We don't need headless automation, where some magic happens behind the scene. We need menu/button click based actions/tasks on current page only.

NightmareJS, Puppeteer etc all seems to start their own instances of web pages (since because they were built for testing of standalone apps) but what we need is automation of existing BrowserWindows.

Is puppeteer or nightmarejs correct tools for such goals? If yes, any documentation?

Or else, should we inject our own native JS events like mouseclick etc events in console to perform action?

You can use puppeteer-core. core version by default does not download Chromium, which you do not need if you want to control an Electron app.

In the test you then call launch method, where you define electron as the executable file instead of Chromium, like in following snippet:

const electron = require("electron");
const puppeteer = require("puppeteer-core");

const delay = ms =>
  new Promise(resolve => {
    setTimeout(() => {
      resolve();
    }, ms);
  });

(async () => {
  try {
    const app = await puppeteer.launch({
      executablePath: electron,
      args: ["."],
      headless: false,
    });
    const pages = await app.pages();
    const [page] = pages;

    await page.setViewport({ width: 1200, height: 700 });
    await delay(5000);
    const image = await page.screenshot();
    console.log(image);
    await page.close();
    await delay(2000);
    await app.close();
  } catch (error) {
    console.error(error);
  }
})();

Update for electron 5.x.y and up (currently up to 7.x.y, I did not test it on 8.x.y beta yet), where puppeteer.connect is used instead of launch method:

// const assert = require("assert");
const electron = require("electron");
const kill = require("tree-kill");
const puppeteer = require("puppeteer-core");
const { spawn } = require("child_process");

let pid;

const run = async () => {
  const port = 9200; // Debugging port
  const startTime = Date.now();
  const timeout = 20000; // Timeout in miliseconds
  let app;

  // Start Electron with custom debugging port
  pid = spawn(electron, [".", `--remote-debugging-port=${port}`], {
    shell: true
  }).pid;

  // Wait for Puppeteer to connect
  while (!app) {
    try {
      app = await puppeteer.connect({
        browserURL: `http://localhost:${port}`,
        defaultViewport: { width: 1000, height: 600 } // Optional I think
      });
    } catch (error) {
      if (Date.now() > startTime + timeout) {
        throw error;
      }
    }
  }

  // Do something, e.g.:
  // const [page] = await app.pages();
  // await page.waitForSelector("#someid")// 
  // const text = await page.$eval("#someid", element => element.innerText);
  // assert(text === "Your expected text");
  // await page.close();
};

run()
  .then(() => {
    // Do something
  })
  .catch(error => {
    // Do something
    kill(pid, () => {
      process.exit(1);
    });
  });

Getting the pid and using kill is optional. For running the script on some CI platform it does not matter, but for local environment you would have to close the electron app manually after each failed try.

Simple demo repo: https://github.com/peterdanis/electron-puppeteer-demo

Automated Testing with a Custom Driver, To write automated tests for your Electron app, you will need a way to "drive" your application. Spectron is a commonly-used solution which lets you emulate  Let’s use the Electron API demos app, which can be downloaded here. The first thing to notice is that the Chrome developer tools are already there. Use alt+cmd+i (or F12 on windows) to bring up the dev tools. Now you can locate elements in the HTML and build css selectors for your own Selenium test. With that, let’s jump into a tutorial.

Spectron is the best match for electron build applications.

You will have access to all electron API.we can start and stop your app by spectron only.

We can run both packaged app or with out even packaging.

https://electronjs.org/spectron

How to Automate Electron Applications Using Selenium, Give a warm welcome to Electron: a new rising star claiming to take over the world of desktop applications smoothing the rough edges between  Create a new empty folder for your new Electron application. Open up your command line client and run npm init from that very folder. npm will guide you through creating a basic package.json file. The script specified by the main field is the startup script of your app, which will run the main process.

You can use Spectron but if you want to look at documentation, Spectron is using webdriverio which has good documentation.

I recommend you to use Spectron because I tried to automate my tests with java-selenium but it fails some of case. If you want to use selenium, write below code to set capabilities to setup electron app to chromedriver.

 ChromeOptions options = new ChromeOptions();
    options.setBinary(binaryPath);
    options.addArguments("--app=" + argPath);
    options.setCapability("chromeOptions", options);
    driver = new ChromeDriver(options);   

Hope this will help to you.

Automation Tool for Electron App, You can find a code example on the official Github page To get started, have a look at this code snippet: # Install Spectron $ npm install --save-dev spectron. Provide a base, self contained Electron User Space App that: Provides a fully self-contained app to run in user space with no elevated privileges. Manages an overall user connection to the API back end (rest based) Allows the user to see and monitor Wemo, Homekit and other devices on the local network.

Automation Script in Java using Selenium and ChromeDriver

package setUp;

import helper.Constants;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.DesiredCapabilities;


public class Test {

       public static void main(String[] args) {

             System.setProperty(Constants.WebDriverType, Constants.WebDriverPath + Constants.WindowsDriver);

             ChromeOptions opt = new ChromeOptions();

             DesiredCapabilities capabilities = new DesiredCapabilities();

             capabilities.setCapability("chromeOptions", opt);
             capabilities.setBrowserName("chrome");
             capabilities.setVersion("73.0.3683.121");

             ChromeOptions options = new ChromeOptions();
             options.merge(capabilities);
             options.setBinary("C:\\\\Program Files\\\\Audio\\\\Audio-Configuration\\\\Audio-Configuration.exe");
             options.setCapability("chromeOptions", options);
             ChromeDriver driver = new ChromeDriver(options);

             try {
                    Thread.sleep(5000);
                    WebElement webElement = driver.findElement(By.xpath(
                                 "/html/body/app-root/mat-drawer-container/mat-drawer/div/app-bottom-side-nav/div/app-settings-nav/div/div/a/div"));                        
                    webElement.click();
             } catch (Exception e) {
                    System.out.println("Exception trace");
                    System.out.println(e);
             }
       }
}

Automation Script in JavaScript using Spectron (built on top-of ChromeDriver and WebDriverIO).

const Application = require("spectron").Application;

const path =
  "C:/Program Files/Audio/Audio-Configuration/Audio-Configuration.exe";
const myApp = new Application({
  path: path,
  chromeDriverArgs: ["--disable-extensions"],
  env: {
    SPECTRON: true,
    ELECTRON_ENABLE_LOGGING: true,
    ELECTRON_ENABLE_STACK_DUMPING: true
  }
});

const windowClick = async app => {
  await app.start();
  try {
    // Identifying by class name
    await app.client.click(".ic-setting");

    // Identifying by Id
    // await app.client.click("#left-btn");
  } catch (error) {
    // Log any failures
    console.error("Test failed", error.message);
  }
  // Stop the application
     await app.stop();
};

windowClick(myApp);

How to automate Electron application using WebDriver, TestComplete makes it easy to create automated tests for Electron applications since it automatically recognizes web pages that implement the  Go to the Electron app release page; Download the latest chrome webdriver from the above page . For Mac: download version 3.1.6; For Windows: Download version 3.16; Extract into the location; Copy the location path and replace into below code; Run the above program and it launches the electron app and prints the window title on the console.

How to Test Electron Apps, What is Electron? Challenges in automating desktop applications; How does browser automation works? Remote debugging with Chrome  We have a Desktop App which has been built using electron and is chrome underneath. We want an automation tool for it. Could anybody tell me what are the options to automate it? I found Spectron which is developed by Electron community only. However I am not getting anything how to start. I am not getting any good documentation or YouTube videos.

Selenium Conf 2018, js file in which we cater the function to trigger the Electron app and load required files. Electron application window is created by BrowserWindow  Write Automated Tests for Electron With Spectron, Mocha, and Chai Automated testing is a key part of any truly Agile environment. We take a look at how to use these technologies to achieve testing

Spectron For Electron Apps Automation, What test framework should I choose for automation and why? So, the question is what test framework to choose to automate such apps. On the  Test your app. An open source framework for easily writing integrations tests for your Electron app. Spectron sets up and tears down your app and allows it to be test-driven remotely with full support for the Electron APIs. Built on top of ChromeDriver and WebDriverIO .

Comments
  • Hello Peter, does this mean I can script user interaction inside the Electron application? How does it know how to launch Electron and place necessary script inside the Electron app? Are the Electron CLI flags similar to Chromium CLI flags then?
  • Hi Joe. Exactly! You can control page living inside Electron (in the renderer process). It controls the Electron app in the same way as it does control Chromium - through DevTools protocol. Regarding launching the right executable - in the example above I pass in Electron's path instead of Chromium in the launch method. I did not try yet to use it for e2e testing of final built app, but it should probably work in the same way.
  • I get this error: The "file" argument must be of type string. Received type object at puppeteer-core/lib/Launcher.js:126:40
  • @PeterDanis: I have been testing your solution without success. Your proposition is coherent... But have you made this working or can you provide a repo where we can use your working solution ?
  • @Alain - sorry for late reply. Please check simple demo repo: github.com/peterdanis/electron-puppeteer-demo