web-dev-qa-db-fra.com

obtenir la valeur de l'attribut de l'élément dans le rapporteur

J'écris un test de rapporteur qui doit attendre qu'un attribut d'élément ait une valeur non vide, puis je veux renvoyer cette valeur à la fonction d'appelant. Cela s’est avéré plus difficile à écrire que prévu!

Je suis en mesure de planifier correctement une commande browser.wait() pour attendre que l'attribut d'élément ait une valeur non vide et j'ai vérifié que cette valeur correspond bien à ce que j'attends de la fonction de rappel, mais pour une raison quelconque, impossible de renvoyer cette valeur en dehors de la fonction de rappel et sur le reste du code de test.

Voici à quoi ressemble mon code:

function test() {
    var item = getItem();
    console.log(item);
}

function getItem() {
    var item;
    browser.wait(function() {
        return element(by.id('element-id')).getAttribute('attribute-name').then(function(value) {
            item = value;
            // console.log(item);
            return value !== '';
        });
    });
    return item;
}

Je peux dire que l'ordre d'exécution n'est pas celui que je prévois, car lorsque je retire le commentaire de l'appel console.log() dans la fonction de rappel, la valeur attendue est imprimée. Cependant, le même appel dans la fonction test() imprime 'non défini'.

Qu'est-ce qui se passe ici? Qu'est-ce que je rate? Comment puis-je obtenir la valeur d'attribut de la fonction de rappel correctement?

J'apprécie ton aide.

7
exbuddha

Je ne voudrais pas combiner les parties attribut wait et get - logiquement, ce sont deux choses distinctes, gardez-les séparées:

browser.wait(function() {
    return element(by.id('element-id')).getAttribute("attribute").then(function(value) {
        item = value;
        // console.log(item);
        return value !== '';
    });
});

element(by.id('element-id')).getAttribute("attribute").then(function (value) {
    console.log(value);
});

Notez que vous pouvez simplifier la condition d’attente de la manière suivante:

var EC = protractor.ExpectedConditions;
var Elm = $('#element-id[attribute="expected value"]');

browser.wait(EC.presenceOf(Elm), 5000);
Elm.getAttribute("attribute").then(function (value) {
    console.log(value);
});

Juste pour votre information, vous avez peut-être résolu votre problème actuel avec le deferred :

function test() {
    getItem().then(function (value) {
        console.log(value);
    });
}

function getItem() {
    var item = protractor.promise.defer();
    browser.wait(function() {
        return element(by.id('element-id')).getAttribute('attribute').then(function(value) {
            var result = value !== '';
            if (result) {
                item.fulfill(value);
            }
            return result;
        });
    });
    return item.promise;
}
11
alecxe

Après avoir lu un peu plus sur le fonctionnement de rapporteur avec les promesses et les planifiant/les enregistrant avec le flux de contrôle, j'ai trouvé une solution de contournement plus facile à proximité de la première solution fournie par @alecxe. Ici ça va:

function test() {
  var item = getItem().then(function(item) {
    console.log(item);
  });
}

function getItem() {
  return browser.wait(function() {
    return element(by.id('element-id')).getAttribute('attribute-name').then(function(value) {
      return value;
    });
  });
}

Étant donné que browser.wait() renvoie une promesse elle-même, elle peut être chaînée à une autre then() dans l'appelant, ce qui garantit le bon ordre d'exécution.

1
exbuddha