lovelock

0.1.1 • Public • Published

Lovelock.js

Build Status

Lovelock consists of a few handy utilities for writing end-to-end tests for Electron JS desktop applications.

Given that its for poking at Electron JS applications, I named it after James Lovelock, who, among many other things, invented the electron capture detector.

Note: It's still under development, and the API might change.

Installation

npm install lovelock

Scope

  • Lovelock was written to be used for Electron, but I'm sure it could easily be used for NW.js or many other application frameworks.

  • It is completely test framework and UI library agnostic: it merely a sort of RPC-type bridge between your unit test and the browser process. This means that you need still to get a test framework set up, and a library on the front end to facilitate DOM traversal, such as jQuery!

Getting started

The only requirement is including the following line somewhere within your Electron browser-process JS code:

require('lovelock').try_server(window);

If you want your tests to wait until page load, then consider putting it after everything is set up. Note that this function does nothing unless it detects the environmental variables set by Lovelock.

Now, somewhere in your unit tests, use lovelock.launch_electron to spawn a copy of the electron editor, and perform tests.

Here is an example NodeUnit test case, leveraging jQuery on the front-end to simulate clicks and gather data:

var lovelock = require('lovelock');
 
exports.test_start_click = function (test) {
    lovelock.launch_electron(function (window, teardown) {
        window.$('#start_button').trigger('click')._wait(100)._end();
        window.$('#message').text()._get(function (text) {
            test.equal("Ready to go!", text);
            teardown();
            test.done();
        });
    });
};

Important: If you get an error about Proxy, and are using Node.js to run the unit tests, make sure to use --harmony_proxies flag when running node in order to enable the ES6 Proxy feature!

How it works

The launch_electron method runs electron as a child process. The electron browser process runs a little RPC server based on httpserver. Every "chain" of commands from within the unit tests is "fired off" as soon as it gets to a _get function. It then sends the chain of commands to the browser-process server, which then runs them and returns the result.

The chain syntax is possible with ES6's Proxy feature.

API

Browser

  • try_server(obj, [callback]) - Start server if env variables are found, returning true if a server will be started, false otherwise. obj (typically window) will be exposed for manipulation to the client.

Unit test

  • launch(opts, callback) - Spawn a server and set up bridge. Callback is called with a placeholder for window (or whatever object you pass in the front end), and a teardown function which will kill the child process. Options are listed below:

    • path [required] - path to binary to spawn
    • args [required] - args to pass to binary
    • noisy [default: false] - echo stdout and stderr
    • port [default: 9797] -
    • host [default: localhost] -
    • env [default: {}] - extra env settings
    • cwd [default: null] - specify a custom directory
  • launch_electron([opts], callback) - Shortcut for above. Uses which to find the Electron binary, and includes . as the first arg (assuredly, the location of the Electron binary). args can be specified for additional CLI arguments.

  • connect_remote(opts) - Connects to a remote server. Same options as above, excluding path and args. Synchronous: returns a ready-to-use fake window object.

Chaining

The fake window objects use Proxy to seemingly possess every property. They also have built-in functions, as follows:

  • _wait(t) - Pauses for t milliseconds before continuing the chain (pause occurs asynchronously within browser process)

  • _get(callback) - Sends off the full chain to the server. When successful, call callback with a single argument being the last value in the chain.

  • _collect(name) - Store the last value of the chain in an obj. If any number of _collect is present in the chain, then _get will return instead an object containing all collected values, instead of a single value.

  • _end() - Reset chain back to root element, e.g. resetting back to window, or a base element created with new (see below).

Constructor

new ([chain]) - Constructor syntax allows you to "freeze" portions of the chain to be re-usable. Example below, also demonstrating how _collect and _end can be used effectively to reduce round-trips:

// get various properties about the paragraph
var $para = new (window.$('#main').find('p:first'));
$para.text()._collect('text')._end();
$para.height()._collect('height')._end();
$para.offset()._collect('offset')._end();
$para._get(function (results) {
    test.equal("A paragraph", results.text, "correct text");
    test.ok(results.height > 15, "taller than 15")
    test.ok(results.offset.top > 100, "more than 100 from the top");
    test.ok(results.offset.left > 40, "more than 40 from the left");
});

Development

Please report bugs and make any contributions to the BitBucket repo.

Anti-features

  • Documentation needs work, until then check out tests.js

  • Unit tests don't cover full electron-spin up, only a mocked version of it

Package Sidebar

Install

npm i lovelock

Weekly Downloads

0

Version

0.1.1

License

LGPL-3.0

Last publish

Collaborators

  • michaelb