web-dev-qa-db-fra.com

Comment fonctionne l'attente (). To.be.true dans Chai?

expect(true).to.be.true;

Dans ce code, tous les 'to', 'be', 'true' semblent être un attribut de la réponse d'objet de 'expect (true)'.

Comment ces attributs peuvent-ils fonctionner pour qu'ils puissent déclencher une exception?

22
wangzi6147

Vous pouvez vérifier le code source:

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

et il y a un addProperty dans utils:
https://github.com/chaijs/chai/blob/master/lib/chai/utils/addProperty.js

Avec cela, vous pouvez enchaîner les propriétés à l'infini comme: .to.be.to.to.to.be.equal()

Créons une démonstration plus simple:

Supposons que vous avez un objet assert, avec la méthode .true()

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

et vous voulez pouvoir chaîner .to à l'infini. Utilisez simplement le defineProperty pour définir notre getter:

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

alors maintenant vous pouvez

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

code de travail: https://codepen.io/CodinCat/pen/LLzBEX?editors=0012


J'ai ajouté un autre exemple plus complexe ici: https://codepen.io/CodinCat/pen/dRVjXL?editors=0012

Dans cet exemple, vous pouvez voir qu'il existe des comportements dans la propriété .true.

Nous stockons la valeur de expect() dans les propriétés internes __expectObj Et __value, Puis la vérifions dans le getter de .true. Afin que vous puissiez

expect(false).to.to.to.to.true
22
CodinCat

Jetez un oeil à la source de Chai Assertion mais le tl; dr est que Chai implémente ses propres méthodes chaînables sur sa bibliothèque d'assert. Cependant, les mots-clés spéciaux sont simplement du sucre syntaxique comme le montre le code ci-dessous. Littéralement, ce ne sont que des propriétés qui sont ajoutées et peuvent être enchaînées mais rien n'est vraiment défini:

  /**
   * ### 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);
  });

À partir de là, ce qu'il recherche réellement, ce sont des mots-clés qu'il définit spécifiquement. Un exemple est le mot clé .to.be.true il regardera true comme défini dans l'extrait de code ci-dessous

  /**
   * ### .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
    );
  });
7
aug