chai-kefir
用于断言 Kefir 可观察对象的 Chai 插件。
如何使用
使用 npm 安装
npm i --save-dev chai-kefir
在测试文件顶部,导入 chai-kefir
和 kefir
并注册 Kefir
import Kefir from 'kefir';
import { use } from 'chai';
import chaiKefir from 'chai-kefir';
如果您没有使用 ESModules,请确保获取 default
属性
const Kefir = require('kefir');
const { use } = require('chai');
const chaiKefir = require('chai-kefir').default;
在您的测试文件顶部,使用导出的工厂函数创建插件并将其注册到 chai
const { plugin, activate, send, stream, prop, pool } = chaiKefir(Kefir);
use(plugin);
所有导出的函数都允许您与 Kefir 可观察对象进行交互,而无需将它们直接连接到真实或模拟源。
API
Factory: (Kefir) => PluginHelpers
默认导出是一个工厂函数,它接受应用程序的 Kefir 实例,并返回一个包含插件助手对象的插件助手对象。这些助手将在下面介绍。
PluginHelpers
plugin: (chai, utils) => void
plugin
函数将 chai-kefir
的断言注册到 chai
。此函数应传递给 chai
的 use
函数。
activate: (obs: Kefir.Observable) => void
activate
是一个简单的辅助函数,用于打开流。
deactivate: (obs: Kefir.Observable) => void
deactivate
是一个简单的辅助函数,用于关闭流。它可以关闭使用 activate
激活的流。通过其他方式打开的流(直接调用 on{Value|Error|End|Any}
,使用 observe
等)需要通过其补充机制来停用。
send: (obs: Kefir.Observable, values: Array<Event<T>>) => obs
send
是一个辅助函数,用于将值发射到给定的可观察对象中。请注意,第二个参数是一个要从可观察对象中发射的值数组。该 Event
由 value
、error
和 end
函数生成。对于这三个函数,可选的 options
对象不需要。
value: (value, options: ?{ current }) => Event<Value>
error: (error, options: ?{ current }) => Event<Error>
end: (options: ?{ current }) => Event<End>
value
和 error
接受一个值或错误以及一个可选的 options
对象,并返回一个可以传递给 send
、emit
或 emitInTime
的 Event
对象。 end
不接受此值,因为 Kefir 中的 end
事件不会与其一起发送值。
当传递给 send
时,options
对象将被忽略。 options
由 emit
和 emitInTime
(两者将在下面描述)使用,以确定事件是否应该被视为 Kefir.Property
的当前事件、错误或结束。
stream: () => Kefir.Stream
prop: () => Kefir.Property
pool: () => Kefir.Pool
stream
、prop
和 pool
是创建空流、属性和池的辅助函数。这些可以用作模拟源来发送值。它们没有其他行为。
断言
observable
断言预期值是否为 Kefir.Observable
。对于其他断言,我们建议从 observable
中进行链式调用。下面介绍的 property
需要它;其他断言应该为了保持一致性。
expect(obs).to.be.an.observable();
property
断言预期值是否为 Kefir.Property
。必须与 observable
进行链式调用。
expect(obs).to.be.an.observable.property();
stream
断言预期值是否为 Kefir.Stream
。
expect(obs).to.be.an.observable.stream();
pool
断言预期值是否为 Kefir.Pool
。
expect(obs).to.be.an.observable.pool();
active
断言预期值是否是一个处于活动状态的可观察对象。
expect(obs).to.be.an.active.observable();
emit
断言提供的可观察对象是否同步发射预期值。 emit
接受一个要匹配的值数组,并期望它们按照正确的顺序深度等于值。
接受一个可选的回调函数,该函数在可观察对象激活后被调用。这是因为在将可观察对象传递给 chai
之前发射到可观察对象中的值不会发射到断言中,除非它是 Property。
expect(obs).to.emit([value(1), error(new Error('whoops!')), end()], () => {
send(obs, [value(1), error(new Error('whoops!')), end()]);
});
如果 obs
是一个具有当前值的 Kefir.Property
,则预期值应该获取包含 current: true
的 options 对象。请注意,鉴于 Properties 的工作方式,只有最后一个值是当前值。
send(obs, [value(1)]);
send(obs, [value(2)]);
expect(obs).to.emit([value(2, { current: true }), end()], () => {
send(obs, [end()]);
});
这些规则也适用于 emitInTime
。
emitInTime
资产断言提供的资产是否随着时间的推移正确地发射了值。在幕后使用 lolex
接管 JavaScripts 定时器,允许您根据值发射的时间进行断言。预期值应该是一个元组数组,其中第一个值是时间,第二个值是发射的值。
const expected = [
[0, value(1)],
[10, error(new Error('whoops!'))],
[20, end()]
]
接受一个回调函数,该函数传递一个简单的 tick
函数以及完整的 lolex
clock
。 tick
通过提供的毫秒数来推进内部计时器。 clock
在 这里 有记录。
expect(obs).to.emit(expected, (tick, clock) => {
send(obs, [value(1)]);
tick(10);
send(obs, [error(new Error('whoops!'))]);
tick(10);
send(obs, [end()]);
});
emitInTime
还接受一个可选的配置对象,该对象在回调函数之后。该对象接受以下选项
-
reverseSimultaneous: bool
:指示是否应该以相反的顺序调用计划在同一时间执行的回调函数。这是一个高级用例,用于检查您的实现是否处理了常见的浏览器错误。有关详细信息,请参阅 此问题。Kefir 的内置方法正确地处理了这种情况,因此,除非您在实现中使用计时器,否则大多数情况下是不必要的。