airtap
Run TAP unit tests in 1789+ browsers. Airtap is a command-line interface to unit test your JavaScript in browsers, using a TAP-producing harness like tape
. Start testing locally and seamlessly move to browsers in the cloud for full coverage. Airtap runs browsers concurrently and lets you iterate quickly during development. Don't just claim your JavaScript supports "all browsers", prove it with tests!
Install
With npm do:
npm install airtap --save-dev
If you are upgrading or migrating from zuul
: please see the upgrade guide.
Getting Started
You'll need an entry point for your tests like test.js
. For a complete example see airtap-demo
. If you already have an entry point, go ahead and run it with:
airtap test.js
Out of the box, this will launch the default browser on your system. To keep the browser open and automatically reload when you make changes to your test files, run:
airtap --live test.js
Adding Browsers
In order to run more browsers, create a .airtap.yml
file in your working directory, containing at least one provider and browser. For example:
providers:
- airtap-system
browsers:
- name: chrome
- name: ff
Providers discover browsers on a particular platform or remote service. In the above example, airtap-system
finds browsers installed on your machine which Airtap then matches against the specified browsers
. Providers are npm packages that must be installed separately from the main airtap
package. So that would be:
npm install airtap airtap-system --save-dev
You can include multiple providers and let Airtap find the best matching browser(s):
providers:
- airtap-playwright
- airtap-system
browsers:
- name: ff
version: 78
You can also match browsers by provider:
Click to expand
browsers:
- name: ff
provider: airtap-system
Airtap, providers and browsers are tied together by manifests. They define the name and other metadata of browsers. You can see these manifests by running airtap -l
or -la
which is short for --list-browsers --all
. For example:
Click to expand
$ airtap -la
- name: electron
title: Electron 9.0.5
version: 9.0.5
options:
headless: true
provider: airtap-electron
Airtap can match browsers on any manifest property, with the exception of options
which exists to customize the browser behavior. Options are specific to a provider. For example, the airtap-playwright
provider supports disabling headless mode and setting custom command-line arguments:
browsers:
- name: chromium
options:
headless: false
launch:
args: [--lang=en-US]
For more information on the browsers
field, see Configuration.
Available Providers
Package | Description |
---|---|
airtap-system |
Locally installed browsers on Linux, Mac & Windows |
airtap-playwright |
Playwright (headless Chromium, FF and WebKit) |
airtap-sauce |
Remote browsers in Sauce Labs |
airtap-electron |
Electron |
airtap-default |
Default browser |
airtap-manual |
Manually open a URL in a browser of choice |
Cloud Testing With Sauce Labs
The airtap-sauce
provider runs browsers on Sauce Labs. Sauce Labs offers quite a few browsers, with a wide range of versions and platforms.
Open source projects can use the free for open source version of Sauce Labs.
1. Set Credentials
Airtap needs to know your Sauce Labs credentials. You don't want to commit these sensitive credentials to your git repository. Instead set them via the environment as SAUCE_USERNAME
and SAUCE_ACCESS_KEY
.
2. Select Browsers
Add the airtap-sauce
provider and wanted browsers to .airtap.yml
:
providers:
- airtap-sauce
browsers:
- name: chrome
- name: ios_saf
- name: ie
3. Set Hostname
Airtap runs a server to serve JavaScript test files to browsers. The airtap-sauce
provider establishes a tunnel to your local machine so that Sauce Labs can find that server. For this to work, some browsers need a custom loopback hostname, because they don't route localhost
through the tunnel. Add the following to your hosts
file:
127.0.0.1 airtap.local
You are now ready to run your tests in the cloud with airtap test.js
.
Continuous Integration
After making sure your tests pass when initiated from your local machine, you can setup continuous integration to run your tests whenever changes are committed. Any CI service that supports Node.js will work.
Travis CI
1. Setup Travis
Take a look at the Travis getting started guide for Node.js. At minimum we need to create a .travis.yml
file containing:
language: node_js
node_js:
- 12
addons:
hosts:
- airtap.local
2. Add Test Script
Add the following to your package.json
:
{
"scripts": {
"test": "airtap test.js"
}
}
3. Enable Code Coverage
Optionally enable code coverage with the --coverage
flag. This will collect code coverage per browser into the .nyc-output/
folder in Istanbul 1.0 format. Afterwards you can generate reports with nyc report
, which takes care of merging code coverage from multiple browsers.
A typical setup for Travis looks like:
{
"scripts": {
"test": "airtap --coverage test.js"
}
}
You can choose to post the results to coveralls
(or similar) by adding a step to .travis.yml
:
after_success: npm run coverage
{
"scripts": {
"test": "airtap --coverage test.js",
"coverage": "nyc report --reporter=text-lcov | coveralls"
}
}
4. Set Credentials
Skip this step if you're not using the airtap-sauce
provider. Same as when initiating tests locally, we need to get Sauce Labs credentials to Travis. Luckily Travis has a feature called secure environment variables. You'll need to set 2 of those: SAUCE_USERNAME
and SAUCE_ACCESS_KEY
.
GitHub Actions
Should work in theory :)
CLI
Usage: airtap [options] <files>
. Supports multiple files
. They can be paths relative to the working directory or glob patterns (e.g. airtap test/*.js
). Options:
-v --version Print version and exit
-l --list-browsers List (effective or --all) browsers
-a --all Test or list all available browsers
--coverage Enable code coverage analysis
--live Keep browsers open to allow repeated test runs
-c --concurrency <n> Number of browsers to test concurrently, default 5
-r --retries <n> Number of retries when running a browser, default 6
-t --timeout <n> How long to wait for test results, default 5m. Can
be a number in milliseconds or a string with unit.
-p --preset <preset> Select a configuration preset
-s --server <script> Path to script that runs a support server
--loopback <host> Custom hostname that equals or resolves to 127.0.0.1
--verbose Enable airtap debug output
--silly Enable all debug output
-h --help Print help and exit.
Examples (click to expand)
List all available browsers:
airtap -la
Test browsers specified in .airtap.yml:
airtap test.js
Test all available browsers (careful):
airtap -a test.js
Test multiple files:
airtap "test/*.js"
Configuration
Airtap consumes a YAML config file at .airtap.yml
in the working directory. The following fields are available.
providers
(array)
browsers
(array)
List of browsers to test in the cloud. Each entry should contain a name
property. Additional properties like version
and platform
may be specified depending on the provider.
The version
property defaults to latest
and can be a specific version number, the keyword latest
, the keyword oldest
, or (for Firefox and Chrome) one of the keywords beta
or dev
.
browsers:
- name: chrome
- name: firefox
version: beta
Specific version of a browser on a specific platform
Only supported by the airtap-sauce
provider at the time of writing, as other providers do not run browsers on a particular platform.
browsers:
- name: chrome
version: 28
platform: Windows XP
Range of versions of a browser
browsers:
- name: firefox
version: 14..latest
- name: ie
version: 9..11
Range of versions with negative start index.
This example would test the latest three stable versions of Firefox (latest - 2, latest - 1, latest).
browsers:
- name: firefox
version: -2..latest
Disjoint versions
browsers:
- name: firefox
version: [19, 20]
Disjoint with ranges
browsers:
- name: firefox
version: [19, 20, 23..latest]
- name: chrome
version: [-1..latest, beta]
Float version numbers
browsers:
- name: ios_saf
version: '8.0..latest'
Float version numbers should be quoted.
browserify
(array)
You can set any of the items in the following list, and they'll be passed to browserify
.
plugin
external
ignore
exclude
transform
add
require
They can be repeated and accept options.
browserify:
- require: ./some-file.js
expose: intimidate
- transform: brfs
- transform: jadeify
You can also customize what's passed to browserify(options)
.
browserify:
- options:
node: true
IE support
To support Internet Explorer, older versions of the buffer
and stream-browserify
polyfills are required. Use the following configuration and run npm install buffer@4 stream-browserify@2
:
# Use buffer@4 and stream-browserify@2 to support IE
browserify:
- require: 'buffer/'
expose: 'buffer'
- require: 'stream-browserify'
expose: 'stream'
This is not officially supported. There may be other reasons that IE will not work.
server
(string or object)
This field can point to an optional shell command or JavaScript file to run as a support server. It will be started before all tests and stopped afterwards. This allows testing websockets and other network requests. Your command will be run with the AIRTAP_SUPPORT_PORT
environment variable set to a port number you must use. If your server does not listen on this port it will be unreachable (on browser providers that use a tunnel).
server: ./test/support/server.js
We recommend writing simple support servers using http
or express
. For shell commands you can use $AIRTAP_SUPPORT_PORT
in the arguments, which will be substituted:
server: "python -m SimpleHTTPServer $AIRTAP_SUPPORT_PORT"
Firefox Profile
The airtap-sauce
provider supports running Firefox instances with custom user profiles. This allows you to configure anything you can change in about:config
programmatically for a test run. You can set these options with a section under any Firefox browser entry:
browsers:
- name: firefox
options:
profile:
webgl.force-enabled: true
ESM Support
By default airtap doesn't support ESM, but you can configure it to work with ESM and CJS using the following config:
browserify:
- transform: babelify
global: true
presets: ['@babel/preset-env']
plugins: ['@babel/plugin-syntax-import-assertions']
You'll need to install babelify
, @babel/preset-env
and @babel/plugin-syntax-import-assertions
. Note that other global browserify configs might break this and that the global
parameter might not be required.
Who Uses Airtap?
Lots of folks! Collectively, packages that depend on Airtap get 100's of millions of downloads per month!
level
(and dependencies)webtorrent
(and dependencies)simple-peer
buffer
stream-http
readable-stream
- Send a PR to add your package to the list!
Contributing
Airtap is an OPEN Open Source Project. This means that:
Individuals making significant and valuable contributions are given commit-access to the project to contribute as they see fit. This project is more like an open wiki than a standard guarded open source project.
See the contribution guide for more details.
License
MIT © Roman Shtylman, Zuul contributors and Airtap contributors.