// If a start stack function was provided we capture the current stack trace and pass
// it to the `captureStackTrace` function so we can remove frames that come after it
ssf = ssf || arguments.callee;
if (ssf && Error.captureStackTrace) {
Error.captureStackTrace(this, ssf);
} else {
// If no start stack function was provided we just use the original stack property
try {
throw new Error();
} catch(e) {
this.stack = e.stack;
}
}
}
如你所见,我们使用Error.captureStackTrace捕获堆栈追踪并将它存储在我们正在创建的AssertError实例中(如果存在的话),然后我们将一个起始堆栈函数传递给它,以便从堆栈跟踪中删除不相关的调用帧,它只显示Chai的内部实现细节,最终使堆栈变得清晰明了。
现在让我们来看看@meeber在这个令人惊叹的PR中提交的代码。
在你开始看下面的代码之前,我必须告诉你addChainableMethod方法是干啥的。它将传递给它的链式方法添加到断言上,它也用包含断言的方法标记断言本身,并将其保存在变量ssfi(启动堆栈函数指示符)中。这也就意味着当前断言将会是堆栈中的最后一个调用帧,因此我们不会在堆栈中显示Chai中的任何进一步的内部方法。我没有添加整个代码,因为它做了很多事情,有点棘手,但如果你想读它,点我阅读。
下面的这个代码片段中,我们有一个lengOf断言的逻辑,它检查一个对象是否有一定的length。我们希望用户可以像这样来使用它:expect(['foo', 'bar']).to.have.lengthOf(2)。
function assertLength (n, msg) {
if (msg) flag(this, 'message', msg);
var obj = flag(this, 'object')
, ssfi = flag(this, 'ssfi');
// Pay close attention to this line
new Assertion(obj, msg, ssfi, true).to.have.property('length');
var len = obj.length;
// This line is also relevant
this.assert(
len == n
, 'expected #{this} to have a length of #{exp} but got #{act}'
, 'expected #{this} to not have a length of #{act}'
, n
, len
);
}
Assertion.addChainableMethod('lengthOf', assertLength, assertLengthChain);
Assertion.addChainableMethod('lengthOf', assertLength, assertLengthChain);
在上面的代码片段中,我突出强调了与我们现在相关的代码。让我们从调用this.assert开始说起。
以下是this.assert方法的源代码:
Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual, showDiff) {
var ok = util.test(this, arguments);
if (false !== showDiff) showDiff = true;
(责任编辑:admin)