The purpose of this library is to simplify the development of end-to-end tests for native Electron.js applications using Selenium.
The Selectron project aims to provide the minimum necessary components for you to perform your E2E tests quickly and simply. We also use the Mocha testing framework, which allows us to better organize the execution of each test block, validating their success or failure.
The most basic component you need to test your application with Selenium is the ChromeDriver. For this, we created a customized version of the ChromeDriver that has specific methods to directly access form elements on a screen, without all the verbosity needed to access them otherwise.
- Create a test class inside the
/testdirectory. Hint: You should organize your test classes inside modules or subdirectories. - Add your test case. For example
my.test.js. If you prefer you can start copying the basic structure from our example test case - Implement each test scenario - use our test classes as example to create yours.
The lib/util.js provides a set of helper methods to simplify your test automation. Here are examples of how to use each method:
// Click elements
await driver.waitAndClick('#submit-button'); // Click by CSS selector
await driver.waitAndClick('.menu-item'); // Click any CSS selector
// Fill form inputs
await driver.waitAndFill('firstname', 'John'); // Fill by input name
await driver.waitAndFill('email', '[email protected]');
// Check checkboxes
await driver.waitAndCheck('subscribe'); // Check by input name
await driver.waitAndCheck('terms'); // Handles hidden inputs too
// Select radio buttons
await driver.waitAndCheckRadio('gender', 'male'); // Select by name and value
await driver.waitAndCheckRadio('plan', 'premium'); // Works with any radio group
// Select dropdown options
await driver.waitAndSelect('#country', 'US'); // Select by CSS selector and option value
await driver.waitAndSelect('.language', 'en');// Wait for images to load
await driver.waitForImageLoad('.hero-image'); // Wait for specific image
await driver.waitForImageLoad('#product-pic'); // Ensures image is fully loaded
// Wait for CSS transitions
const element = await driver.findElement(By.css('.animated-div'));
await driver.waitForTransition(element); // Waits for CSS transitions to complete
// Wait for element visibility
const element = await driver.waitUntilVisible('.notification'); // Wait for element to be visible// Get browser console logs
const logs = await driver.getBrowserLogs();
logs.forEach(log => {
console.log(`[${log.level}] ${log.timestamp}: ${log.message}`);
});Here's a complete example of how to structure your test file:
const util = require('@/lib/util');
const config = util.loadConfig();
const assert = require('assert');
describe('Login Form Tests', function() {
let driver;
before(async function() {
// Initialize the driver before tests
driver = await util.generateChromeDriver();
});
after(async function() {
// Clean up after tests
await util.quitDriver(driver);
});
it('Should complete login successfully', async function() {
// Fill the form
await driver.waitAndFill('username', 'testuser');
await driver.waitAndFill('password', 'testpass');
// Check "Remember me"
await driver.waitAndCheck('remember');
// Click login button
await driver.waitAndClick('#login-button');
// Wait for success message
const message = await driver.waitUntilVisible('.success-message');
const text = await message.getText();
assert.strictEqual(text, 'Welcome back!');
});
});The generateChromeDriver method accepts several configuration options:
const driver = await util.generateChromeDriver({
electronPath: 'C:\\Program Files\\MyApp\\example.exe', // Path to your Electron app
profileName: 'my_test_profile', // Chrome profile name
headless: true, // Run in headless mode
debugPort: 9222, // Chrome debug port
extraArgs: ['--no-sandbox', '--disable-gpu'], // Additional Chrome arguments
enableDiagnostics: true // Save diagnostic info on startup
});All methods will throw descriptive errors if elements aren't found or interactions fail. Example error handling:
try {
await driver.waitAndClick('#non-existent');
} catch (error) {
if (error.name === 'TimeoutError') {
console.log('Element not found within timeout period');
} else if (error.name === 'ElementClickInterceptedError') {
console.log('Element was covered by another element');
}
}This library was created and tested with the Chrome Driver version 140.0.7339.240. If your app uses a different version you will have to download a proper Chrome Driver EXE on your local project, as our Electron.js app needs the specific version. Follow the official URL to download it.
HINT: If you don't want to use our app you can just skip this part!
We have provided here an example app, so you can see how this library works. To avoid having large files in this repo you have to download the Electron app source code and build it on your local machine. Follows the repo URL: https://github.com/felipecaparelli/electron-example.
After you have cloned this repo on your local execute the following commands:
npm install
npm run build:win (if Windows)
Then you can set the path to your repo location or you can just copy the files generated inside the dist/win-unpacked directory to data/client inside this project (in this case you don't need to change any environment configuration).
- Install dependencies (
npm install) - Configure test environment
- Run test suite
You can run the test suite using different environment configurations by setting the ENV variable. For example, if we want to test the default environment (DEV) we run the following command:
npm run testor
npm run test:localThis allows you to target specific environments such as development or local setups. Make sure your environment variables are configured correctly before running the tests.
It is a personal initiative, so few free to contribute to this project if you need something else. Also, I would like to say that I love coffee, so if this library saved you at least 1 hour of your work day you can buy me a coffee :).
- selenium
- mocha
