# Technical Documentation: karma-runner/karma

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/karma-runner/karma)

### Overview (`README.md`)

# Karma
[](https://github.com/karma-runner/karma) [](https://www.npmjs.com/package/karma) [](https://npmcharts.com/compare/karma?minimal=true)

 [](https://codeclimate.com/github/karma-runner/karma) [](https://makeapullrequest.com/) [](https://david-dm.org/karma-runner/karma) [](https://david-dm.org/karma-runner/karma#info=devDependencies) [](https://github.com/semantic-release/semantic-release)

A simple tool that allows you to execute JavaScript code in multiple
_real_ browsers.

> The main purpose of Karma is to make your test-driven development easy,
>  fast, and fun.

## Karma is deprecated and is not accepting new features or general bug fixes.

The web testing space has evolved significantly in the [10+ years](https://testing.googleblog.com/2012/11/testacular-spectacular-test-runner-for.html) since Karma's creation. The web landscape looks very different today and new patterns and tools have emerged in the ecosystem. New test runners offer more performant alternatives, and Karma no longer provides clear unique value.

Based on the current state of the web testing ecosystem, we have made the hard decision to deprecate Karma.

We know Karma is used particularly commonly in the Angular ecosystem, so Angular is adding [Jest](https://jestjs.io/) and [Web Test Runner](https://modern-web.dev/docs/test-runner/overview/) support to provide a migration path off of Karma. See the [Angular blog](https://blog.angular.io/moving-angular-cli-to-jest-and-web-test-runner-ef85ef69ceca) for more details.

Critical security issues in Karma will still be triaged and fixed as necessary. This will continue until 12 months after Angular CLI's Web Test Runner support is marked stable.

For those outside Angular looking to migrate off Karma, both [Web Test Runner](https://modern-web.dev/docs/test-runner/overview/) and [`jasmine-browser-runner`](https://github.com/jasmine/jasmine-browser-runner) provide browser-based unit testing solutions which can be used as a direct alternative. [Jest](https://jestjs.io/) and [Vitest](https://vitest.dev/) also provide Node-based alternatives.

It has been incredible to see Karma's impact on the web testing ecosystem and we greatly appreciate the support of everyone who contributed to an awesome community. Keep testing. ✅


## Help and Support

> For questions and support please use the mailing list or Gitter.
> The issue tracker is for bug reports and feature discussions only.

* Obligatory [documentation]
* Quick questions:
[](https://gitter.im/karma-runner/karma)
* Longer questions: [Mailing List]
* Bug reports [Issue Tracker]
* Everything less than 140 characters: [@JsKarma] on Twitter



## When should I use Karma?

* You want to test code in *real* browsers.
* You want to test code in multiple browsers (desktop, mobile,
  tablets, etc.).
* You want to execute your tests locally during development.
* You want to execute your tests on a continuous integration server.
* You want to execute your tests on every save.
* You love your terminal.
* You don't want your (testing) life to suck.
* You want to use [Istanbul] to automagically generate coverage
  reports.
* You want to use [RequireJS] for your source files.


## But I still want to use \_insert testing library\_

Karma is not a testing framework, nor an assertion library.
Karma just launches an HTTP server, and generates the test runner HTML file you probably already know from your favourite testing framework.
So for testing purposes you can use pretty much anything you like. There are already plugins for most of the common testing frameworks:

* [Jasmine]
* [Mocha]
* [QUnit]
* and [many others](https://www.npmjs.com/search?q=keywords:karma-adapter)

If you can't find an adapter for your favourite framework, don't worry and write your own.
It's not that hard and we are here to help.


## Which Browsers can I use?

All the major browsers are supported, if you want to know more see the
[browsers] page.


## Troubleshooting
See [FAQ](https://karma-runner.github.io/latest/intro/faq.html).


## I want to use it. Where do I sign?

You don't need to sign anything but here are some resources to help
you to get started...


### Obligatory Screencast.

Every serious project has a screencast, so here is ours.  Just click
[here] and let the show begin.


### Installation.

See [installation](https://karma-runner.github.io/latest/intro/installation.html).


### Using it.

See [configuration](https://karma-runner.github.io/latest/intro/configuration.html).


## This is so great. I want to help.

Please, see
[contributing](https://karma-runner.github.io/latest/dev/contributing.html).


## Why did you create this?

Throughout the development of [AngularJS], we've been using [JSTD] for
testing. I really think that JSTD is a great idea. Unfortunately, we
had many problems with JSTD, so we decided to write our own test
runner based on the same idea. We wanted a simple tool just for
executing JavaScript tests that is both stable and fast. That's why we
use the awesome [Socket.io] library and [Node.js].


## My boss wants a license. So where is it?
[MIT License](./LICENSE)


[AngularJS]: https://angularjs.org/
[JSTD]: https://code.google.com/p/js-test-driver/
[Socket.io]: https://socket.io/
[Node.js]: https://nodejs.org/
[Jasmine]: https://github.com/karma-runner/karma-jasmine
[Mocha]: https://github.com/karma-runner/karma-mocha
[QUnit]: https://github.com/karma-runner/karma-qunit
[here]: https://www.youtube.com/watch?v=MVw8N3hTfCI
[Mailing List]: https://groups.google.com/forum/#!forum/karma-users
[Issue Tracker]: https://github.com/karma-runner/karma/issues
[@JsKarma]: https://twitter.com/JsKarma
[RequireJS]: https://requirejs.org/
[Istanbul]: https://github.com/gotwarlost/istanbul

[browsers]: https://karma-runner.github.io/latest/config/browsers.html
[documentation]: https://karma-runner.github.io

---

### Index (`docs/index.md`)

---
layout: homepage
pageTitle: Spectacular Test Runner for Javascript
---

---

### About 01 Versioning (`docs/about/01-versioning.md`)

Karma uses [Semantic Versioning].

It is recommended that you add Karma by running:

```bash
$ yarn add --dev karma
```

or: 

```bash
$ npm --save-dev install karma
```

[Semantic Versioning]: https://semver.org/

---

### About 03 Migration (`docs/about/03-migration.md`)

---
pageTitle: Migration from v0.10
---

The good thing is that you don't have to migrate everything at once.
You can leave all the existing projects using an older version of Karma and only use the latest
version for the new projects. Alternatively, you can migrate the existing projects one at a time...


Anyway, this migration should be easy ;-) so let's get started...

```bash
cd <path-to-your-project>
npm install karma --save-dev
```
This will install the latest version of Karma and also update `package.json` of your project.


## Install missing plugins
Karma does not ship with any "default" plugins anymore.
For existing projects, this should not cause any problems as npm (when updating Karma to 0.10 using
`npm install karma --save-dev`) added these "default" plugins into `package.json` as regular dependencies.
For new projects, just remember you have to install all the plugins you need. These are the "default" plugins that were removed:
- karma-jasmine
- karma-requirejs
- karma-coffee-preprocessor
- karma-html2js-preprocessor
- karma-chrome-launcher
- karma-firefox-launcher
- karma-phantomjs-launcher
- karma-script-launcher


## Install CLI interface
Karma does not put the `karma` command in your system PATH anymore.
If you want to use the `karma` command, please install the command line interface (`karma-cli`).

You probably have the `karma` package installed globally, in which case you should remove it first:
```bash
npm remove -g karma
```

And then install the command line interface:
```bash
npm install karma-cli
```


## Default configuration
`autoWatch` is true by default, so if you don't wanna use it make sure you set it to `false`.
But hey, give it a shot first, it's really awesome to run your tests on every save!


## npm complaining
In some cases, npm can run into dependency tree issues during the migration process. If you are faced with an "unsatisfied peer dependency" error, removing all of the packages (`rm -rf ./node_modules`) and installing them again should clear up the issue.

If you have any other issues, please ask on the [mailing list].


[mailing list]: https://groups.google.com/forum/?fromgroups#!forum/karma-users

---

### Config 01 Configuration File (`docs/config/01-configuration-file.md`)

## Overview
In order to serve you well, Karma needs to know about your project in order to test it
and this is done via a configuration file. The easiest way to generate an initial configuration file
is by using the `karma init` command. This page lists all of the available configuration options.

Note: Most of the framework adapters, reporters, preprocessors and launchers need to be loaded as [plugins].


The Karma configuration file can be written in JavaScript, CoffeeScript, or TypeScript and is loaded as a regular Node.js module.

Unless provided as argument, the Karma CLI will look for a configuration file at

* `./karma.conf.js`
* `./karma.conf.coffee`
* `./karma.conf.ts`
* `./.config/karma.conf.js`
* `./.config/karma.conf.coffee`
* `./.config/karma.conf.ts`

in that order.

Within the configuration file, the configuration code is put together by setting `module.exports` to point to a function
which accepts one argument: the configuration object.

```javascript
// karma.conf.js
module.exports = function(config) {
  config.set({
    basePath: '../..',
    frameworks: ['jasmine'],
    //...
  });
};
```

```coffeescript
# karma.conf.coffee
module.exports = (config) ->
  config.set
    basePath: '../..'
    frameworks: ['jasmine']
    # ...
```

```typescript
// karma.conf.ts
module.exports = (config) => {
  config.set({
    basePath: '../..',
    frameworks: ['jasmine'],
    //...
  });
}
```

Alternatively, you can use an `async` function instead (since v6.3).

```javascript
// karma.conf.js
module.exports = async (config) => {
  const karmaConfig = await getKarmaConfig("dev");
  
  config.set({
    ...karmaConfig
  });
};
```


### Customized TypeScript Configuration
Under the hood Karma uses ts-node to transpile TypeScript to JavaScript. If the resolved `tsconfig.json` has `module` configured as `ES` formats. You might get errors like `SyntaxError: Unexpected token`. This is due that in Node `ES` module formats are not supported. To overcome this issue you need to configure ts-node to use `commonjs` module format.

Create a JavaScript configuration file that overrides the module format.
```javascript
// karma.conf.js
require('ts-node').register({
  compilerOptions: {
    module: 'commonjs'
  }
});
require('./karma.conf.ts');
```

## File Patterns
All of the configuration options, which specify file paths, use the [minimatch][minimatch] library to facilitate flexible
but concise file expressions so you can easily list all of the files you want to include and exclude.

You can find details about each configuration option in the section below. The following options utilize minimatch expressions:

 * `exclude`
 * `files`
 * `preprocessors`

Examples:

 * `**/*.js`: All files with a "js" extension in all subdirectories
 * `**/!(jquery).js`: Same as previous, but excludes "jquery.js"
 * `**/(foo|bar).js`: In all subdirectories, all "foo.js" or "bar.js" files

## Configuration Options
These are all of the available configuration options.

## autoWatch
**Type:** Boolean

**Default:**  `true`

**CLI:** `--auto-watch`, `--no-auto-watch`

**Description:** Enable or disable watching files and executing the tests whenever one of these files changes.


## autoWatchBatchDelay
**Type:** Number

**Default:**  `250`

**Description:** When Karma is watching the files for changes, it tries to batch
multiple changes into a single run so that the test runner doesn't try to start and restart running
tests more than it should, or restart while build files are not in a consistent state. The configuration setting
tells Karma how long to wait (in milliseconds) from the last file change before starting
the test process again, resetting the timer each time a file changes (i.e. [debouncing](https://davidwalsh.name/javascript-debounce-function)).


## basePath
**Type:** String

**Default:** `''`

**Description:** The root path location that will be used to resolve all relative
paths defined in `files` and `exclude`. If the `basePath` configuration is a
relative path, then it will be resolved to the `__dirname` of the configuration file.


## browserDisconnectTimeout
**Type:** Number

**Default:** `2000`

**Description:** How long does Karma wait for a browser to reconnect (in ms).

With a flaky connection, it is pretty common that the browser disconnects, but the actual test execution is still running
without any problems. Karma does not treat a disconnection as an immediate failure and will wait for `browserDisconnectTimeout` (ms).
If the browser reconnects during that time, everything is fine.


## browserConsoleLogOptions
**Type:** Object

**Default:** `{level: "debug", format: "%b %T: %m", terminal: true}`

**Description:** Configure how the browser console is logged with the following
properties, all of which are optional:

```javascript
{
  level:  string,
  format: string,
  path:   string,
  terminal: boolean
}
```


Here the `level` is the desired log-level, where level `log` always is logged. The format
is a string where `%b`, `%t`, `%T`, and `%m` are replaced with the browser string,
log type in lower-case, log type in uppercase, and log message, respectively. This format will
only effect the output file. `path` is the output-path of the output-file, and `terminal` indicates
if the log should be written in the terminal, or not.


## browserDisconnectTolerance
**Type:** Number

**Default:** `0`

**Description:** The number of disconnections tolerated.

The `disconnectTolerance` value represents the maximum number of tries a browser will attempt in the case of a disconnection.
Usually, any disconnection is considered a failure, but this option allows you to define a tolerance level when there is
a flaky network link between the Karma server and the browsers.


## browserNoActivityTimeout
**Type:** Number

**Default:** `30000`

**Description:** How long will Karma wait for a message from a browser before disconnecting from it (in ms).

If, during test execution, Karma does not receive any message from a browser within `browserNoActivityTimeout`(ms), it will disconnect from the browser. The default is the one recommended by Travis (https://docs.travis-ci.com/user/gui-and-headless-browsers/#karma-and-firefox-inactivity-timeouts)


## browsers
**Type:** Array

**Default:**  `[]`

**CLI:** `--browsers Chrome,Firefox`, `--no-browsers`

**Possible Values:**

  * `Chrome` (launcher requires karma-chrome-launcher plugin)
  * `ChromeCanary` (launcher requires karma-chrome-launcher plugin)
  * `ChromeHeadless` (launcher requires karma-chrome-launcher plugin ^2.1.0)
  * `PhantomJS` (launcher requires karma-phantomjs-launcher plugin)
  * `Firefox` (launcher requires karma-firefox-launcher plugin)
  * `Opera` (launcher requires karma-opera-launcher plugin)
  * `IE` (launcher requires karma-ie-launcher plugin)
  * `Safari` (launcher requires karma-safari-launcher plugin)

**Description:** A list of browsers to launch and capture. When Karma starts up, it will also start up each browser
which is placed within this setting. Once Karma is shut down, it will shut down these
browsers as well. You can capture any browser manually by opening the browser and visiting the URL where
the Karma web server is listening (by default it is `http://localhost:9876/`).

See [config/browsers] for more information. Additional launchers can be defined through [plugins]. Use the
`--no-browsers` command line option to override the value of this setting specified in the configuration file
with an empty list.


## captureTimeout
**Type:** Number

**Default:** `60000`

**Description:** Timeout for capturing a browser (in ms).

The `captureTimeout` value represents the maximum boot-up time allowed for a browser to start and connect to Karma.
If any browser does not get captured within the timeout, Karma will kill it and try to launch
it again and, after three attempts to capture it, Karma will give up.


## client.args
**Type:** Array

**Default:** `undefined`

**CLI:** All arguments after `--` (only when using `karma run`)

**Description:** When `karma run` is passed additional arguments on the command-line, they
are passed through to the test adapter as `karma.config.args` (an array of strings).
The `client.args` option allows you to set this value for actions other than `run`.

How this value is used is up to your test adapter - you should check your adapter's documentation to see how (and if) it uses this value.


## client.useIframe
**Type:** Boolean

**Default:** `true`

**Description:** Run the tests inside an iFrame or a new window

If true, Karma runs the tests inside an iFrame. If false, Karma runs the tests in a new window. Some tests may not run in an
iFrame and may need a new window to run.

## client.runInParent
**Type:** Boolean

**Default:** `false`

**Description:** Run the tests on the same window as the client, without using iframe or a new window

If true, Karma runs the tests inside the original window without using iframe. It will load the test scripts dynamically.

## client.captureConsole
**Type:** Boolean

**Default:** `true`

**Description:** Capture all console output and pipe it to the terminal.


## client.clearContext
**Type:** Boolean

**Default:** `true`

**Description:** Clear the context window

If true, Karma clears the context window upon the completion of running the tests. If false, Karma does not clear the context window
upon the completion of running the tests. Setting this to false is useful when embedding a Jasmine Spec Runner Template.

## client.clientDisplayNone
**Type:** Boolean

**Default:** `false`

**Description:** Set style display none on client elements.

If true, Karma does not display the banner and browser list. Useful when using karma on component tests with screenshots.

## client.allowedReturnUrlPatterns
**Type:** Array

**Default:** `['^https?://']`

**Description:** Define the string representations of the regular expressions that will be allowed for the `return_url` query parameter.

If the value of the `return_url` query parameter does not match any regular expression derived from the string representation of each of the elements of this array, navigation to it will be blocked.

## colors
**Type:** Boolean

**Default:**   `true`

**CLI:** `--colors`, `--no-colors`

**Description:** Enable or disable colors in the output (reporters and logs).


## concurrency
**Type:** Number

**Default:** `Infinity`

**Description:** How many browsers Karma launches in parallel.

Especially on services like SauceLabs and Browserstack, it makes sense only to launch a limited amount of browsers at once, and only start more when those have finished. Using this configuration, you can specify how many browsers should be running at once at any given point in time.

## crossOriginAttribute

**Type:** Boolean

**Default:** `true`

**Description:** When true, this will append the crossorigin attribute to generated script tags, which enables better error reporting for JavaScript files served from a different origin.
Disable this when you need to load external scripts that are served without the necessary `Access-Control-Allow-Origin` header.


## customContextFile
**Type:** string

**Default:** `null`

**Description:** If `null` (default), uses karma's own `context.html` file.


## customDebugFile
**Type:** string

**Default:** `null`

**Description:** If `null` (default), uses karma's own `debug.html` file.


## customClientContextFile
**Type:** string

**Default:** `null`

**Description:** If `null` (default), uses karma's own `client_with_context.html` file (which is used when client.runInParent set to true).


## customHeaders
**Type:** Array

**Default:** `undefined`

**Description** Custom HTTP headers that will be set upon serving files by Karma's web server.
Custom headers are useful, especially with upcoming browser features like Service Workers.

The `customHeaders` option allows you to set HTTP headers for files that match a regular expression.
`customHeaders` is an array of `Objects` with properties as follows:

* match: Regular expression string to match files
* name: HTTP header name
* value: HTTP header value

**Example:**
```javascript
customHeaders: [{
  match: '.*foo.html',
  name: 'Service-Worker-Allowed',
  value: '/'
}]
```


## detached
**Type:** Boolean

**Default:** `false`

**CLI:** `--detached`

**Description:** When true, this will start the karma server in another process, writing no output to the console.
The server can be stopped using the `karma stop` command.


## exclude
**Type:** Array

**Default:** `[]`

**Description:** List of files/patterns to exclude from loaded files.

## failOnEmptyTestSuite
**Type:** Boolean

**Default:** `true`

**CLI:** `--fail-on-empty-test-suite`, `--no-fail-on-empty-test-suite`

**Description:** Enable or disable failure on running empty test-suites. If disabled the program
will return exit-code `0` and display a warning.

## failOnSkippedTests
**Type:** Boolean

**Default:** `false`

**CLI:** `--fail-on-skipped-tests`, `--no-fail-on-skipped-tests`

**Description:** Enable or disable failure on tests deliberately disabled, eg fit() or xit() tests in jasmine.
Use this to prevent accidental disabling tests needed to validate production.

## failOnFailingTestSuite
**Type:** Boolean

**Default:** `true`

**CLI:** `--fail-on-failing-test-suite`, `--no-fail-on-failing-test-suite`

**Description:** Enable or disable failure on failing tests.

## files
**Type:** Array

**Default:** `[]`

**Description:** List of files/patterns to load in the browser.

See [config/files] for more information.

## forceJSONP
**Type:** Boolean

**Default:** `false`

**Description:** Force socket.io to use JSONP polling instead of XHR polling.

## frameworks
**Type:** Array

**Default:** `[]`

**Description:** List of test frameworks you want to use. Typically, you will set this to `['jasmine']`, `['mocha']` or `['qunit']`...

Please note just about all frameworks in Karma require an additional plugin/framework library to be installed (via npm).

Additional information can be found in [plugins].

## listenAddress
**Type:** String

**Default:** `'0.0.0.0' or LISTEN_ADDR`

**Description:** Address that the server will listen on. Change to 'localhost' to only listen to the loopback, or '::' to listen on all IPv6 interfaces

## hostname
**Type:** String

**Default:** `'localhost'`

**Description:** Hostname to be used when capturing browsers.


## httpsServerOptions
**Type:** Object

**Default:** `{}`

**Description:** Options object to be used by Node's `https` class.

Object description can be found in the [NodeJS.org API docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener)

**Example:**
```javascript
httpsServerOptions: {
  key: fs.readFileSync('server.key', 'utf8'),
  cert: fs.readFileSync('server.crt', 'utf8')
},
```

## logLevel
**Type:** Constant

**Default:** `config.LOG_INFO`

**CLI:** `--log-level debug`

**Possible values:**

  * `config.LOG_DISABLE`
  * `config.LOG_ERROR`
  * `config.LOG_WARN`
  * `config.LOG_INFO`
  * `config.LOG_DEBUG`

**Description:** Level of logging.


## loggers
**Type:** Array

**Default:** `[{type: 'console'}]`

**Description:** A list of log appenders to be used. See the documentation for [log4js] for more information.


## middleware
**Type:** Array

**Default:** `[]`

**Description:** List of names of additional middleware you want the karma server to use. Middleware will be used in the order listed.

You must have installed the middleware via a plugin/framework (either inline or via npm). Additional information can be found in [plugins].

The plugin must provide an express/connect middleware function (details about this can be found in [the Express docs](https://expressjs.com/en/guide/using-middleware.html). An example of custom inline middleware is shown below.

**Example:**
```javascript
function CustomMiddlewareFactory (config) {
  return function (request, response, /* next */) {
    response.writeHead(200)
    return response.end("content!")
  }
}
```

```javascript
middleware: ['custom']
plugins: [
  {'middleware:custom': ['factory', CustomMiddlewareFactory]}
  ...
]
```


## mime
**Type:** Object

**Default:** `{}`

**Description:** Redefine default mapping from file extensions to MIME-type

Set property name to required MIME, provide Array of extensions (without dots) as it's value

**Example:**
```javascript
mime: {
   'text/x-typescript': ['ts','tsx']
   'text/plain' : ['mytxt']
}
```


## beforeMiddleware
**Type:** Array

**Default:** `[]`

**Description:** This is the same as middleware except that these middleware will be run before karma's own middleware.


## plugins
**Type:** Array

**Default:** `['karma-*']`

**Description:** List of plugins to load. A plugin can be either a plugin object, or a string containing name of the module which exports a plugin object. See [plugins] for more information on how to install and use plugins. 

By default, Karma loads plugins from all sibling npm packages which have a name starting with `karma-*`.


## port
**Type:** Number

**Default:** `9876`

**CLI:** `--port 9876`

**Description:** The port where the web server will be listening.

If the defined port is already in use, karma will automatically increase its value in steps of 1 until a free port is found.


## processKillTimeout
**Type:** Number

**Default:** `2000`

**Description:** How long will Karma wait for browser process to terminate before sending a SIGKILL signal.

If, after test execution or after Karma attempts to kill the browser, browser is not killed within `processKillTimeout`(ms), Karma will send a SIGKILL signal to attempt to kill the browser forcefully.


## preprocessors
**Type:** Object

**Default:** `{'**/*.coffee': 'coffee'}`

**Description:** A map of preprocessors to use.

Preprocessors can be loaded through [plugins].

Note: Just about all preprocessors in Karma require an additional library to be installed (via npm).

Be aware that preprocessors may be transforming the files and file types that are available at run time. For instance,
if you are using the "coverage" preprocessor on your source files, if you then attempt to interactively debug
your tests, you'll discover that your expected source code is completely changed from what you expected.  Because
of that, you'll want to engineer this so that your automated builds use the coverage entry in the "reporters" list,
but your interactive debugging does not.

Click <a href="preprocessors.html">here</a> for more information.


## protocol
**Type:** String

**Default:** `'http:'`

**Possible Values:**

* `http:`
* `https:`

**Description:** Protocol used for running the Karma webserver.

Determines the use of the Node `http` or `https` class.

Note: Using `'https:'` requires you to specify `httpsServerOptions`.


## httpModule
**Type:** String

**Default:** `undefined`

**Description:** Module used for Karma webserver.

Uses the provided module instead of node's built in `http` or `https` module. The module loaded here must exactly match the interface of node's http module. This can be useful for loading in a module like `node-http2` to allow for http2 support.

Note: if you're using this to enable `http2` you must also set the `protocol` to `https:` and specify certificates as http2 can only run of https.

## proxies
**Type:** Object

**Default:** `{}`

**Description:** A map of path-proxy pairs.

The proxy can be specified directly by the target url or path, or with an object to configure more options. The available options are:

- `target` The target url or path (mandatory)
- `changeOrigin` Whether or not the proxy should override the Host header using the host from the target (default `false`)

**Example:**
```javascript
proxies: {
  '/static': 'http://gstatic.com',
  '/web': 'http://localhost:9000',
  '/img/': '/base/test/images/',
  '/proxyfied': {
    'target': 'http://myserver.localhost',
    'changeOrigin': true
  }
},
```


## proxyValidateSSL
**Type:** Boolean

**Default:** `true`

**Description:** Whether or not Karma or any browsers should raise an error when an invalid SSL certificate is found.


## reportSlowerThan
**Type:** Number

**Default:** `0`

**Description:** Karma will report all the tests that are slower than given time limit (in ms).
This is disabled by default (since the default value is 0).


## reporters
**Type:** Array

**Default:** `['progress']`

**CLI:** `--reporters progress,growl`

**Possible Values:**

  * `dots`
  * `progress`

**Description:** A list of reporters to use.

Additional reporters, such as `growl`, `junit`, `teamcity` or `coverage` can be loaded through [plugins].

Note: Just about all additional reporters in Karma (other than progress) require an additional library to be installed (via npm).


## formatError
**Type:** Function

**Default:** `undefined`

**CLI:** `--format-error ./path/to/formatFunction.js`

**Arguments:**

  * `msg` - A single line of the assertion error and stack trace (called for each line).

**Returns:** A new error message line.

**Description:** Format assertion errors and stack traces.  Useful for removing vendors and compiled sources.  Return an empty line `''` to remove it.

The CLI option should be a path to a file that exports the format function.  This can be a function exported at the root of the module or an export named `formatError`.

## pingTimeout
**Type** Number

**Default** 5000

**Description** Socket.io pingTimeout in ms, https://socket.io/docs/server-api/#new-Server-httpServer-options.
Very slow networks may need values up to 60000. Larger values delay discovery of deadlock in tests or browser crashes.

## restartOnFileChange
**Type:** Boolean

**Default:** `false`

**Description:** When Karma is watching the files for changes, it will delay a new run until
the current run is finished. Enabling this setting will cancel the current run and start a new run
immediately when a change is detected.


## retryLimit
**Type:** Number

**Default:** 2

**Description:** When a browser crashes, karma will try to relaunch. This defines how many times karma should relaunch
a browser before giving up.

## singleRun
**Type:** Boolean

**Default:** `false`

**CLI:** `--single-run`, `--no-single-run`

**Description:** Continuous Integration mode.

If `true`, Karma will start and capture all configured browsers, run tests and then exit with an exit code of `0` or `1` depending
on whether all tests passed or any tests failed.



## transports
**Type:** Array

**Default:** `['polling', 'websocket']`

**Description:** An array of allowed transport methods between the browser and testing server. This configuration setting
is handed off to [socket.io](https://socket.io/) (which manages the communication
between browsers and the testing server).


## proxyReq
**Type:** Function

**Default:** `undefined`

**Description:** Called when requesting Proxy.

Details about this can be found in the [node-http-proxy](https://github.com/nodejitsu/node-http-proxy). An example of overwriting the HTTP header is shown below.

**Example:**
```javascript
proxyReq: function(proxyReq, req, res, options) {
  proxyReq.setHeader('Referer', 'https://www.example.com/');
}
```

## proxyRes
**Type:** Function

**Default:** `undefined`

**Description:** Called when respnsing Proxy.

Details about this can be found in the [node-http-proxy](https://github.com/nodejitsu/node-http-proxy). An example of overwriting the HTTP header is shown below.

**Example:**
```javascript
proxyRes: function(proxyRes, req, res) {
  if (proxyRes.headers['set-cookie']) {
    proxyRes.headers['set-cookie'] = proxyRes.headers['set-cookie'].map(function (cookie) {
      return cookie.replace(/\s*secure;?/i, '');
    })
  }
}
```


## upstreamProxy
**Type:** Object

**Default:** `undefined`

**Description:** For use when the Karma server needs to be run behind a proxy that changes the base url, etc

If set then the following fields will be defined and can be overridden:

### path
**Type:** String

**Default:** `'/'`

**Description:** Will be prepended to the base url when launching browsers and prepended to internal urls as loaded by the browsers

### port
**Type:** Number

**Default:** `9875`

**Description:** Will be used as the port when launching browsers

### hostname
**Type:** String

**Default:** `'localhost'`

**Description:** Will be used as the hostname when launching browsers



### protocol
**Type:** String

**Default:** `'http:'`

**Description:** Will be used as the protocol when launching browsers


## urlRoot
**Type:** String

**Default:** `'/'`

**Description:** The base url, where Karma runs.

All of Karma's urls get prefixed with the `urlRoot`. This is helpful when using proxies, as
sometimes you might want to proxy a url that is already taken by Karma.

## browserSocketTimeout
**Type:** Number

**Default:** `20000`

**Description:** Timeout for the client socket connection (in ms).

This configuration represents the amount of time that the client will wait for the socket
to connect.

When running a browser in different environments, it can take different amounts of time for the
client socket to connect. If Karma cannot connect within the default timeout, you may see an
error similar to the following:
```
ChromeHeadless has not captured in 60000ms, killing.
Trying to start ChromeHeadless again (1/2).
ChromeHeadless has not captured in 60000ms, killing.
Trying to start ChromeHeadless again (2/2).
ChromeHeadless has not captured in 60000ms, killing.
ChromeHeadless failed 2 times(timeout). Giving up.
```
If you see this error, you can try increasing the socket connection timeout.


[plugins]: plugins.html
[config/files]: files.html
[config/browsers]: browsers.html
[config/preprocessors]: preprocessors.html
[log4js]: https://github.com/nomiddlename/log4js-node
[minimatch]: https://github.com/isaacs/minimatch

---

### Config 02 Files (`docs/config/02-files.md`)

The `files` array determines which files are included in the browser, watched, and served by Karma.

## `files`
**Type.** Array
**No Default.** This property is mandatory.
**Description.** Each item is either a string (equivalent to `{ pattern: "<string>" }`) or an object with the following properties:

### `pattern`
* **Type.** String
* **No Default.** This property is mandatory.
* **Description.** The pattern to use for matching. See below for details on how patterns are resolved.

### `type`
* **Type.** String
* **Default.** Will attempt to determine type based on file extension. If that fails, defaults to `js`.
* **Possible Values:**
  * `css` - Include using `<link rel="stylesheet">` tag.
  * `html` - Include using [HTML Imports](https://developer.mozilla.org/en-US/docs/Web/Web_Components/HTML_Imports). Note that this feature is obsolete and does not work in the modern browsers.
  * `js` - Include using `<script></script>` tag.
  * `module` - Include using `<script type="module"></script>` tag.
  * `dom` - Inline content of the file in the page. This can be used, for example, to test components combining HTML and JS.
* **Description.** The type determines the mechanism for including the file.

### `watched`
* **Type.** Boolean
* **Default.** `true`
* **Description.**  If `autoWatch` is `true` all files that have set `watched` to true will be watched for changes.

### `included`
* **Type.** Boolean
* **Default.** `true`
* **Description.** Should the files be included in the browser using
    `<script>` tag? Use `false` if you want to load them manually, eg.
    using [Require.js](../plus/requirejs.html).

    If a file is covered by multiple patterns with different `include` properties, the most specific pattern takes
    precedence over the other.

    The specificity of the pattern is defined as a six-tuple, where larger tuple implies lesser specificity:
    *(n<sub>glob parts</sub>, n<sub>glob star</sub>, n<sub>star</sub>, n<sub>ext glob</sub>, n<sub>range</sub>, n<sub>optional</sub>)*.
    Tuples are compared lexicographically.

    The *n<sub>glob parts</sub>* is the number of patterns after the bracket sections are expanded. E.g. the
    the pattern *{0...9}* will yield *n<sub>glob parts</sub>=10*. The rest of the tuple is decided as the least
    specific of each expanded pattern.

### `served`
* **Type.** Boolean
* **Default.** `true`
* **Description.** Should the files be served by Karma's webserver?

### `nocache`
* **Type.** Boolean
* **Default.** `false`
* **Description.** Should the files be served from disk on each request by Karma's webserver?

### `integrity`
* **Type.** String
* **Default.** `undefined`
* **Description.** Set the `integrity` HTML attribute value to the `<script>` or the `<link>` tag loading the resource that matches the given pattern if the pattern is an absolute URL.

## Pattern matching and `basePath`
- All of the relative patterns will get resolved using the `basePath` first.
- If the `basePath` is a relative path, it gets resolved to the
  directory where the configuration file is located.
- Eventually, all the patterns will get resolved into files using
  [glob], so you can use [minimatch] expressions like `test/unit/**/*.spec.js`.

## Ordering
- The order of patterns determines the order in which files are included in the browser.
- Multiple files matching a single pattern are sorted alphabetically.
- Each file is included exactly once. If multiple patterns match the
  same file, it's included as if it only matched the first pattern.

## Preprocessor transformations
Depending on preprocessor configuration, be aware that files loaded may be transformed and no longer available in
their native format. For instance, if html2js preprocessor is enabled, the actual .html files are no longer
served - but rather available as `window.__html__['my.html']`. Read more about [preprocessors].


## Complete example
Here is a complete example showing the different options possible:
```javascript
files: [

  // Detailed pattern to include a file. Similarly other options can be used
  { pattern: 'lib/angular.js', watched: false },
  // Prefer to have watched false for library files. No need to watch them for changes

  // simple pattern to load the needed testfiles
  // equal to {pattern: 'test/unit/*.spec.js', watched: true, served: true, included: true}
  'test/unit/*.spec.js',

  // this file gets served but will be ignored by the watcher
  // note if html2js preprocessor is active, reference as `window.__html__['compiled/index.html']`
  {pattern: 'compiled/index.html', watched: false},

  // this file only gets watched and is otherwise ignored
  {pattern: 'app/index.html', included: false, served: false},

  // this file will be served on demand from disk and will be ignored by the watcher
  {pattern: 'compiled/app.js.map', included: false, served: true, watched: false, nocache: true}
],
```

## Loading files from another server

Pattern can also be an absolute URL. This allows including files which are not served by Karma.

Example:

```javascript
config.set({
  files: [
    'https://example.com/my-lib.js',
    { pattern: 'https://example.com/my-lib', type: 'js' }
  ]
})
```

Absolute URLs have some special rules comparing to the regular file paths:

- Globing is not support, so each URL must be specified as a separate pattern.
- Most of the regular options are not supported:
    - `watched` is always `false`
    - `included` is always `true`
    - `served` is always `false`
    - `nocache` is always `false`

## Loading Assets
By default all assets are served at `http://localhost:[PORT]/base/`

Example for loading images

```javascript
files: [
  {pattern: 'test/images/*.jpg', watched: false, included: false, served: true, nocache: false}
],
```

The pattern is a glob which matches the specified image assets. Watched and included are not necessary as images are not tests. However, they will need to be served to the browser.

In this case an image would be accessed at `http://localhost:[PORT]/base/test/images/[MY IMAGE].jpg`

Notice the **base** in the URL, it is a reference to your **basePath**. You do not need to replace or provide your own **base**.

In addition, you can use a proxy

```javascript
proxies: {
  "/img/": "http://localhost:8080/base/test/images/"
},
```

Now you can fetch images in `test/images` at `http://localhost:8080/img/[MY IMAGE].jpg`

Change **8080** to the port you use

You can also use proxies without specifying the protocol, hostname, and port

```javascript
proxies: {
  "/img/": "/base/test/images/"
},
```

## Webserver features

* [Range requests][].
* In-memory caching of files.
* Watching for updates in the files.
* Proxies to alter file paths.
* Support for custom middlewares (the `middleware` configuration option).


[glob]: https://github.com/isaacs/node-glob
[preprocessors]: preprocessors.html
[minimatch]: https://github.com/isaacs/minimatch
[Range requests]: https://en.wikipedia.org/wiki/Byte_serving

---

### Config 03 Browsers (`docs/config/03-browsers.md`)

Capturing browsers on your own can be a tedious and time-consuming task. However, Karma can automate this for you. Simply add the browsers you would like to capture into the [configuration file].

```javascript
browsers: ['Chrome']
```

Then, Karma will take care of auto-capturing these browsers, as well as killing them after the job is over.

Note: Most of the browser launchers need to be loaded as [plugins].

## Available browser launchers
- [Chrome and Chrome Canary](https://www.npmjs.com/package/karma-chrome-launcher)
- [Firefox](https://www.npmjs.com/package/karma-firefox-launcher)
- [Safari](https://www.npmjs.com/package/karma-safari-launcher)
- [PhantomJS](https://www.npmjs.com/package/karma-phantomjs-launcher)
- [JSDOM](https://www.npmjs.com/package/karma-jsdom-launcher)
- [Opera](https://www.npmjs.com/package/karma-opera-launcher)
- [Internet Explorer](https://www.npmjs.com/package/karma-ie-launcher)
- [SauceLabs](https://www.npmjs.com/package/karma-sauce-launcher)
- [BrowserStack](https://www.npmjs.com/package/karma-browserstack-launcher)
- [many more](https://www.npmjs.com/search?q=keywords:karma-launcher)

Here's an example of how to add Firefox to your testing suite:

```bash
# Install the launcher first with npm:
$ npm install karma-firefox-launcher --save-dev
```

And then, inside your configuration file, add the browser name in `browsers` array.

```javascript
module.exports = function(config) {
  config.set({
    browsers : ['Chrome', 'Firefox']
  });
};
```

Also, keep in mind that the `browsers` configuration setting is empty by default.

Of course, you can write [custom plugins] too!

## Capturing any browser manually

You can also capture browsers by simply opening `http://<hostname>:<port>/`, where `<hostname>` is the IP
address or hostname of the machine where the Karma server is running and `<port>` is the port where the Karma
server is listening (by default it's `9876`). With the default settings in place, just point your browser to `http://localhost:9876/`.

This allows you to capture a browser on any device, such as a tablet or a phone, that is on the same network
as the machine running Karma (or using a local tunnel).


## Configured launchers
Some of the launchers can also be configured:

```javascript
sauceLabs: {
  username: 'michael_jackson'
}
```

Or defined as a configured launcher:

```javascript
customLaunchers: {
  chrome_without_security: {
    base: 'Chrome',
    flags: ['--disable-web-security']
  },
  sauce_chrome_win: {
    base: 'SauceLabs',
    browserName: 'chrome',
    platform: 'windows'
  }
}
```

A display name can be set for any custom launcher. If set, this name will be used for reporting instead of the
user agent. Here is a code snippet example explaining how to set a display name for a custom launcher.

```javascript
customLaunchers: {
  chrome_without_security: {
    base: 'Chrome',
    flags: ['--disable-web-security'],
    displayName: 'Chrome w/o security'
  }
}
```

If the definition is as above, the browser will be displayed as `Chrome w/o security` in logs and reports.

## Correct path to browser binary
Each plugin has some default paths where to find the browser binary on particular OS.
You can override these settings by `<BROWSER>_BIN` ENV variable, or alternatively by creating a `symlink`.

### POSIX shells
```bash
# Changing the path to the Chrome binary
$ export CHROME_BIN=/usr/local/bin/my-chrome-build

# Changing the path to the Chrome Canary binary
$ export CHROME_CANARY_BIN=/usr/local/bin/my-chrome-build

# Changing the path to the PhantomJs binary
$ export PHANTOMJS_BIN=$HOME/local/bin/phantomjs
```

### Windows cmd.exe
```bash
C:> SET IE_BIN=C:\Program Files\Internet Explorer\iexplore.exe
```

### Windows Powershell
```bash
$Env:FIREFOX_BIN = 'c:\Program Files (x86)\Mozilla Firefox 4.0 Beta 6\firefox.exe'
```

## Custom browsers
```javascript
// in the karma.conf.js
browsers: ['/usr/local/bin/custom-browser.sh'],

// from cli
karma start --browsers /usr/local/bin/custom-browser.sh
```
The browser scripts need to take one argument, which is the URL with the ID-parameter to be used to connect to the server. The supplied ID is used by the server to keep track of which specific browser is captured.



[Chrome and Chrome Canary]: https://github.com/karma-runner/karma-chrome-launcher
[PhantomJS]: https://github.com/karma-runner/karma-phantomjs-launcher
[JSDOM]: https://github.com/badeball/karma-jsdom-launcher
[Firefox]: https://github.com/karma-runner/karma-firefox-launcher
[Safari]: https://github.com/karma-runner/karma-safari-launcher
[IE]: https://github.com/karma-runner/karma-ie-launcher
[Opera]: https://github.com/karma-runner/karma-opera-launcher
[SauceLabs]: https://github.com/karma-runner/karma-sauce-launcher
[BrowserStack]: https://github.com/karma-runner/karma-browserstack-launcher
[custom plugins]: ../dev/plugins.html
[plugins]: plugins.html
[configuration file]: configuration-file.html

---

### Config 04 Preprocessors (`docs/config/04-preprocessors.md`)

Preprocessors in Karma allow you to do some work with your files before
they get served to the browser. These are configured in the `preprocessors` block
of the configuration file:

```javascript
preprocessors: {
  '**/*.coffee': ['coffee'],
  '**/*.tea': ['coffee'],
  '**/*.html': ['html2js']
},
```

Note: There are multiple expressions referencing the "coffee" preprocessor in this example, as a preprocessor
can be listed more than once as another way to specify multiple file path expressions.

Note: Most of the preprocessors need to be loaded as [plugins].

## Available Preprocessors
- [coffee]
- [html2js]
  - Note any .html files listed in the files section must be referenced at run time as `window.__html__['template.html']`. [Learn more](https://github.com/karma-runner/karma-html2js-preprocessor#how-does-it-work-).
  - If this preprocessor is disabled, included .html files will need `base/` added to beginning of their path reference. See [discussion in issue 788][issue788].
- [coverage]
- [ng-html2js]
- [many more](https://www.npmjs.com/search?q=keywords:karma-preprocessor)

Here's an example of how to add the CoffeScript preprocessor to your testing suite:

```bash
# Install it first with npm
$ npm install karma-coffee-preprocessor --save-dev
```

And then inside your configuration file...

```javascript
module.exports = function(config) {
  config.set({
    preprocessors: {
      '**/*.coffee': ['coffee']
    }
  });
};
```

Of course, you can write [custom plugins] too!


## Configured Preprocessors
Some of the preprocessors can also be configured:

```javascript
coffeePreprocessor: {
  options: {
    bare: false
  }
}
```

Or define a configured preprocessor:

```javascript
customPreprocessors: {
  bare_coffee: {
    base: 'coffee',
    options: {bare: true}
  }
}
```


## Mini matching
The keys of the preprocessors config object are used to filter the files specified in
the `files` configuration.

* First the file paths are expanded to an absolute path, based on the
  `basePath` configuration and the directory of the configuration file. See
  [files] for more information on that.
* Then the newly expanded path is matched using [minimatch] against the specified key.

So for example the path `/my/absolute/path/to/test/unit/file.coffee` matched against
the key `**/*.coffee` would return `true`, but matched against just `*.coffee` it would
return `false` and the preprocessor would not be executed on the CoffeeScript files.



[files]: files.html
[minimatch]: https://github.com/isaacs/minimatch
[coffee]: https://github.com/karma-runner/karma-coffee-preprocessor
[html2js]: https://github.com/karma-runner/karma-html2js-preprocessor
[ng-html2js]: https://github.com/karma-runner/karma-ng-html2js-preprocessor
[coverage]: https://github.com/karma-runner/karma-coverage
[custom plugins]: ../dev/plugins.html
[plugins]: plugins.html
[issue788]: https://github.com/karma-runner/karma/issues/788

## Order of execution

If a file matches only one key in the preprocessors config object, then karma
will execute the preprocessors over that file in the order they are listed in
the corresponding array. So for instance, if the config object is:

```js
preprocessors: {
  '*.js': ['a', 'b']
}
```

Then karma will execute `'a'` before executing `'b'`.

If a file matches multiple keys, karma will use the `config.preprocessor_priority` map to control the execution order. The `config.preprocessor_priority` should be an object with property names equal to the preprocessor names and property values equal to the priority of execution. Higher priority preprocessors are run earlier. The default priority is 0.

If this config option is not set, karma will do its best to execute the preprocessors in a reasonable order. So if you have:

```js
preprocessors: {
  '*.js': ['a', 'b'],
  'a.*': ['b', 'c']
}
```

then for `a.js`, karma will run `'a'` then `'b'` then `'c'`.  If two lists contradict each other, like:
```js
preprocessors: {
  '*.js': ['a', 'b'],
  'a.*': ['b', 'a']
}
```

then karma will arbitrarily pick one list to prioritize over the other.  In a
case like:

```js
preprocessors: {
  '*.js': ['a', 'b', 'c'],
  'a.*': ['c', 'b', 'd']
}
```

Then `'a'` will definitely be run first, `'d'` will definitely be run last, but
it's arbitrary if karma will run `'b'` before `'c'` or vice versa.

---

### Config 05 Plugins (`docs/config/05-plugins.md`)

Karma can be easily extended through plugins. In fact, all the existing preprocessors, reporters, browser launchers and frameworks are plugins. 

You can install [existing plugins] from npm or you can write [your own plugins][developing plugins] for Karma.

## Installing Plugins

The recommended way to install plugins is to add them as project dependencies in your `package.json`:

```json
{
  "devDependencies": {
    "karma": "~0.10",
    "karma-mocha": "~0.0.1",
    "karma-growl-reporter": "~0.0.1",
    "karma-firefox-launcher": "~0.0.1"
  }
}
```

Therefore, a simple way to install a plugin is:

```bash
npm install karma-<plugin name> --save-dev
```

## Loading Plugins

By default, Karma loads plugins from all sibling npm packages which have a name starting with `karma-*`.

You can also override this behavior and explicitly list plugins you want to load via the `plugins` configuration setting:

```javascript
config.set({
  plugins: [
    // Load a plugin you installed from npm.
    require('karma-jasmine'),

    // Load a plugin from the file in your project.
    require('./my-custom-plugin'),
  
    // Define a plugin inline.
    { 'framework:xyz': ['factory', factoryFn] },

    // Specify a module name or path which Karma will require() and load its 
    // default export as a plugin.
    'karma-chrome-launcher',
    './my-fancy-plugin'
  ]
})
```

## Activating Plugins

Adding a plugin to the `plugins` array only makes Karma aware of the plugin, but it does not activate it. Depending on the plugin type you'll need to add a plugin name into `frameworks`, `reporters`, `preprocessors`, `middleware` or `browsers` configuration key to activate it. For the detailed information refer to the corresponding plugin documentation or check out [Developing plugins][developing plugins] guide for more in-depth explanation of how plugins work.

[existing plugins]: https://www.npmjs.com/search?q=keywords:karma-plugin
[developing plugins]: ../dev/plugins.html

---

### Dev 01 Contributing (`docs/dev/01-contributing.md`)

---
pageTitle: Contributing to Karma
---

**Working on your first Pull Request?** You can learn how from this *free* series
[How to Contribute to an Open Source Project on GitHub]

You want to contribute to Karma? That is truly great!
Here are some tips to get you started...

### Help others
The best way to start contributing to any open source project is to help other people.
You can answer questions on the [Gitter] or [Stack Overflow].
Either find something you already know the answer for, or something you feel interested in and
dig into it a little bit to find the answer.

Soon, you will realize you know Karma pretty well...


### Improve the documentation
You don’t feel like hacking on the code, but still want to help?
Improving the documentation is very valuable as it will help many others.

All the source code is in [`docs/`].


### Fix something that bothers you
Did you find a bug that really bothers you? It’s more likely it bothers other users too, and maybe
it’s not that hard to fix it! Try to find an existing issue. If it does not exist yet, create one.
Look into the code and let others know what solution you are thinking about.
Then, send a pull request and let other contributors review.

[Here](./making-changes.html) is some more info on how to set up your workspace and send a pull
request.


### Fix something else
You want to contribute some code but not sure where to start? That's cool. Fortunately,
there are many issues labeled as "PR please". These are typically fairly simple issues with
a well-known, waiting just for you...

[Here](https://github.com/karma-runner/karma/issues?labels=PR+please&page=1&state=open) is a list
of all the issues for the core repo. In the same way, each plugin has "PR please" label as well...


### Review others work
Check out the list of outstanding pull requests if there is something you might be interested in.
Maybe somebody is trying to fix that stupid bug that bothers you. Review the PR.
Do you have any better ideas how to fix this problem? Let us know...

### I want to help more
Check out [Maintaining Karma]. Becoming a Karma maintainer is simple.
You just do it. There is no test to pass ;-)

[gitter]: https://gitter.im/karma-runner/karma
[Stack Overflow]: https://stackoverflow.com/questions/tagged/karma-runner
[`docs/`]: https://github.com/karma-runner/karma/tree/master/docs
[Maintaining Karma]: ./maintaining.html
[How to Contribute to an Open Source Project on GitHub]: https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github

---

### Dev 02 Making Changes (`docs/dev/02-making-changes.md`)

If you are thinking about making Karma better, or you just want to hack on it, that’s great!
Here are some tips on how to set up a Karma workspace and how to send a good pull request.

## Setting up the Workspace

* Make sure you have a [GitHub account](https://github.com/signup/free).
* [Fork the repository] on GitHub.
* Clone your fork
  ```bash
  $ git clone https://github.com/<your-username>/karma.git
  $ cd karma
  ```
* Install for development
  ```bash
  $ npm install
  ```

## Testing and Building
- Run the tests via:
  ```bash
  $ npm test
  # or you can run test suits individually
  $ npm run test:unit
  $ npm run test:e2e
  $ npm run test:client
  ```

- Lint the code via:
  ```bash
  $ npm run lint
  # or you can also apply auto-fixes where possible
  $ npm run lint:fix
  ```

- Build the client code via:
  ```bash
  $ npm run build
  # or use the watch mode
  $ npm run build:watch
  ```

## Changing the Code
Checkout a new branch and name it accordingly to what you intend to do:
- Features get the prefix `feature-`.
- Bug fixes get the prefix `fix-`.
- Improvements to the documentation get the prefix `docs-`.
```bash
$ git checkout -b <branch_name>
```

Open your favorite editor, make some changes, run the tests, change the code, run the tests,
change the code, run the tests, etc.

- Please follow http://nodeguide.com/style.html (with exception of 100 characters per line).


## Sending a Pull Request

- Commit your changes (please follow [commit message conventions]):
  ```bash
  $ git commit -m "..."
  ```
- Verify that the last commit follows the conventions:
  ```bash
  $ npm run commit:check
  ```
- Push to your GitHub repo:
  ```bash
  $ git push origin <branch_name>
  ```
- Go to the GitHub page and click "Open a Pull request".
- Write a good description of the change.

After sending a pull request, other developers will review and discuss your change.
Please address all the comments. Once everything is all right, one of the maintainers will merge
your changes in.


## Contributor License Agreement
Please sign our Contributor License Agreement (CLA) before sending pull requests.
For any code changes to be accepted, the CLA must be signed. It's a quick process, we promise!
- For individuals, we have a [simple click-through form].
- For corporations we'll need you to print, sign and one of scan+email, fax or mail [the form].

## Additional Resources

- [Mailing List](https://groups.google.com/forum/#!forum/karma-users)
- [Issue tracker](https://github.com/karma-runner/karma/issues)
- [General GitHub documentation](https://docs.github.com/)
- [GitHub pull request documentation](https://docs.github.com/github/collaborating-with-issues-and-pull-requests/about-pull-requests#about-pull-requests)

[commit message conventions]: git-commit-msg.html
[simple click-through form]: https://code.google.com/legal/individual-cla-v1.0.html
[the form]: https://code.google.com/legal/corporate-cla-v1.0.html
[Fork the repository]: https://github.com/karma-runner/karma/fork

---

### Dev 03 Maintaining (`docs/dev/03-maintaining.md`)

---
pageTitle: Maintaining Karma
---

This document is for people working on Karma. It describes common tasks such as triaging or merging
pull requests.

If you are interested in contributing to Karma, you might check out [Contributing to Karma].

We use [gitter/karma-runner] to talk about pull requests and issues, stuff like,
“hey this is important, can you look into it...”, “I’m not sure what to do about this issue...”.


## Triaging issues
New issues pop up every day. We need to identify urgent issues (such as “nobody can install karma”),
close duplicates, answer questions, etc.

See [angular/TRIAGING.md] for more info.

An issue or pull request is untriaged (needs to be triaged) when it is not assigned to any milestone.

## Merging a pull request
Please, make sure:
- CI build is green.
- At least one owner (other than you) approved the PR
  - by commenting “LGTM” or something like that.
  - if it’s just a simple docs change or a typo fix, feel free to skip this step.
- All the commits follow the [convention].
  - This is very important, because the auto-release tasks depend on it.
  - Commits are squashed. Each change is a single commit.
    - e.g. if the PR contains two changes such as, `fix(web-server): xxx` and then `style(web-server): missing semicolons`; it should be two separate changes
    - e.g. if the first commit is `fix(web-server): serve binary files` and a second commit is “fix unit tests broken in the previous commit”, you should squash them into a single commit.
  - It’s alright to ask the author of the pull request to fix any of the above.

## Releasing npm
For core collaborators with admin rights.
- Be on a good network that won't go down in the middle.
- Make sure you are sync to upstream master.
- `echo $GH_TOKEN`
  - If not set, set GH_TOKEN from https://github.com/settings/tokens/new
- `npm login karmarunnerbot`
  - The password is known to authorized releasers.
- `grunt release`
If the release fails, check the state of the git tags pushed to github.  You may have to delete one.


## Ownership
Every project has one or more owners (or “maintainers”), listed in `owners` field of the
`package.json`. Typically, owners have push permissions.

Being a maintainer of one plugin doesn’t mean you can’t contribute to some other plugins.
In fact, you can be a maintainer of multiple projects. The main point is to have people who are
familiar with the codebase and therefore can better decide what a good change is or not.


## Becoming a maintainer
If you are interested in becoming a Karma maintainer, start by triaging issues, reviewing pull
requests and stop by at [gitter/karma-runner]. Once we see you are helping, we will give you push
permissions. Being a maintainer is not an obligation. You can help when you have time and be less
active when you don’t. If you get a new job and get busy, that’s alright.

These are all just recommendations, something we found to be helpful for us to be more efficient.
Nothing is set in a stone. If you feel like there is a way to improve this workflow,
please send a proposal to [karma-devs@googlegroups.com](mailto:karma-devs@googlegroups.com).

[gitter/karma-runner]: https://gitter.im/karma-runner
[convention]: https://karma-runner.github.io/latest/dev/git-commit-msg.html
[fetch_pr]: https://github.com/vojtajina/dotfiles/blob/master/bin/fetch_pr
[merge_pr]: https://github.com/vojtajina/dotfiles/blob/master/bin/merge_pr
[Contributing to Karma]: ./contributing.html
[angular/TRIAGING.md]: https://github.com/angular/angular.js/blob/master/TRIAGING.md

---

### Dev 04 Public Api (`docs/dev/04-public-api.md`)

Most of the time, you will be using Karma directly from the command line.
You can, however, call Karma programmatically from your node module. Here is the public API.


## karma.Server(options, [callback=process.exit])

### `constructor`

- **Returns:** `Server` instance.

#### Usage

Notice the capital 'S' on  `require('karma').Server`.

##### Deprecated Behavior

The following still works, but the way it behaves is deprecated and will be
changed in a future major version.

```javascript
var Server = require('karma').Server
var karmaConfig = {port: 9876}
var server = new Server(karmaConfig, function(exitCode) {
  console.log('Karma has exited with ' + exitCode)
  process.exit(exitCode)
})
```

##### New Behavior

```javascript
const karma = require('karma')
const parseConfig = karma.config.parseConfig
const Server = karma.Server

parseConfig(
  null,
  { port: 9876 },
  { promiseConfig: true, throwErrors: true }
).then(
  (karmaConfig) => {
    const server = new Server(karmaConfig, function doneCallback(exitCode) {
      console.log('Karma has exited with ' + exitCode)
      process.exit(exitCode)
    })
  },
  (rejectReason) => { /* respond to the rejection reason error */ }
);
```

### `server.start()`

Equivalent of `karma start`.

```javascript
server.start()
```

### `server.refreshFiles()`

Trigger a file list refresh. Returns a promise.

```javascript
server.refreshFiles()
```

### `server.refreshFile(path)`

Trigger a file refresh. Returns a promise.

```javascript
server.refreshFile('src/js/module-dep.js')
```

### Events

The `server` object is an [`EventEmitter`](https://nodejs.org/docs/latest/api/events.html#events_class_events_eventemitter). You can simply listen to events like this:

```javascript
server.on('browser_register', function (browser) {
  console.log('A new browser was registered')
})
```

### `listening`
**Arguments:**

* `port`: Port number

Begin accepting connections on the specified port.

### `browser_register`
**Arguments:**

* `browser`: The browser instance

A new browser was opened, but is not ready yet.

### `browser_error`
**Arguments:**

* `browser`: The browser instance
* `error`: The error that occurred

There was an error in this browser instance.

### `browser_start`
**Arguments:**

* `browser`: The browser instance
* `info`: Details about the run

A test run is beginning in this browser.

### `browser_complete`
**Arguments:**

* `browser`: The browser instance
* `result`: Test results

A test run has completed in this browser.

### `browsers_change`
**Arguments:**

* `browsers`: A collection of browser instances

The list of browsers has changed.

### `browsers_ready`

All browsers are ready for execution

### `run_start`
**Arguments:**

* `browsers`: A collection of browser instances on which tests are executed

A test run starts.

### `run_complete`
**Arguments:**

* `browsers`: A collection of browser instances
* `results`: A list of results

This event gets triggered whenever all the browsers, which belong to a test run, finish. For example, on a run that has 3 browsers, one would expect 3 `browser_complete` events before the `run_complete` one.

## karma.runner

### `runner.run(options, [callback=process.exit])`

- **Returns:** `EventEmitter`

The equivalent of `karma run`.

#### Usage

##### Deprecated Behavior

The following still works, but the way it behaves is deprecated and will be
changed in a future major version.

```javascript
var runner = require('karma').runner
runner.run({port: 9876}, function(exitCode) {
  console.log('Karma has exited with ' + exitCode)
  process.exit(exitCode)
})
```

##### New Behavior

```javascript
const karma = require('karma')

karma.config.parseConfig(
  null,
  { port: 9876 },
  { promiseConfig: true, throwErrors: true }
).then(
  (karmaConfig) => {
    karma.runner.run(karmaConfig, function doneCallback(exitCode, possibleErrorCode) {
      console.log('Karma has exited with ' + exitCode)
      process.exit(exitCode)
    })
  },
  (rejectReason) => { /* respond to the rejection reason error */ }
);
```

#### `callback` argument

The callback receives the exit code as the first argument.

If there is an error, the error code will be provided as the second parameter to
the error callback.

#### runner Events

`runner.run()` returns an `EventEmitter` which emits a `progress` event passing
the reporter output as a `Buffer` object.

You may listen for that event to print the reporter output to the console:

```javascript
runner.run({port: 9876}).on('progress', function(data) {
  process.stdout.write(data)
})
```

## karma.stopper

### `stopper.stop(options, [callback=process.exit])`

This function will signal a running server to stop. The equivalent of
`karma stop`.

#### Usage

##### Deprecated Behavior

The following still works, but the way it behaves is deprecated and will be
changed in a future major version.

```javascript
var stopper = require('karma').stopper
stopper.stop({port: 9876}, function(exitCode) {
  if (exitCode === 0) {
    console.log('Server stop as initiated')
  }
  process.exit(exitCode)
})
```

##### New Behavior

```javascript
const karma = require('karma')

karma.config.parseConfig(
  null,
  { port: 9876 },
  { promiseConfig: true, throwErrors: true }
).then(
  (karmaConfig) => {
    karma.stopper.stop(karmaConfig, function doneCallback(exitCode, possibleErrorCode) {
      if (exitCode === 0) {
        console.log('Server stop as initiated')
      }
      process.exit(exitCode)
    })
  },
  (rejectReason) => { /* respond to the rejection reason error */ }
);
```

#### `callback` argument

The callback receives the exit code as the first argument.

If there is an error, the error code will be provided as the second parameter to
the error callback.

## karma.config

### `config.parseConfig([configFilePath], [cliOptions], [parseOptions])`

This function will load given config file and returns a filled config object.
This can be useful if you want to integrate karma into another tool and want to load
the karma config while honoring the karma defaults.

#### Usage

##### Deprecated Behavior

The following still works, but the way it behaves is deprecated and will be
changed in a future major version.

```javascript
const cfg = require('karma').config;
const path = require('path');
// Read karma.conf.js, but override port with 1337
const karmaConfig = cfg.parseConfig(
  path.resolve('./karma.conf.js'),
  { port: 1337 }
);
```

The new behavior in the future will involve throwing exceptions instead of
exiting the process and asynchronous config files will be supported through the
use of promises.

##### New Behavior

```javascript
const cfg = require('karma').config;
const path = require('path');
// Read karma.conf.js, but override port with 1337
cfg.parseConfig(
  path.resolve('./karma.conf.js'),
  { port: 1337 },
  { promiseConfig: true, throwErrors: true }
).then(
  (karmaConfig) => { /* use the config with the public API */ },
  (rejectReason) => { /* respond to the rejection reason error */ }
);
```


#### `configFilePath` argument

- **Type:** String | `null` | `undefined`
- **Default Value:** `undefined`

A string representing a file system path pointing to the config file whose
default export is a function that will be used to set Karma configuration
options. This function will be passed an instance of the `Config` class as its
first argument. If this option is not provided, then only the options provided
by the `cliOptions` argument will be set.

- JavaScript must use CommonJS modules.
- ECMAScript modules are not currently supported by Karma when using
    JavaScript.
    - Other formats, such as TypeScript, may support ECMAScript modules.


#### `cliOptions` argument

- **Type:** Object | `null` | `undefined`
- **Default Value:** `undefined`

An object whose values will take priority over options set in the config file.
The config object passed to function exported by the config file will already
have these options applied. Any changes the config file makes to these options
will effectively be ignored in the final configuration.

Supports all the same options as the config file and is applied using the same
`config.set()` method.

The expected source of this argument is parsed command line options, but 
programatic users may construct this object or leave it out entirely.


#### `parseOptions` argument

- **Type:** Object | `null` | `undefined`
- **Default Value:** `undefined`

`parseOptions` is an object whose properties are configuration options that
allow additional control over parsing and opt-in access to new behaviors or
features.

These options are only related to parsing configuration files and object and are
not related to the configuration of Karma itself.


##### `parseOptions.promiseConfig` option

- **Type:** Boolean
- **Default Value:** `false`

When `parseOptions.promiseConfig === true`, then `parseConfig` will return a
promise instead of a configuration object.

When this option is `true`, then the function exported by the config file may
return a promise. The resolution of that promise indicates that all asynchronous
activity has been completed. Internally, the resolved/fulfilled value is 
ignored. As with synchronous usage, all changes to the config object must be
done with the `config.set()` method.

If the function exported by the config file does not return a promise, then
parsing is completed and an immediately fulfilled promise is returned.

Whether the function exported by the config file returns a promise or not, the
promise returned by `parseConfig()` will resolve with a parsed configuration
object, an instance of the `Config` class, as the value.

_**In most cases, `parseOptions.throwErrors = true` should also be set. This
disables process exiting and allows errors to result in rejected promises.**_


##### `parseOptions.throwErrors` option

- **Type:** Boolean
- **Default Value:** `false`

In the past, `parseConfig()` would call `process.exit(exitCode)` when it
encountered a critical failure. This meant that your own code had no way of
responding to failures before the Node.js process exited.

By passing `parseOptions.throwErrors = true`, `parseConfig()` will disable
process exiting.

For synchronous usage, it will throw an exception instead of exiting the
process. Your code can then catch the exception and respond how ever it needs
to.

If the asynchronous API (`parseOptions.promiseConfig = true`) is being used,
then `parseOptions.throwErrors = true` allows the promise to be rejected
instead of exiting the process.


## `karma.constants`

### `constants.VERSION`

The current version of karma

### `constants.DEFAULT_PORT`

The default port used for the karma server

### `constants.DEFAULT_HOSTNAME`

The default hostname used for the karma server

### `constants.DEFAULT_LISTEN_ADDR`

The default address use for the karma server to listen on

### `constants.LOG_DISABLE`

The value for disabling logs

### `constants.LOG_ERROR`

The value for the log `error` level

### `constants.LOG_WARN`

The value for the log `warn` level

### `constants.LOG_INFO`

The value for the log `info` level

### `constants.LOG_DEBUG`

The value for the log `debug` level

### `constants.LOG_PRIORITIES`

An array of log levels in descending order, i.e. `LOG_DISABLE`, `LOG_ERROR`, `LOG_WARN`, `LOG_INFO`, and `LOG_DEBUG`

### `constants.COLOR_PATTERN`

The default color pattern for log output

### `constants.NO_COLOR_PATTERN`

The default pattern for log output without color

### `constants.CONSOLE_APPENDER`

The default console appender

### `constants.EXIT_CODE`

The exit code

---

### Dev 05 Plugins (`docs/dev/05-plugins.md`)

---
pageTitle: Developing Plugins
---

Karma can be extended through plugins. There are five kinds of plugins: *framework*, *reporter*, *launcher*, *preprocessor* and *middleware*. Each type allows to modify a certain aspect of the Karma behavior.

- A *framework* connects a testing framework (like Mocha) to a Karma API, so browser can send test results back to a Karma server.
- A *reporter* defines how test results are reported to a user.
- A *launcher* allows Karma to launch different browsers to run tests in.
- A *preprocessor* is responsible for transforming/transpiling source files before loading them into a browser.
- A *middleware* can be used to customise how files are served to a browser.

## Dependency injection

Karma is assembled using [*dependency injection*](https://en.wikipedia.org/wiki/Dependency_injection). It is important to understand this concept to be able to develop plugins.

On the very high level you can think of Karma as an object where each key (a *DI token*) is mapped to a certain Karma object (a *service*). For example, `config` DI token maps to `Config` instance, which holds current Karma configuration. Plugins can request (or *inject*) various Karma objects by specifying a corresponding DI token. Upon injection a plugin can interact with injected services to implement their functionality.

There is no exhaustive list of all available services and their DI tokens, but you can discover them by reading Karma's or other plugins' source code.

## Plugin structure

Each plugin is essentially a service with its associated DI token. When user [activates a plugin][plugins] in their config, Karma looks for a corresponding DI token and instantiates a service linked to this DI token.

To declare a plugin one should define a DI token for the plugin and explain Karma how to instantiate it. A DI token consists of two parts: a plugin type and plugin's unique name. The former defines what a plugin can do, requirements to the service's API and when it is instantiated. The latter is a unique name, which a plugin user will use to activate a plugin. 

It is totally valid for a plugin to define multiple services. This can be done by adding more keys to the object exported by the plugin. Common example of this would be `framework` + `reporter` plugins, which usually come together.

Let's make a very simple plugin, which prints "Hello, world!" when instantiated. We'll use a `framework` type as it is instantiated early in the Karma lifecycle and does not have any requirements to its API. Let's call our plugin "hello", so its unique name will be `hello`. Joining these two parts we get a DI token for our plugin `framework:hello`. Let's declare it.

```js
// hello-plugin.js

// A factory function for our plugin, it will be called, when Karma needs to
// instantiate a plugin. Normally it should return an instance of the service
// conforming to the API requirements of the plugin type (more on that below),
// but for our simple example we don't need any service and just print 
// a message when function is called.
function helloFrameworkFactory() {
  console.log('Hello, world!')
}

module.exports = {
  // Declare the plugin, so Karma knows that it exists.
  // 'factory' tells Karma that it should call `helloFrameworkFactory`
  // function and use whatever it returns as a service for the DI token
  // `framework:hello`.
  'framework:hello': ['factory', helloFrameworkFactory]
};
```

```js
// karma.conf.js

module.exports = (config) => {
  config.set({
    plugins: [
      require('./hello-plugin')
    ],
    // Activate our plugin by specifying its unique name in the 
    // corresponding configuration key.
    frameworks: ['hello']
  })
}
```

## Injecting dependencies

In "Dependency injection" section we discussed that it is possible to inject any Karma services into a plugin and interact with them. This can be done by setting an `$inject` property on the plugin's factory function to an array of DI tokens plugin wishes to interact with. Karma will pick up this property and pass requested services to the factory functions as parameters.

Let's make the `hello` framework a bit more useful and make it add `hello.js` file to the `files` array. This way users of the plugin can, for example, access a function defined in `hello.js` from their tests.

```js
// hello-plugin.js

// Add parameters to the function to receive requested services.
function helloFrameworkFactory(config) {
  config.files.unshift({
    pattern: __dirname + '/hello.js',
    included: true,
    served: true,
    watched: false
  })
}

// Declare DI tokens plugin wants to inject.
helloFrameworkFactory.$inject = ['config']

module.exports = {
  'framework:hello': ['factory', helloFrameworkFactory]
};
```

The Karma config is unchanged and is omitted for brevity. See above example for the plugin usage.

Note: Currently, Karma uses [node-di] library as a DI implementation. The library is more powerful than what's documented above, however, the DI implementation may change in the future, so we recommend not to rely on the node-di implementation details.

## Plugin types

This section outlines API requirements and conventions for different plugin types. There also links to some plugins, which you can use for inspiration.

### Frameworks

- example plugins: [karma-jasmine], [karma-mocha], [karma-requirejs]
- use naming convention is `karma-*`
- use npm keywords `karma-plugin`, `karma-framework`.

A framework connects existing testing libraries to Karma's API, so that their results can be displayed in a browser and sent back to the server.

Karma frameworks _must_ implement a `window.__karma__.start` method that Karma will
call to start test execution. This function is called with an object that has methods
to send results back to karma:

* `.result` a single test has finished
* `.complete` the client completed execution of all the tests
* `.error` an error happened in the client
* `.info` other data (e.g. number of tests or debugging messages)

Most commonly you'll use the `result` method to send individual test success or failure
statuses. The method takes an object of the form:

```js
{
    // test id
    id: String,

     // test description
    description: String,

    // the suite to which this test belongs. potentially nested.
    suite: Array[String],

    // an array of string error messages that might explain a failure.
    // this is required if success is false.
    log: Array[String],

    success: Boolean, // pass / fail

    skipped: Boolean // skipped / ran
}
```

### Reporters

- example plugins: [karma-growl-reporter], [karma-junit-reporter], [karma-material-reporter]
- use naming convention is `karma-*-reporter`
- use npm keywords `karma-plugin`, `karma-reporter`

### Launchers

- example plugins: [karma-chrome-launcher], [karma-sauce-launcher]
- use naming convention is `karma-*-launcher`
- use npm keywords `karma-plugin`, `karma-launcher`

### Preprocessors

- example plugins: [karma-coffee-preprocessor], [karma-ng-html2js-preprocessor]
- use naming convention is `karma-*-preprocessor`
- user npm keywords `karma-plugin`, `karma-preprocessor`

A preprocessor is a function that accepts three arguments (`content`, `file`, and `next`), mutates the content in some way, and passes it on to the next preprocessor.

- arguments passed to preprocessor plugins:
  - **`content`** of the file being processed
  - **`file`** object describing the file being processed
     - **path:** the current file, mutable file path. e. g. `some/file.coffee` -> `some/file.coffee.js` _This path is mutable and may not actually exist._
     - **originalPath:** the original, unmutated path
     - **encodings:** A mutable, keyed object where the keys are a valid encoding type ('gzip', 'compress', 'br', etc.) and the values are the encoded content. Encoded content should be stored here and not resolved using `next(null, encodedContent)`
     - **type:** determines how to include a file, when serving
  - **`next`** function to be called when preprocessing is complete, should be called as `next(null, processedContent)` or `next(error)`

### Crazier stuff

As Karma is assembled by dependency injection, a plugin can ask for pretty much any Karma component and interact with it. There are a couple of plugins that do more interesting stuff like this, check out [karma-closure], [karma-intellij].

[karma-jasmine]: https://github.com/karma-runner/karma-jasmine
[karma-mocha]: https://github.com/karma-runner/karma-mocha
[karma-requirejs]: https://github.com/karma-runner/karma-requirejs
[karma-growl-reporter]: https://github.com/karma-runner/karma-growl-reporter
[karma-junit-reporter]: https://github.com/karma-runner/karma-junit-reporter
[karma-chrome-launcher]: https://github.com/karma-runner/karma-chrome-launcher
[karma-sauce-launcher]: https://github.com/karma-runner/karma-sauce-launcher
[karma-coffee-preprocessor]: https://github.com/karma-runner/karma-coffee-preprocessor
[karma-ng-html2js-preprocessor]: https://github.com/karma-runner/karma-ng-html2js-preprocessor
[karma-closure]: https://github.com/karma-runner/karma-closure
[karma-intellij]: https://github.com/karma-runner/karma-intellij
[node-di]: https://github.com/vojtajina/node-di
[karma-material-reporter]: https://github.com/ameerthehacker/karma-material-reporter
[plugins]: ../config/plugins.html

---

### Dev 06 Git Commit Msg (`docs/dev/06-git-commit-msg.md`)

---
showInMenu: false
---

In the repository we use and enforce the commit message conventions. The conventions are verified using [commitlint] with [Angular config](https://www.npmjs.com/package/@commitlint/config-angular).

## The reasons for these conventions:
- automatic generating of the changelog
- simple navigation through git history (e.g. ignoring style changes)

## Format of the commit message:
```bash
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
```

## Example commit message:

```bash
fix(middleware): ensure Range headers adhere more closely to RFC 2616

Add one new dependency, use `range-parser` (Express dependency) to compute
range. It is more well-tested in the wild.

Fixes #2310
```

## Message subject (first line)
The first line cannot be longer than 72 characters and should be followed by a blank line. The type and scope should always be lowercase as shown below.

### Allowed `<type>` values:

* **feat** for a new feature for the user, not a new feature for build script. Such commit will trigger a release bumping a MINOR version.
* **fix** for a bug fix for the user, not a fix to a build script. Such commit will trigger a release bumping a PATCH version.
* **perf** for performance improvements. Such commit will trigger a release bumping a PATCH version.
* **docs** for changes to the documentation.
* **style** for formatting changes, missing semicolons, etc.
* **refactor** for refactoring production code, e.g. renaming a variable.
* **test** for adding missing tests, refactoring tests; no production code change.
* **build** for updating build configuration, development tools or other changes irrelevant to the user.

### Example `<scope>` values:

* init
* runner
* watcher
* config
* web-server
* proxy
* etc.

The `<scope>` can be empty (e.g. if the change is a global or difficult
to assign to a single component), in which case the parentheses are
omitted. In smaller projects such as Karma plugins, the `<scope>` is empty.

## Message body

Just as in the `<subject>`, use the imperative, present tense: "change" not "changed" nor "changes". Message body should include motivation for the change and contrasts with previous behavior.

## Message footer

### Referencing issues
Closed issues should be listed on a separate line in the footer prefixed with "Closes" keyword like this:
```bash
Closes #234
```
or in the case of multiple issues:
```bash
Closes #123, #245, #992
```
### Breaking changes

All breaking changes have to be mentioned in footer with the
description of the change, justification and migration notes.
```bash
BREAKING CHANGE:

`port-runner` command line option has changed to `runner-port`, so that it is
consistent with the configuration file syntax.

To migrate your project, change all the commands, where you use `--port-runner`
to `--runner-port`.
```

Any commit with the breaking change section will trigger a MAJOR release and appear on the changelog independently of the commit type.

---

This document is based on [Angular Commit Message Format]. See the [commit history] for examples of properly-formatted commit messages.

[commitlint]: https://conventional-changelog.github.io/commitlint/
[Angular config]: https://www.npmjs.com/package/@commitlint/config-angular
[Angular Commit Message Format]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
[commit history]: https://github.com/karma-runner/karma/commits/master

---

### Intro 01 Installation (`docs/intro/01-installation.md`)

Karma runs on [Node.js] and is available as an [npm] package.

## Installing Node.js

On Mac or Linux we recommend using [NVM](https://github.com/creationix/nvm). On Windows, download Node.js
from [the official site](https://nodejs.org/) or use the [NVM PowerShell Module](https://www.powershellgallery.com/packages/nvm).

Karma works on all [LTS releases](https://nodejs.org/en/about/releases/) of Node.js.

## Installing Karma and plugins

The recommended approach is to install Karma (and all the plugins your project needs) locally in
the project's directory.

```bash
# Install Karma:
$ npm install karma --save-dev

# Install plugins that your project needs:
$ npm install karma-jasmine karma-chrome-launcher jasmine-core --save-dev

```

This will install `karma`, `karma-jasmine`, `karma-chrome-launcher` and `jasmine-core` packages into `node_modules` in your current
working directory and also save these as `devDependencies` in `package.json`, so that any
other developer working on the project will only have to do `npm install` in order to get all these
dependencies installed.

```bash
# Run Karma:
$ ./node_modules/karma/bin/karma start
```

## Commandline Interface
Typing `./node_modules/karma/bin/karma start` sucks and so you might find it useful to install `karma-cli` globally. You will need to do this if you want to run Karma on Windows from the command line.

```bash
$ npm install karma-cli
```

Then, you can run Karma simply by `karma` from anywhere and it will always run the local version.


[Node.js]: https://nodejs.org/
[npm]: https://www.npmjs.com/package/karma
[NVM]: https://github.com/creationix/nvm
[FAQ]: ./faq.html

---

### Intro 02 Configuration (`docs/intro/02-configuration.md`)

In order to serve you well, Karma needs to know about your project in order to test it
and this is done via a configuration file. This page explains how to create such a configuration file.

See [configuration file docs] for more information about the syntax and all the available options.

## Generating the config file

The configuration file can be generated using `karma init`:
```bash
$ karma init my.conf.js

Which testing framework do you want to use?
Press tab to list possible options. Enter to move to the next question.
> jasmine

Do you want to use Require.js?
This will add Require.js plugin.
Press tab to list possible options. Enter to move to the next question.
> no

Do you want to capture a browser automatically?
Press tab to list possible options. Enter empty string to move to the next question.
> Chrome
> Firefox
>

What is the location of your source and test files?
You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js".
Press Enter to move to the next question.
> *.js
> test/**/*.js
>

Should any of the files included by the previous patterns be excluded?
You can use glob patterns, eg. "**/*.swp".
Press Enter to move to the next question.
>

Do you want Karma to watch all the files and run the tests on change?
Press tab to list possible options.
> yes

Config file generated at "/Users/vojta/Code/karma/my.conf.js".
```

The configuration file can be written in CoffeeScript as well.
In fact, if you execute `karma init` with a `*.coffee` extension such as `karma init karma.conf.coffee`, it will generate a CoffeeScript file.

Of course, you can write the config file by hand or copy-paste it from another project ;-)

## Starting Karma
When starting Karma, the configuration file path can be passed in as the first argument.

By default, Karma will look for `karma.conf.js` or `karma.conf.coffee` in the current directory.
```bash
# Start Karma using your configuration:
$ karma start my.conf.js
```

For more detailed information about the Karma configuration file, such as available options and features,
please read the [configuration file docs].

## Command line arguments
Some configurations, which are already present within the configuration file, can be overridden by specifying the configuration
as a command line argument for when Karma is executed.

```bash
karma start my.conf.js --log-level debug --single-run
```

Try `karma start --help` if you want to see all available options.


## Integrating with Grunt/Gulp
- [grunt-karma]
- [gulp-karma]


[configuration file docs]: ../config/configuration-file.html
[Grunt]: https://gruntjs.com/
[grunt-karma]: https://github.com/karma-runner/grunt-karma
[Gulp]: https://gulpjs.com
[gulp-karma]: https://github.com/karma-runner/gulp-karma

---

### Intro 03 How It Works (`docs/intro/03-how-it-works.md`)

Karma is essentially a tool which spawns a web server that executes source code against test code for each of the browsers connected.
The results of each test against each browser are examined and displayed via the command line to the developer
such that they can see which browsers and tests passed or failed.

A browser can be captured either
- manually, by visiting the URL where the Karma server is listening (typically `http://localhost:9876/`),
- or automatically by letting Karma know which browsers to start when Karma is run (see [browsers]).

Karma also watches all the files, specified within the configuration file, and whenever any file changes, it triggers the test run by
sending a signal to the testing server to inform all of the captured browsers to run the test code again.
Each browser then loads the source files inside an IFrame, executes the tests and reports the results back to the server.

The server collects the results from all of the captured browsers and presents them to the developer.

This is only a very brief overview, as the internals of how Karma works aren't entirely necessary when using Karma.

## Outline of workflow.

Here is roughly how Karma works:

After starting up, Karma loads plugins and the configuration file, then starts its local web server which listens for connections.
Any browser already waiting on websockets from the server will reconnect immediately. As part of loading the plugins, test reporters
register for 'browser' events so they are ready for test results.

Then karma launches zero, one, or more browsers, setting their start page the Karma server URL.

When the browsers connect, Karma serves a 'client.html' page; when this page runs in the browser it connects back to the server via websockets.

Once the server sees the websocket connection, it instructs the client -- over the websocket -- to execute tests.  The client page opens an iframe with a 'context.html' page from the server. The server generates this context.html page using the configuration. This page includes the test framework adapter, the code to be tested, and the test code.

When the browser loads this context page, the onload event handler connects the context page to the client page via postMessage. The framework adapter is in charge at this point: it runs the test, reporting errors or success by messaging through the client page.

Messages sent to the client page are forwarded through the websocket to the Karma server. The server re-dispatches these messages as 'browser' events.  The reporters listening to 'browser' events get the data; they may print it, save it to files, or forward the data to another service.
Since the data is sent by the test framework adapter to the reporter, adapters and reporters almost always come in pairs, like karma-jasmine and karma-jasmine-reporter.  The detailed content of test-result data is of no concern to other parts of karma: only the reporter needs to know its format.

Karma has many variations and options that may cause different workflow with different configurations.

If you are interested in learning more about the design, Karma itself originates from a university thesis, which goes into detail about the design
and implementation, and it is available to read [right here].

[right here]: https://github.com/karma-runner/karma/raw/master/thesis.pdf
[browsers]: ../config/browsers.html

---

### Intro 04 Faq (`docs/intro/04-faq.md`)

---
pageTitle: Frequently Asked Questions
menuTitle: FAQ
---

The list below is a collection of common questions regarding Karma and its use.
If you have any other questions in mind, please visit the [mailing list] to let the community know.


### Can I use Karma with testing framework X?
Yes. There are plugins for most of the common testing frameworks (such as Jasmine, Mocha, QUnit).
If there is no plugin for the testing framework you like, go ahead and write one. It is simple -
you can start by looking into the source code of the existing ones.


### Can I use Karma to do end to end testing?
Karma has primarily been designed for low level (unit) testing. If it's an AngularJS app, you can
use Karma with the [karma-ng-scenario] plugin. However, we recommend [Protractor] for high-level testing.


### Can I use Karma on Continuous Integration server ?
Of course! Check out the docs for [Jenkins], [Semaphore], [TeamCity] or [Travis].


### Which version of Karma should I use?
The latest stable version from npm (`npm install karma`). See [versioning] for more detailed information about Karma's release channels.


### Which version of Node.js does Karma run with?
Karma works on all LTS versions of Node.js as specified by the [Node.js Release Working Group](https://github.com/nodejs/Release/blob/master/README.md). The Node.js version numbers are set in the package.json. Older versions of karma work with older versions of Node.js, but are not maintained or updated.

[mailing list]: https://groups.google.com/d/forum/karma-users
[karma-ng-scenario]: https://github.com/karma-runner/karma-ng-scenario
[Protractor]: https://github.com/angular/protractor
[Jenkins]: ../plus/jenkins.html
[Semaphore]: ../plus/semaphore.html
[TeamCity]: ../plus/teamcity.html
[Travis]: ../plus/travis.html
[versioning]: ../about/versioning.html
[browsers]: ../config/browsers.html

---

### Intro 05 Troubleshooting (`docs/intro/05-troubleshooting.md`)

---
pageTitle: Troubleshooting
menuTitle: Troubleshooting
---

karma has an extensive set of tests and we have limited time to help with bugs. Here are some suggestions to get you unstuck.

### npm audit vulnerabilities
Please open a Pull Request that will fix the issue.

We get lots of these reports, from multiple automated services, from other projects, and from users. The vast majority are minor: please open a pull request if you want a fix. We only take direct action to fix serious issues that affect online users.

### How Do I Debug a karma issue?

Many issues can be solved by reading the `debug log` or by using the `browsers devtools`:

#### Use `--log-level debug` to investigate server-side issues, especially configuration issues.
The `DEBUG` log includes a copy of the final 'config': note that plugins can alter the config and sometimes the settings you applied do not give the result you expected. The log includes both core `karma` lines and lines from plugins: use the logging prefix to determine if your issue may need to be reported to a karma plugin.

#### Use `--no-single-run` to investigate browser-side issues, especially global errors in test files.
The `--no-single-run` option causes the server to print a URL and wait.  Open the URL in a browser and use the browsers devtools to investigate the problem. Typically you will want to open the URL, then click the DEBUG link in the upper right corner. That opens a new window with cleaner code for debugging.

#### Is your issue related to another tool?
Issues with Angular setups are probably better debugged by consulting with other Angular users.  Issues with coverage are probably related to your config, the compiler for coverage instrumentation, or possibly karma-coverage.

#### Use the source!
`karma` is all JavaScript code: perhaps you can debug your issue by adding logging?

### I'm getting an error during the installation related to the ```ws``` module, how can I solve it?
This is a common Windows [issue](https://github.com/einaros/ws/issues/178), the compilation of the native [ws](https://www.npmjs.com/package/ws) module fails. Anyways, ```ws``` has a fallback JS implementation which npm should take care using it. All you need to do is make sure that you're using an up-to-date version of npm. To do that you can:

#### Update npm
```$ npm install npm```

or

#### Do a fresh NodeJS install
If you have issues to update npm, you can just go to the [NodeJS](https://nodejs.org/) download the current version. It will come with the latest npm version.


### The browser just does not start. What's going on?
It's more likely Karma can't find the location of the browser binary (the execution file). You can fix this by setting
the appropriate environment variable with the correct path (Google Chrome, for instance, uses the `CHROME_BIN` environment variable).
Check out [browsers] for more information.


### I'm getting a weird error from the browser, how can I debug it?
Go to the captured browser and click the "DEBUG" button (or open `http://localhost:9876/debug.html`)
and use the web inspector to see what's going on. (You may need to refresh the debug.html page for it to kick in once
the web inspector is open.)


### I'm getting a syntax error from a HTML file. It looks like the preprocessor isn't working.
The patterns in the `preprocessors` configuration setting are resolved via the `basePath` setting.
See preprocessors for more information. You can also turn on debug logging (use `--log-level debug` when starting Karma)
and Karma will display which files are preprocessed.


### I'm getting a `npm ERR! peerinvalid Peer` error. How can I fix that?
Try to remove `karma` and `karma-*` modules from your `node_modules` first (for instance `rm -rf /usr/local/lib/node_modules/karma-*`), then install Karma again.


### My tests are running really slow. What's going on?
Make sure the Karma's tab is active. Browsers give inactive tabs only minimum CPU.

Note: If you can't find the solution for your issue here you can also ask for help in the [mailing-list](https://groups.google.com/d/forum/karma-users) or [Stack Overflow](https://stackoverflow.com/questions/tagged/karma-runner).

### I'm really stuck. I tried every thing!
Because of the complexity of test setups, we rarely work to fix bugs without steps to reproduce. The best approach is to create a github project that installs all the components and reproduces the bug.

---

### Plus 01 Requirejs (`docs/plus/01-requirejs.md`)

---
pageTitle: RequireJS
menuTitle: RequireJS
---

To get Karma to run with [Require.js] we need two files:

* `karma.conf.js` &mdash; which configures Karma
* `test-main.js` &mdash; which configures Require.js for the tests

Let's imagine our app has a directory structure which looks something like this:

```bash
$ tree
.
|-- index.html
|-- karma.conf.js
|-- lib
|   |-- jquery.js
|   |-- require.js
|   `-- underscore.js
|-- src
|   |-- app.js
|   `-- main.js
`-- test
    |-- appSpec.js
    `-- test-main.js

3 directories, 9 files
```

## Configure Karma

The first step is creating our `karma.conf.js`. We can do this from the
command line:

```bash
$ karma init
```

This will give you a series of prompts for things such as paths to the source and test
files as well as which browsers to capture.

In this example we'll use Jasmine, but other test frameworks work just
as well.

Choose "yes" for Require.js.

For the question *"Which files do you want to include with &lt;script&gt;
tag?"*, we need to choose all files which are *not* loaded by Require.js.
Usually, you'll only need to include your `test-main.js` file, which has
the same role for your tests as `main.js` has for your app when using
Require.js.

For the question *"What is the location of your source and test files?"*, we choose all the
files we want to load with Require.js. For this example we'll need:

* `lib/**/*.js` &mdash; all external libraries
* `src/**/*.js` &mdash; our source code
* `test/**/*Spec.js` &mdash; all the tests

And then, when excluding files, type in `src/main.js`, as we don't want to actually
start the application in our tests.

Now your `karma.conf.js` should include:

```javascript
// list of files / patterns to load in the browser
module.exports = function(config) {
  config.set({
    frameworks: ['jasmine', 'requirejs'],

    files: [
      {pattern: 'lib/**/*.js', included: false},
      {pattern: 'src/**/*.js', included: false},
      {pattern: 'test/**/*Spec.js', included: false},

      'test/test-main.js'
    ],

    // list of files to exclude
    exclude: [
        'src/main.js'
    ]
  });
};
```

The files property contains every file you want to be available to the
Karma runner. By default a script tag will be created for the files,
unless you use the `included: false` option.

If you want a script tag to be added before requirejs (to load an amd 
compatible script before requirejs) then you must add the requirejs
and adapter script to the files list and remove requirejs from the
frameworks list. This allows you to control the order. For instance
to load `knockout.js` before requirejs...

```
  config.set({
    frameworks: ['jasmine'],

    files: [
      'knockout.js',

      'node_modules/requirejs/require.js',
      'node_modules/karma-requirejs/lib/adapter.js',

      {pattern: 'lib/**/*.js', included: false},
      {pattern: 'src/**/*.js', included: false},
      {pattern: 'test/**/*Spec.js', included: false},

      'test/test-main.js'
    ],
```

## Configuring Require.js

Just like any Require.js project, you need a main module to bootstrap
your tests. We do this in `test/test-main.js`.

### Karma `/base` Directory

Karma serves files under the `/base` directory. So, on the server
requests to files will be served up under
`http://localhost:9876/base/*`.

The Require.js config for `baseUrl` gives a starting context for modules
that load with relative paths. When setting this value for the Karma
server, it will need to start with `/base`. We want the `baseUrl` for our
tests to be the same folder as the base url we have in `src/main.js`, so
that relative requires in the source won’t need to change. So, as we
want our base url to be at `src/`, we need to write `/base/src`.

### Require Each Test File

With Karma we don't need to list all test files ourselves as we can
easily find them from the files specified in `test-main.js`: Karma
includes all the files in `window.__karma__.files`, so by filtering this
array we find all our test files.

Now we can tell Require.js to load our tests, which must be done
asynchronously as dependencies must be fetched before the tests are run.
The `test/test-main.js` file ends up looking like this:

```javascript
var TEST_REGEXP = /(spec|test)\.js$/i;
var allTestFiles = [];

// Get a list of all the test files to include
Object.keys(window.__karma__.files).forEach(function(file) {
  if (TEST_REGEXP.test(file)) {
    // Normalize paths to RequireJS module names.
    // If you require sub-dependencies of test files to be loaded as-is (requiring file extension)
    // then do not normalize the paths
    var normalizedTestModule = file.replace(/^\/base\/|\.js$/g, '');
    allTestFiles.push(normalizedTestModule);
  }
});

require.config({
  // Karma serves files under /base, which is the basePath from your config file
  baseUrl: '/base/src',

  // example of using a couple of path translations (paths), to allow us to refer to different library dependencies, without using relative paths
  paths: {
    'jquery': '../lib/jquery',
    'underscore': '../lib/underscore',
  },

  // example of using a shim, to load non AMD libraries (such as underscore)
  shim: {
    'underscore': {
      exports: '_'
    }
  },

  // dynamically load all test files
  deps: allTestFiles,

  // we have to kickoff jasmine, as it is asynchronous
  callback: window.__karma__.start
});
```

## Using Require.js in tests

Tests can now be written as regular Require.js modules. We wrap
everything in `define`, and inside we can use the regular test methods,
such as `describe` and `it`. Example:

```javascript
define(['app', 'jquery', 'underscore', './test-helper'], function(App, $, _, testHelper) {

    describe('just checking', function() {
    
        testHelper.setup();

        it('works for app', function() {
            var el = $('<div></div>');

            var app = new App(el);
            app.render();

            expect(el.text()).toEqual('require.js up and running');
        });

        it('works for underscore', function() {
            // just checking that _ works
            expect(_.size([1,2,3])).toEqual(3);
        });

    });

});
```

## Running the tests

We can now run the tests from the command line:

```bash
$ karma start
```

If you didn't configure Karma to watch all the files and run tests
automatically on any change, you can trigger the tests manually by
typing:

```bash
$ karma run
```

[Here is a running example of Karma with Require.js][example].

[Require.js]: https://requirejs.org/
[example]: https://github.com/kjbekkelund/karma-requirejs

---

### Plus 02 Travis (`docs/plus/02-travis.md`)

---
pageTitle: Travis CI
menuTitle: Travis CI
---

[Travis CI] is a popular continuous integration service that
integrates with your [Github] repository to automatically run your
tests when the code is pushed. Integration is done by adding a simple
[YAML] file to your project root; Travis and Github take care of the
rest. Whenever tested, the Travis results will appear in your Github pull requests and your
history will be available within their control panel. This article assumes you
already have Travis account.

## Configure Travis
Create a file in your project root called `.travis.yml` with the
following YAML content:

```ruby
language: node_js
node_js:
  - "4"
```

## Set up a Test Command
If you do not already have a `package.json` in your project root, create one now. Travis runs `npm test` to trigger your tests, so this
is where you tell Travis how to run your tests.

```json
// ...snip...
"devDependencies": {
  "karma": "~0.12"
},
// ...snip...
"scripts": {
   "test": "karma start --single-run --browsers PhantomJS"
}
// ...snip...
```

Travis will run `npm install` before every suite, so this is your
chance to specify any modules your app needs that Travis does not know
about like Karma.

## Configure Travis with Firefox
Travis supports running a real browser (Firefox) with a virtual
screen. Just update your `.travis.yml` to set up the virtual screen
like this (if you're using Xenial):
```ruby
language: node_js
node_js:
  - "4"
dist: xenial
services:
  - xvfb
```

Or this, for Trusty and below:
```ruby
language: node_js
node_js:
  - "4"
before_script:
  - export DISPLAY=:99.0
  - sh -e /etc/init.d/xvfb start
```

And now, you can run your tests on Firefox, just change the `npm test`
command to
```bash
karma start --browsers Firefox --single-run
```

## Notes

* Travis' Node environment has very little available. If the startup
  process in Travis fails to check for missing module information and be sure to add them to your `package.json` dependencies.
* Travis does not run on your local network so any code that attempts
  to connect to resources should be stubbed out using [Nock].
* There are more options available to your `.travis.yml`, such as
  running scripts before the install or test run. There are hints in
  the Travis docs for [GUI apps] configuration.


[Travis CI]: https://travis-ci.org/
[Github]: https://github.com/
[YAML]: https://yaml.org/
[PhantomJS]: https://phantomjs.org/
[GUI apps]: https://docs.travis-ci.com/user/gui-and-headless-browsers/
[Nock]: https://github.com/nock/nock

---

### Plus 03 Jenkins (`docs/plus/03-jenkins.md`)

---
pageTitle: Jenkins CI
menuTitle: Jenkins CI
---

[Jenkins CI] is one of the most popular continuous integration servers
in the market today. At some point while developing your [AngularJS]
project (hopefully early on), you might want to have automated tests run
off your code versioning system. Jenkins will help you with this task.
This tutorial assumes you have Jenkins already setup and running
on your CI environment.

## Install Prerequisites
You need the following tools installed on your Jenkins CI server:

* Node
* Karma

The following Jenkins plugin is optional, but the next guidelines are based on it:
* [EnvInject] - it makes things easier under certain linux distributions and user permissions.

## Configure Karma
 Make the following additions and changes to your `karma.conf.js`
 file as needed:

```javascript
singleRun: true,
reporters: ['dots', 'junit'],
junitReporter: {
  outputFile: 'test-results.xml'
},
 ```

Please note the `test-results.xml` files will be written to subdirectories
named after the browsers the tests were run in inside the present working
directory (and you will need to tell Jenkins where to find them).

## Create a new Jenkins Job
In Jenkins, start a new job for Angular/Karma with the basic
settings (Name, description, parameters, source code repo to pull
from, etc.)

## Configure the Build Environment
First go to the job page and click on configure. Then in the Build
Environment sub-section, check the “Inject environment
variables to the build process' checkbox. A few textboxes will
appear and in the “Properties Content” box set the following:

```bash
$ PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
$ PHANTOMJS_BIN=/usr/local/bin/phantomjs #or wherever PhantomJS happens to be installed
```

Further down the page, in the Post-build Actions sub-section add a
`Publish JUnit test result report` from the Post-build action drop
down menu. When the textbox labeled Test report XMLs appears, enter
the path to where the `test-results.xml` files are relative to the root of your
Jenkins job workspace (you can use wildcards for this, so `**/test-results.xml`
will find the file even if it was stored inside a browser-specific
subdirectory).



[Jenkins CI]: https://www.jenkins.io/
[AngularJS]: https://angularjs.org
[EnvInject]: https://plugins.jenkins.io/envinject/

---

### Plus 04 Semaphore (`docs/plus/04-semaphore.md`)

---
pageTitle: Semaphore CI
menuTitle: Semaphore CI
---

[Semaphore] is a popular continuous integration service that
supports a [wide range of programming languages]. Up-to-date 
versions of [Firefox], [PhantomJS] and [Node.js] make it a good 
testing ground for JavaScript applications. This article assumes 
you already have a Semaphore account.

## Configure Your Project

If you do not already have a `package.json` in your project root,
create one now. This will both document your configuration and
make it easy to run your tests. Here's an example:

```json
// ...snip...
"devDependencies": {
  "karma": "~0.10"
},
// ...snip...
"scripts": {
   "test": "./node_modules/.bin/karma start --single-run --browsers PhantomJS"
}
// ...snip...
```

Another option is to use Firefox as your test browser. To do this, change
the last part to:

```json
"scripts": {
   "test": "./node_modules/.bin/karma start --single-run --browsers Firefox"
}
```

Now running `npm test` within your project will run your tests with Karma.

## Add Your Project to Semaphore

Follow the process as shown in the [screencast] on the Semaphore docs.

After the analysis is finished, ignore the Ruby version Semaphore has set
for you, choose to customize your build commands and use these:

```bash
npm install
npm test
```

That's it - proceed to your first build. In case you're using Firefox as
your test browser, Semaphore will automatically run it on a virtual screen
during your builds.

Also, if necessary, build commands can be further [customized] at any time.


[screencast]: https://semaphoreci.com/docs/adding-github-bitbucket-project-to-semaphore.html
[Semaphore]: https://semaphoreci.com
[wide range of programming languages]: https://semaphoreci.com/docs/supported-stack.html
[Firefox]: https://semaphoreci.com/docs/firefox.html
[PhantomJS]: https://semaphoreci.com/docs/phantomjs.html
[Node.js]: https://semaphoreci.com/docs/languages/javascript/javascript-support-on-semaphore.html
[platform]: https://semaphoreci.com/docs/supported-stack.html
[customized]: https://semaphoreci.com/docs/customizing-build-commands.html

---

### Plus 05 Cloud9 (`docs/plus/05-cloud9.md`)

[Cloud9 IDE] is an open source web-based cloud integrated development environment that supports
several programming languages, with a focus on the web stack (specifically JavaScript and NodeJS).
It is written almost entirely in JavaScript and uses NodeJS on the back-end.

## Configuration

First, make sure the `karma.conf.js` includes the following entries:

```javascript
hostname: process.env.IP,
port: process.env.PORT
```

## Capture the browser manually on the local machine

You can use any of your local browsers.

```bash
# Start Karma without browsers:
$ karma start --no-browsers
```

Now, open `http://<projectName>.<cloud9User>.c9.io/` in your browser.

## Run Karma unit tests with PhantomJS

It is also possible to run headless PhantomJS on the Cloud9 server.

```bash
# Install the PhantomJS plugin:
$ npm install karma-phantomjs-launcher

# Start Karma:
$ karma start --browsers PhantomJS
```

[Cloud9 IDE]: https://c9.io/

---

### Plus 06 Angularjs (`docs/plus/06-angularjs.md`)

---
pageTitle: AngularJS
menuTitle: AngularJS
---

If you're using [AngularJS](https://angularjs.org), check out the [AngularJS Generator](https://github.com/yeoman/generator-angular), which makes use of the [Karma Generator](https://github.com/yeoman/generator-karma) to setup a fully featured, testing-ready project.

---

### Plus 07 Yeoman (`docs/plus/07-yeoman.md`)

[Yeoman](https://yeoman.io/) is a set of tools to make building web apps easier. Yeoman has support for Karma via the [Karma Generator](https://github.com/yeoman/generator-karma).

---

### Plus 08 Emberjs (`docs/plus/08-emberjs.md`)

---
pageTitle: Ember.js
menuTitle: Ember.js
---

To execute javascript unit and integration tests with ember.js follow the steps below:

1. [install karma]

2. install the qunit plugin

   ```bash
   npm install karma-qunit --save-dev
   ```

3. install the ember preprocessor plugin

   ```bash
   npm install karma-ember-preprocessor --save-dev
   ```

4. generate a configuration file for karma
   ```bash
   karma init
   ```
   note -the above will walk you through the basic setup. An example configuration file that works with ember.js/qunit and phantomjs is below

   ```javascript
   module.exports = function(config) {
     config.set({
       basePath: 'js',
 
       files: [
         'vendor/jquery/jquery.min.js',
         'vendor/handlebars/handlebars.js',
         'vendor/ember/ember.js',
         'app.js',
         'tests/*.js',
         'templates/*.handlebars'
       ],
 
       browsers: ['PhantomJS'],
       singleRun: true,
       autoWatch: false,
 
       frameworks: ['qunit'],
 
       plugins: [
         'karma-qunit',
         'karma-ember-preprocessor',
         'karma-phantomjs-launcher'
       ],
 
       preprocessors: {
         '**/*.handlebars': 'ember'
       }
     });
   };
   ```

   Note - the `files` section above should include all dependencies, ie- jQuery/handlebars/ember.js along with the js and handlebars files required to deploy and run your production ember.js application

   Note - when testing ember applications, it is important that karma does not try to run the tests until the ember application has finished initialization. You will need to include a small bootstrap file in the `files` section above to enforce this.  Here's an example:
   ```javascript
   __karma__.loaded = function() {};
 
   App.setupForTesting();
   App.injectTestHelpers();
 
   //this gate/check is required given that standard practice in Ember tests to is to call
   //Ember.reset() in the afterEach/tearDown for each test.  Doing so, causes the application
   //to 're-initialize', resulting in repeated calls to the initialize function below
   var karma_started = false;
   App.initializer({
       name: "run tests",
       initialize: function(container, application) {
           if (!karma_started) {
               karma_started = true;
               __karma__.start();
           }
       }
   });
   ```

5. add a simple Qunit test

   ```javascript
   test('one should equal one', function() {
       equal(1, 1, 'error: one did not equal one');
   });
   ```

6. run the tests with karma from the command line
   ```bash
   karma start
   ```

A simple unit / integration tested example app showing karma / qunit / ember in action can be found [here]

[install karma]: ../intro/installation.html
[here]: https://github.com/toranb/ember-testing-example

---

### Plus 09 Codio (`docs/plus/09-codio.md`)

[Codio] is a web-based cloud integrated development environment that supports almost any programming language. Every project gets its individual Box: an instantly available server-side development environment with full terminal access. Unlimited panels and tabs, and a plethora of productivity features. 

## Customize your Codio Project

Next to the help menu you will see the "Configure" option, if you don't see it click the little arrow near the end and then select "Configure".


This opens a .codio file which you can customize and use rather than entering commands in Terminal. Replace the existing text with the text below:


    {
    // Configure your Run and Preview buttons here.

    // Run button configuration
      "commands": {
        "Karma Start": "karma start --no-browsers"
        "Karam Run": "karma run"
      },

    // Preview button configuration
      "preview": {
        "Karma Preview": "http://{{domain}}:8080"
      }
    }


*If you wish, you can change the port for the `Karma Preview` entry, but make a note of the change as you will need to include that port in the `karma.config js` file later.*


## Configuration

- Edit the `karma.conf.js` and add the following:


        // hostname for the server
        hostname: require('os').hostname() + '.codio.io',


- Review webserver port entry to ensure same port defined as entered in .codio file

    
        // web server port
        port: 8080,
 

## Capture the browser manually on the local machine

You can use your local browser.

- Either:

    - Open a Terminal window and enter

            $ karma start --no-browsers
or 
    - Select `Karma Start` from the Run menu (the 2nd from the right button).


- Select `Karma Preview` from the Preview menu (the right-hand button).

- Switch back into your Codio project and either: 

    - Open a new Terminal window and enter

            $ karma run
or 
    - Select `Karma Run` from the Run menu (the 2nd from the right button).

and your test will execute


[Codio]: https://codio.com

---

### Plus 10 Teamcity (`docs/plus/10-teamcity.md`)

---
pageTitle: TeamCity
menuTitle: TeamCity
---

Running Karma in your [TeamCity] build is as simple as adding command line build
step to perform the task. That is basically it.

## Install Prerequisites
The only prerequisite is `Node` (with `npm`) installed on the agent(s) you are going to use to
run build on.
You may decide to install Karma and Karma-related packages on the agent globally to reuse the same
Karma installation by different builds.

## Configure project
Add `karma-teamcity-reporter` as a dependency to your project:

    npm i --save-dev karma-teamcity-reporter

It is also a good idea to check that you have all karma npm dependencies listed in your
`package.json` file (e.g. `karma-jasmine`, `karma-phantomjs-launcher` and so on) to have them
being installed during the build.

## Create a new TeamCity build step
Add new build step to the build configuration: use Command Line runner and fill in `Custom
script` text area. If you had decided not to install *all* your npm dependencies globally
add `npm install` at the beginning of the script. Then add command to run Karma, e.g.:

    karma start --reporters teamcity --single-run --browsers PhantomJS --colors false

Running Karma with all these options provided via command line allows to run Karma in
TeamCity build and locally in development environment (with options from configuration
file).

[TeamCity]: https://www.jetbrains.com/teamcity/

---

--- METRICS ---
- Files Extracted: 30
- Estimated Token Budget: ~30804 tokens
- Canonical Reference: https://codewiki.google/github.com/karma-runner/karma
