Skip to content

felipecaparelli/selectron

Repository files navigation

logo

Selectron

The purpose of this library is to simplify the development of end-to-end tests for native Electron.js applications using Selenium.

Overview

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.

How to use it

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.

  1. Create a test class inside the /test directory. Hint: You should organize your test classes inside modules or subdirectories.
  2. Add your test case. For example my.test.js. If you prefer you can start copying the basic structure from our example test case
  3. Implement each test scenario - use our test classes as example to create yours.

Basic API

The lib/util.js provides a set of helper methods to simplify your test automation. Here are examples of how to use each method:

Form Interaction Methods

// 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 and Verification Methods

// 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

Browser Logs and Diagnostics

// Get browser console logs
const logs = await driver.getBrowserLogs();
logs.forEach(log => {
    console.log(`[${log.level}] ${log.timestamp}: ${log.message}`);
});

Basic Test Structure

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!');
    });
});

Advanced Configuration

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
});

Error Handling

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');
    }
}

Installation requirements

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.

Example App

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).

Setup

  1. Install dependencies (npm install)
  2. Configure test environment
  3. Run test suite

Running Tests

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 test

or

npm run test:local

This allows you to target specific environments such as development or local setups. Make sure your environment variables are configured correctly before running the tests.

Contributing

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 :).

Libraries

  • selenium
  • mocha

About

The purpose of this project is to simplify E2E testing via Selenium over Electron.js native apps

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published