Karma可以通过插件进行扩展。插件有五种类型:框架、报告器、启动器、预处理器和中间件。每种类型都允许修改Karma行为的特定方面。
Karma是使用依赖注入构建的。理解这个概念对于开发插件非常重要。
在非常高的层面上,您可以将Karma视为一个对象,其中每个键(一个DI令牌)都映射到某个Karma对象(一个服务)。例如,config
DI令牌映射到Config
实例,该实例保存当前的Karma配置。插件可以通过指定相应的DI令牌来请求(或注入)各种Karma对象。注入后,插件可以与注入的服务交互以实现其功能。
没有所有可用服务及其DI令牌的详尽列表,但您可以通过阅读Karma或其他插件的源代码来发现它们。
每个插件本质上都是一个与其关联的DI令牌的服务。当用户在他们的配置中激活插件时,Karma会查找相应的DI令牌并实例化链接到此DI令牌的服务。
要声明插件,应该为插件定义一个DI令牌并向Karma解释如何实例化它。DI令牌由两部分组成:插件类型和插件的唯一名称。前者定义了插件可以做什么、对服务API的要求以及何时实例化它。后者是一个唯一的名称,插件用户将使用它来激活插件。
插件定义多个服务是完全有效的。这可以通过向插件导出的对象添加更多键来完成。常见的例子是framework
+ reporter
插件,它们通常一起出现。
让我们创建一个非常简单的插件,在实例化时打印“Hello, world!”。我们将使用framework
类型,因为它在Karma生命周期的早期被实例化并且对它的API没有任何要求。让我们将我们的插件命名为“hello”,因此它的唯一名称将是hello
。将这两部分组合起来,我们得到插件的DI令牌framework:hello
。让我们声明它。
// 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]
};
// 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']
})
}
在“依赖注入”部分中,我们讨论了可以将任何Karma服务注入插件并与之交互。这可以通过将$inject
属性设置为插件希望与之交互的DI令牌数组来完成。Karma将获取此属性并将请求的服务作为参数传递给工厂函数。
让我们使hello
框架更有用一些,并使其将hello.js
文件添加到files
数组中。这样,插件的用户可以例如从他们的测试中访问hello.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]
};
Karma配置保持不变,为了简洁起见省略了。请参阅上面的示例以了解插件的使用。
本节概述了不同插件类型的API要求和约定。还有一些插件链接,您可以使用它们作为灵感。
karma-*
karma-plugin
、karma-framework
。框架将现有的测试库连接到Karma的API,以便它们的成果可以在浏览器中显示并发送回服务器。
Karma框架必须实现window.__karma__.start
方法,Karma将调用该方法来启动测试执行。此函数使用一个对象调用,该对象具有将结果发送回karma的方法
.result
单个测试已完成.complete
客户端已完成所有测试的执行.error
客户端发生错误.info
其他数据(例如测试数量或调试消息)最常见的是您将使用result
方法发送单个测试成功或失败状态。该方法采用以下形式的对象
{
// 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
}
karma-*-reporter
karma-plugin
、karma-reporter
karma-*-launcher
karma-plugin
、karma-launcher
karma-*-preprocessor
karma-plugin
、karma-preprocessor
预处理器是一个函数,它接受三个参数(content
、file
和next
),以某种方式修改内容,并将其传递给下一个预处理器。
content
正在处理的文件的内容file
描述正在处理的文件的对象some/file.coffee
-> some/file.coffee.js
此路径是可变的,可能实际上不存在。next(null, encodedContent)
解析。next
预处理完成后要调用的函数,应调用为next(null, processedContent)
或next(error)
由于Karma是由依赖注入构建的,因此插件可以请求几乎任何Karma组件并与之交互。有一些插件可以做更多有趣的事情,例如,查看karma-closure、karma-intellij。