Ответ 1
chai предоставляет метод use
для доступа к экспорту chai
и utils
.
Этот метод может использоваться третьими лицами, когда создает плагины, но он также внутренне используется для загрузки интерфейса.
Реализация этого метода проста:
exports.use = function (fn) {
if (!~used.indexOf(fn)) {
fn(this, util);
used.push(fn);
}
return this;
};
Внутри он использует это для загрузки (среди прочего) первичной Assertion prototype
и основной функции утверждения:
var assertion = require('./chai/assertion'); // primary Assertion prototype
exports.use(assertion); // load it
var core = require('./chai/core/assertions'); // core assertion functionality
exports.use(core); // load it
Одним из методов, который подвергается Assertion prototype
, является метод addProperty
, который позволяет добавлять свойства к указанному prototype
.
Internally chai
использует этот метод для добавления функциональности подтверждения ядра к Assertion prototype
. Например, все языковые цепочки и помощники утверждения (exist
, empty
и т.д.) Добавляются таким образом.
Языковые цепочки:
[ 'to', 'be', 'been'
, 'is', 'and', 'has', 'have'
, 'with', 'that', 'which', 'at'
, 'of', 'same' ].forEach(function (chain) {
Assertion.addProperty(chain, function () {
return this;
});
});
Вся эта функциональность становится доступной, когда определенный интерфейс загружается внутри, например expect
. Когда этот интерфейс загружен, новый Assertion prototype
будет создаваться при каждом выполнении expect
, который будет содержать все функциональные возможности:
// load expect interface
var expect = require('./chai/interface/expect'); // expect interface
exports.use(expect); // load it
// expect interface
module.exports = function (chai, util) {
chai.expect = function (val, message) {
return new chai.Assertion(val, message); // return new Assertion Object with all functionality
};
};
Как вы видите, метод expect
принимает аргумент val
(и необязательный аргумент message
). Когда этот метод вызывается (например, expect(foo)
), будет создан и возвращен новый Assertion prototype
, отображающий все основные функциональные возможности (позволяя делать expect(foo).to.exist
).
Assertion Constructor
использует flag
util
для установки значения флага объекта, который сопоставляется с переданным аргументом val
.
function Assertion (obj, msg, stack) {
flag(this, 'ssfi', stack || arguments.callee);
flag(this, 'object', obj); // the 'object' flag maps to the passed in val
flag(this, 'message', msg);
}
Все exist
, а затем, получает это значение через flag
util
и оценивает, не соответствует ли ему null
, используя метод assert
, определенный на Assertion prototype
.
Assertion.addProperty('exist', function () {
this.assert(
null != flag(this, 'object')
, 'expected #{this} to exist'
, 'expected #{this} to not exist'
);
});