web-dev-qa-db-fra.com

Quand devrions-nous utiliser .then avec Protractor Promise?

J'ai beaucoup d'instabilité avec Protractor, et je suis sûr qu'il y a quelque chose que je ne comprends pas. Parfois, j'ai besoin d'utiliser le .then () lorsque je clique sur un bouton avant de continuer, parfois cela n'a aucun impact et je ne devrais pas utiliser .then () ou le test a échoué.

Je me demande quand dois-je utiliser le rappel .then () lors des tests dans Protractor? Exemple :

createAccountForm = $('#form-create-account');
submitButton = createAccountForm.$('button[type=submit]');

browser.wait(EC.elementToBeClickable(submitButton), 5000);
submitButton.click(); // .then(function(){   <-- uncomment in the .then form

// find the confirmation message
var message = $('.alert-success');
browser.wait(EC.visibilityOf(message), 5000);
log.debug('After visibilityOf');

expect(message.isPresent()).to.be.eventually.true;
// }); --> uncomment when in .then form

Lorsque j'utilise cette forme de test (sans .then ()) je vois sur le navigateur que le cliquer sur le bouton n'est pas terminé, le test continue avec l'attente suivante puis s'arrête.

Si j'utilise le formulaire .then (), le clic sur le bouton est terminé, et le test continue sans erreur.

Sur un autre test, je n'ai pas besoin d'utiliser le rappel then () lorsque je clique sur le bouton.

Alors, quand dois-je utiliser le .then () et quand non?

Jean-Marc

35
jmcollin92

La réponse à cette question se trouve dans cet article: http://spin.atomicobject.com/2014/12/17/asynchronous-testing-protractor-angular/

C'est :

  1. Protractor met en file d'attente toutes les commandes de pilote dans ControlFlow,
  2. lorsque vous avez besoin du résultat d'une commande de pilote, vous devez utiliser .then,
  3. lorsque vous n'avez pas besoin du résultat d'un pilote, vous pouvez éviter le .then mais toutes les instructions suivantes doivent être mises en file d'attente dans le ControlFlow sinon elles seront exécutées avant les commandes dans la file d'attente conduisant à un résultat imprévisible. Donc, si vous souhaitez exécuter une commande de test non pilote, vous devez l'ajouter dans le rappel .then ou encapsuler le test dans une promesse et mettre le test en file d'attente dans ControlFlow. Voir l'exemple ci-dessous.

Voici un exemple de mon test fonctionnant sans .then:

log.debug('test0');

// enqueue the click
submitButton.click(); 
var message = $('.alert-success'); 

// enqueue the wait for message to be visible  
browser.wait(EC.visibilityOf(message), 5000);  

log.debug('test1');

// enqueue a test
expect(message.isPresent()).to.be.eventually.true;
log.debug('test2');

// a function returning a promise that does an async test (check in MongoDB Collection)
var testAccount = function () {           
    var deferred = protractor.promise.defer();

    // Verify that an account has been created
    accountColl.find({}).toArray(function (err, accs) {
        log.debug('test5');
        expect(err).to.not.exist;
        log.debug('test6');
        expect(accs.length).to.equal(1);
        return deferred.fulfill();
    });
    return deferred.promise;
};

log.debug('test3');

// Enqueue the testAccount function
browser.controlFlow().execute(testAccount);  
log.debug('test4');

La sortie est maintenant ce que nous attendons:

test0

test1

test2

test3

test4

test5

test6
40
jmcollin92