lovelock
v0.1.1
Published
End-to-end testing system for Electron or NW.js applications
Downloads
6
Maintainers
Readme
Lovelock.js
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 ateardown
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
andargs
. 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