# electro-func

> A barebones functional testing framework for client-side javascript using a headless electron instance for rendering.

Latest version **2.0.2** (published 2016-11-17) · MIT license · 0 weekly downloads

## Install

```sh
npm install electro-func
pnpm add electro-func
yarn add electro-func
bun add electro-func
```

Provides the command `electro-func`.

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 2.0.2 |
| Published | 2016-11-17 |
| First published | 2016-11-06 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 5 |
| Known vulnerabilities | 0 (+53 in 1 direct dependencies) |
| Install scripts | no |
| Author | Kim Mantas |
| Maintainers | fyorl |
| Keywords | electron, testing, test, functional, client-side, functional testing, headless, javascript testing |

## Links

- npm: https://www.npmjs.com/package/electro-func
- Repository: https://bitbucket.org/fyorl/electro-func
- Homepage: https://bitbucket.org/fyorl/electro-func#readme
- Issues: https://bitbucket.org/Fyorl/electro-func/issues
- npm.io page: https://npm.io/package/electro-func

## Dependencies (5)

- [chai](https://npm.io/package/chai.md) ^3.5.0
- [colors](https://npm.io/package/colors.md) ^1.1.2
- [moment](https://npm.io/package/moment.md) ^2.15.1
- [electron](https://npm.io/package/electron.md) ^1.4.0
- [minimist](https://npm.io/package/minimist.md) ^1.2.0

## Alternatives

- [duck](https://npm.io/package/duck.md) — 4.2M weekly downloads
- [ava](https://npm.io/package/ava.md) — 560.2K weekly downloads
- [storybook-addon-module-mock](https://npm.io/package/storybook-addon-module-mock.md) — 71.7K weekly downloads
- [@ethereum-waffle/mock-contract](https://npm.io/package/@ethereum-waffle/mock-contract.md) — 40.0K weekly downloads
- [aws-elasticsearch-connector](https://npm.io/package/aws-elasticsearch-connector.md) — 37.4K weekly downloads

## Recent versions

- 2.0.2 (latest) — 2016-11-17
- 2.0.1 — 2016-11-17
- 2.0.0 — 2016-11-11
- 1.0.4 — 2016-11-10
- 1.0.3 — 2016-11-09
- 1.0.2 — 2016-11-07
- 1.0.1 — 2016-11-06
- 1.0.0 — 2016-11-06

## README

A barebones functional testing framework for client-side javascript using a headless electron instance for rendering.

Quick Start
===========

Install `electro-func` in your project by running the following from your project's directory:

```
$ npm install electro-func
```

Add the test harness and your tests to the bottom of any files you want to test:

```
#!html
<!-- index.html -->
<body>
	<!-- ... -->
	<script src="node_modules/electro-func/harness.js"></script>
	<script src="tests/example.test.js"></script>
</body>
```

Run your tests by running the following from your project's directory (this example runs any tests in `index.html`):

```
$ node_modules/.bin/electro-func index
```

JQuery
======

If your project uses jQuery, you will need to add the following extra code before the `<script>` that includes jQuery in your page, i.e:

```
#!html
<script>
	if (window.require) {
		window.$ = window.jQuery = require('./js/jquery-3.1.1.min');
	}
</script>
<script src="js/jquery-3.1.1.min.js"></script>
```

The reason for this is because the jQuery library tries to detect whether it's running in a node.js environment or running in a browser environment. Because we use electron to render the pages and not an actual browser, jQuery thinks it's running in a node.js environment and doesn't add itself to the global `window` scope which any client-side javascript will be depending on.

Examples
========

The `examples/` directory contains an example of the most minimal test in the `basic/` directory while the `app/` directory contains an example of a full single-page application and its associated tests which you can use to get a better idea of how to use the framework.

You can view the examples in your browser or run them yourself. To do that, you need to install `electro-func` to the directory of the example you want to run with:

```
$ npm install
```

Then you can run the basic example with:

```
$ node_modules/.bin/electro-func
```

And you can run the app example with:

```
$ node_modules/.bin/electro-func index
```

Adding Tests to a Project
============================

The following is a brief guide/tutorial that goes beyond the quick start guide and walks through adding some functional tests to an existing site's javascript.

All the code can be found in `examples/` directory under the `guide/` directory.

## Project structure

We start with a website that might look like this:

```
├── css
│   └── site.css 
├── js
│   ├── jquery-3.1.1.min.js
│   └── site.js
├── img
│   ├── bg-texture.png
│   └── logo.png
├── about.html
├── example.html
└── index.html
```

On the site's index page, there is a form that allows the visitor to input their favourite colour and it will store this value for the next time they visit. Our `index.html` might look something like this:

```
#!html
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Favourite Colour</title>
	<link rel="stylesheet" href="css/site.css">
</head>
<body>
	<div id="greeting"></div>
	<form id="colour-form">
		<label for="colour">Favourite colour</label>
		<input id="colour" type="text">
		<button id="save" type="button">Save</button>
	</form>
	
	<script src="js/jquery-3.1.1.min.js"></script>
	<script src="js/site.js"></script>
</body>
</html>
```

## Code

The code that manages the loading and saving of visitors' favourite colours is in `site.js`:

```
#!js
'use strict';

const loadFavouriteColour = () => {
	const colour = localStorage['favourite-colour'];
	const msg =
		colour
			? 'Your favourite colour is ' + colour
			: "You don't have a favourite colour yet";
	$('#greeting').text(msg);
};

const saveFavouriteColour = () => {
	const colour = $('#colour').val();
	if (colour.length < 1) {
		localStorage.removeItem('favourite-colour');
	} else {
		localStorage['favourite-colour'] = colour;
	}
};

$('#save').click(saveFavouriteColour);
loadFavouriteColour();
```

We want to write some tests to make sure this code behaves as expected.

## Tests

We write our tests in `tests/site.test.js`:

```
#!js
'use strict';

// Create the test suite.
_tests.Site = {};

// Clean up any saved state before each test.
_tests.Site._before = done => {
	Object.keys(localStorage).forEach(key => localStorage.removeItem(key));
	done();
};

_tests.Site.testLoadNoFavouriteColour = done => {
	loadFavouriteColour();
	assert.equal($('#greeting').text(), "You don't have a favourite colour yet");
	done();
};

_tests.Site.testLoadFavouriteColour = done => {
	localStorage['favourite-colour'] = 'black';
	loadFavouriteColour();
	assert.equal($('#greeting').text(), 'Your favourite colour is black');
	done();
};

_tests.Site.testSaveFavouriteColour = done => {
	const click = $.Event('click');
	$('#colour').val('black');
	$('#save').trigger(click);
	assert.equal(localStorage['favourite-colour'], 'black');
	done();
};

_tests.Site.testSaveBlankFavouriteColour = done => {
	const click = $.Event('click');
	$('#colour').val('');
	$('#save').trigger(click);
	expect(localStorage['favourite-colour']).to.not.exist;
	done();
};
```

Tests belong to suites and suites belong to the global `_tests` object which is provided by the `electro-func` framework.

To add a suite, simply create a new object on the global `_tests` object. For example, using normal property syntax:

```
#!js
_tests.TestSuite = {};
```

Or, if you need spaces, for example, you can use dictionary syntax:

```
#!js
_tests['A Suite of Tests'] = {};
```

**Note:** The names of tests or test suites cannot begin with an underscore ('_').

To add a test to a suite, simply add a function to your suite object with the name of the test, e.g.:

```
#!js
_tests.TestSuite.testSomeFunction = done => {
	done();
};
```

As with test suites, you can also use dictionary syntax:

```
#!js
_tests.TestSuite['testing something'] = done => {
	done();
};
```

All tests accept a single argument, `done` which is a function that must be called once the test is complete. This allows you to use callbacks and promises in your tests, e.g.:

```
#!js
_tests.TestSuite.testTimeout = done => {
	setTimeout(() => {
		assert(true);
		done();
	}, 200);
};
```

If you forget to call `done`, your test will timeout.

See the **Advanced Usage** section for information on `_before`, `_after`, `_beforeSuite`, and `_afterSuite`.

## Putting It All Together

We now have a choice on how we want to proceed: We can add the test code directly to `index.html` where it won't affect the normal functioning of the site ()except to increase page load time); or we can create our own `TestRunner.html` where we set up some special environment for running our tests in.

The choice will depend on the structure of your project. For simplicity, we will just add our tests to the index page.

The first thing we need to do, is allow jQuery to run inside electron. We add the code specified in the **JQuery** section.

Next we need to add the `electro-func` harness and our test to the bottom of the index page, after all our other scripts. The index page now looks like this:

```
#!html
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Favourite Colour</title>
	<link rel="stylesheet" href="css/site.css">
</head>
<body>
	<div id="greeting"></div>
	<form id="colour-form">
		<label for="colour">Favourite colour</label>
		<input id="colour" type="text">
		<button id="save" type="button">Save</button>
	</form>
	
	<script>
    	if (window.require) {
    		window.$ = window.jQuery = require('./js/jquery-3.1.1.min');
    	}
    </script>
	
	<script src="js/jquery-3.1.1.min.js"></script>
	<script src="js/site.js"></script>
	
	<!-- Tests -->
	<script src="node_modules/electro-func/harness.js"></script>
	<script src="tests/site.test.js"></script>
</body>
</html>
```

## Running

In order to run the tests, we run the following command from our project's directory:

```
$ node_modules/.bin/electro-func index
```

And should see some similar output to the following:

```
  +------------------+
  |    INDEX.HTML    |
  +------------------+
  
  Site
    ✔ testLoadNoFavouriteColour (2ms)
    ✔ testLoadFavouriteColour (2ms)
    ✔ testSaveFavouriteColour (2ms)
    ✔ testSaveBlankFavouriteColour (2ms)
  
  4 passing  (8ms)
```

Advanced Usage
==============

Aside from the bare minimum required to run functional tests, `electro-func` also includes some additional features.

## Debug Mode

You can pass the `--debug` flag on the command line which turns off `electron`'s headless mode. A browser window will spawn with the devtools panel open and you can use its debugging features to debug any test failures you might be having. You can rerun the tests from within the browser window by running `location.reload()` in the devtools console.

## Timeout

By default, any test that takes longer than 2000ms to run will timeout and automatically fail. This is in case there are some complicated nested callbacks or promises being used such that `done` never gets called and the framework has no idea whether it can continue to the next test or not.

If some of your tests legitimately require longer than 2000ms to run, you can increase this timeout by specifying the `--timeout n` flag on the command line, where `n` is the number of milliseconds timeout you want.

## Setup and Teardown

The framework provides some facility for providing setup and teardown functions to your tests. You usually want this to ensure that your page state is reset after each test and that whatever was done in one test, doesn't affect the results of a separate test.

For example, you can set a `_before` function on the test suite object in order to reset the `localStorage` before every test is run:

```
#!js
_tests.Suite._before = done => {
	Object.keys(localStorage).forEach(key => localStorage.removeItem(key));
	done();
};
```

These functions all take a single `done` argument which is a function that must be called once done.

### _before
Runs before every test in a suite.

### _after
Runs after every test in a suite.

### _beforeSuite
Runs once, before any tests in a suite are run.

### _afterSuite
Runs once, after all the tests in a suite have been run.

---
_Source: https://npm.io/package/electro-func · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
