expect(true).to.be.true;
В этом коде все "to", "be", "true", кажется, являются атрибутом ответа объекта от "expect (true)".
Как эти атрибуты могут работать, чтобы они могли создавать исключение?
expect(true).to.be.true;
В этом коде все "to", "be", "true", кажется, являются атрибутом ответа объекта от "expect (true)".
Как эти атрибуты могут работать, чтобы они могли создавать исключение?
Вы можете проверить исходный код:
[ '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
. Таким образом, вы можете
expect(false).to.to.to.to.true
Взгляните на источник chai Assertion, но tl; dr - это то, что Чай реализует свои собственные цепочки в своей библиотеке assert. Однако специальные ключевые слова - это просто синтаксический сахар, как показано в приведенном ниже коде. Буквально это просто свойства, которые добавляются и могут быть привязаны, но ничего не определено:
/**
* ### 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
как определено в фрагменте кода ниже
/**
* ### .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 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
);
});