karma Documentation

Spectacular Test Runner for JavaScript

11,951 stars JavaScript JavaScript 30 files · ~30,885 tokens
RAW Doc

Technical Documentation: karma-runner/karma

ℹ️ Provenance: Multi-Tier Ingestion · CodeWiki Reference

Overview (`README.md`)

Karma

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 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 and Web Test Runner support to provide a migration path off of Karma. See the Angular blog 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 and jasmine-browser-runner provide browser-based unit testing solutions which can be used as a direct alternative. Jest and Vitest 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.

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:

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.

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.

Using it.

See configuration.

This is so great. I want to help.

Please, see
contributing.

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


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

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.


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 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).

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

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. 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 here 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 (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. 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. 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:

text
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.


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. 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.

    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:
    (nglob parts, nglob star, nstar, next glob, nrange, noptional).
    Tuples are compared lexicographically.

    The nglob parts is the number of patterns after the bracket sections are expanded. E.g. the
    the pattern {0...9} will yield nglob parts=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).

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

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>:/, where <hostname> is the IP
address or hostname of the machine where the Karma server is running and `` 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 _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.


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

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.

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 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 guide for more in-depth explanation of how plugins work.


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 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 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 ;-)


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.
  • 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.

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!

Additional Resources


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
  • 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 [email protected].


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. 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. 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 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

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

Launchers

Preprocessors

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.


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.

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 `` 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 `` 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.

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.


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. On Windows, download Node.js
from the official site or use the NVM PowerShell Module.

Karma works on all LTS 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.


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


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.


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. 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.


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.

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?

This is a common Windows issue, the compilation of the native 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 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 or Stack Overflow.

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 — which configures Karma
  • test-main.js — 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 <script>
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 — all external libraries
  • src/**/*.js — our source code
  • test/**/*Spec.js — 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...

text
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.


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.

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).


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.


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://.<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

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


pageTitle: AngularJS menuTitle: AngularJS

If you're using AngularJS, check out the AngularJS Generator, which makes use of the Karma Generator to setup a fully featured, testing-ready project.


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

Yeoman is a set of tools to make building web apps easier. Yeoman has support for Karma via the Karma Generator.


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


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:

text
{
// 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:

    text
    // hostname for the server
      hostname: require('os').hostname() + '.codio.io',
  • Review webserver port entry to ensure same port defined as entered in .codio file

    text
    // 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

      text
      $ 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

      text
      $ karma run

or
- Select Karma Run from the Run menu (the 2nd from the right button).

and your test will execute


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:

text
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.:

text
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).


--- METRICS ---