期望()。to.be.true如何在柴?

时间:2017-06-26 09:09:36

标签: javascript chai

expect(true).to.be.true;

在此代码中,所有'to','be','true'似乎都是来自'expect(true)'的对象响应的属性。

这些属性如何工作以便引发异常?

2 个答案:

答案 0 :(得分:22)

您可以查看源代码:

[ 'to', 'be', 'been'
  , 'is', 'and', 'has', 'have'
  , 'with', 'that', 'which', 'at'
  , 'of', 'same', 'but', 'does' ].forEach(function (chain) {
    Assertion.addProperty(chain);
});

addProperty中有一个utils
https://github.com/chaijs/chai/blob/master/lib/chai/utils/addProperty.js

通过这种方式,您可以无限地链接属性,如:.to.be.to.to.to.be.equal()

让我们创建一个更简单的演示:

假设您有一个assert对象,并使用.true()方法

const assert = {
  'true': function (v) {
    return !!v
  }
}

并且您希望能够无限地链接.to。只需使用defineProperty来定义我们的getter:

Object.defineProperty(assert, 'to', {
  get() {
    return assert
  }
})

所以现在你可以

assert.to.to.to.to.true(false)

工作代码:https://codepen.io/CodinCat/pen/LLzBEX?editors=0012

我在这里添加了另一个更复杂的例子:https://codepen.io/CodinCat/pen/dRVjXL?editors=0012

在此示例中,您可以看到.true属性中存在一些行为。

我们将expect()中的值存储在内部__expectObj__value属性中,然后在.true的getter中对其进行验证。所以你可以

expect(false).to.to.to.to.true

答案 1 :(得分:7)

看一下chai Assertion的来源,但是tl; dr是Chai在其断言库上实现了自己的可链接方法。但是,特殊关键字只是语法糖,如下面的代码所示。从字面上看,它们只是添加的属性,可以链接但没有真正定义:

  /**
   * ### Language Chains
   *
   * The following are provided as chainable getters to improve the readability
   * of your assertions.
   *
   * **Chains**
   *
   * - to
   * - be
   * - been
   * - is
   * - that
   * - which
   * - and
   * - has
   * - have
   * - with
   * - at
   * - of
   * - same
   * - but
   * - does
   *
   * @name language chains
   * @namespace BDD
   * @api public
   */

  [ 'to', 'be', 'been'
  , 'is', 'and', 'has', 'have'
  , 'with', 'that', 'which', 'at'
  , 'of', 'same', 'but', 'does' ].forEach(function (chain) {
    Assertion.addProperty(chain);
  });

从那里它实际上寻找的是它专门定义的关键词。一个例子是关键字.to.be.true,它会在下面的代码段中查看true as defined

  /**
   * ### .true
   *
   * Asserts that the target is strictly (`===`) equal to `true`.
   *
   *     expect(true).to.be.true;
   *
   * Add `.not` earlier in the chain to negate `.true`. However, it's often best
   * to assert that the target is equal to its expected value, rather than not
   * equal to `true`.
   *
   *     expect(false).to.be.false; // Recommended
   *     expect(false).to.not.be.true; // Not recommended
   *
   *     expect(1).to.equal(1); // Recommended
   *     expect(1).to.not.be.true; // Not recommended
   *
   * A custom error message can be given as the second argument to `expect`.
   *
   *     expect(false, 'nooo why fail??').to.be.true;
   *
   * @name true
   * @namespace BDD
   * @api public
   */

  Assertion.addProperty('true', function () {
    this.assert(
        true === flag(this, 'object')
      , 'expected #{this} to be true'
      , 'expected #{this} to be false'
      , flag(this, 'negate') ? false : true
    );
  });