Protractor: Comment utiliser browser.wait() pour attendre que l'URL change ?

Créé le 13 mars 2014  ·  26Commentaires  ·  Source: angular/protractor

salut

Je veux écrire un test Protractor qui attend que l'URL actuelle change, donc j'ai regardé browser.wait() , combiné avec browser.getCurrentUrl() .

Cependant, je ne sais pas comment utiliser les deux ensemble : la méthode browser.wait() accepte comme premier paramètre une fonction qui renverra une valeur booléenne - cependant, browser.getCurrentUrl() renvoie une promesse.

Ma première tentative, qui a échoué (comme je m'y attendais), ressemble à ceci :

var currentUrl;
browser.getCurrentUrl().then(function (url) {
    currentUrl = url;
}).then(function () {
    return browser.wait(function () {
        return browser.getCurrentUrl().then(function (url) {
            return url !== currentUrl;
        });
    });
}).then(function () {
    // continue testing
});

Quelqu'un peut-il aider?

Merci beaucoup

Mat

Commentaire le plus utile

Ok, je sais que c'est bien tard, mais je pense que vous pouvez faire quelque chose comme ça:

var EC = browser.ExpectedConditions;
browser.wait(EC.urlContains('Expected URL'), timeout); // Checks that the current URL contains the expected text
browser.wait(EC.urlIs('Expected URL'), timeout); // Checks that the current URL matches the expected text

Tous les 26 commentaires

Comment cela échoue-t-il ? Est-ce un problème d'expiration trop précoce ?
Je ne trouve pas dans la documentation quel est le délai d'attente par défaut lorsqu'aucun paramètre de délai d'attente n'est spécifié dans browser.wait()

Il expire après 30 secondes (comme je l'ai défini dans mon fichier protractor.conf.js ) - ce qui semble indiquer que le browser.wait() ne revient jamais.

J'ai réessayé, cette fois en spécifiant un paramètre de délai d'attente de 12000 - tous les tests ont de nouveau expiré, cette fois après 12 secondes.

Je ne me souviens pas exactement pourquoi, mais à un moment donné, j'ai dû passer de browser.getCurrentUrl() à browser.driver.getCurrentUrl() et j'ai même créé cette fonction d'assistance :

var waitForCurrentUrl = function(timeout) {
    if (timeout == null) {
        timeout = browser.manage().timeouts().pageLoadTimeout;
    };

    return browser.driver.wait(function() {
        // Return a condition. Code will continue to run until is true 
        return browser.driver.getCurrentUrl().then(function(url) {
            return url;
        }, function(err) {
            // errored  .. TODO: retry
            throw err;
        });
    }, timeout, 'Expectation error: Timed out waiting for current url');
};

Super, merci Léo !

Je vais essayer.

Si ça marche, je proposerai un changement de document à @juliemr :-)

Hmmm... on dirait que j'avais raison à l'origine - utiliser browser.getCurrentUrl() et browser.wait() fonctionnent bien pour moi pour le moment :

var currentUrl;
browser.getCurrentUrl().then(function(url) {
        currentUrl = url;
    }
).then(function() {
        browser.wait(function() {
            return browser.getCurrentUrl().then(function (url) {
                return url !== currentUrl;
            });
        });
    }
).then(function () {
    // continue testing
});

Cependant, je rencontre des problèmes lorsque j'essaie d'utiliser getText() de la même manière :

browser.wait(function () {
    return methodThatReturnsWebElementViaPromise().then(function (ele) {
            return ele.getText();    // <-- occasional failure point
        }
    ).then(function (text) {
            return text === 'changed text';
        }
    );
}).then(function () {
    // continue testing
});

Cela fonctionne parfois, mais à d'autres moments, cela échoue avec ce message : StaleElementReferenceError: stale element reference: element is not attached to the page document

Donc, ce que je pense est à l'origine de l'erreur, c'est qu'au moment où l'appel à getText() est exécuté, le contenu de l'élément a changé, rendant ainsi la référence obsolète.

Qu'est-ce que tu penses?

Et pouvez-vous suggérer une solution de contournement? (@juliemr?)

Référence pour tester l'URL : https://github.com/angular/protractor/blob/master/spec/withLoginConf.js#L24

Pour la deuxième question (getText), je suppose que votre methodThatReturnsWebElementViaPromise n'est appelé qu'une seule fois (car la promesse est résolue une fois, puis les invocations ultérieures renvoient simplement la valeur), au lieu d'être appelée à chaque fois. Il semble que vous vouliez retrouver l'élément à chaque fois ?

Bon j'ai fini par trouver une solution :

function waitForElementTextToChange (elementId, textToWaitFor) {
    return browser.wait(function () {
        return element(by.id(elementId)).getText().then(function (text) {
                return text === textToWaitFor;
            },
            function () {
                return element(by.id(elementId)).getText().then(function (text) {
                    return text === textToWaitFor;
                });
            }
        );
    });
}

Vous pouvez voir que j'appelle le element(by.id(elementId)).getText() une deuxième fois, dans le gestionnaire d'erreurs pour la première fois - c'est parce que j'ai toujours trouvé que StaleElementReferenceError s seraient lancés, et de manière très imprévisible (mais parfois pas du tout).

Je suppose que c'est à cause d'une sorte de condition de concurrence: dans le temps entre les appels à element(by.id(elementId)) et getText() , Angular avait mis à jour le DOM avec une nouvelle valeur - juste une supposition cependant.

Ce n'est donc pas une solution idéale, mais cela fonctionne de manière cohérente. Et si je comprends bien, toute erreur qui se produit lors du deuxième appel getText() sera propagée dans la chaîne.

Notez également que j'ai simplifié mon code afin que je n'aie affaire qu'à un ID DOM, et que je n'ai plus besoin d'utiliser la méthode qui a renvoyé une promesse.

Au cas où cela pourrait aider d'autres personnes à l'avenir, voici la méthode que j'ai écrite pour attendre que l'URL passe à une valeur particulière (spécifiée par une regex) :

/**
 * <strong i="6">@name</strong> waitForUrlToChangeTo
 * <strong i="7">@description</strong> Wait until the URL changes to match a provided regex
 * <strong i="8">@param</strong> {RegExp} urlRegex wait until the URL changes to match this regex
 * <strong i="9">@returns</strong> {!webdriver.promise.Promise} Promise
 */
function waitForUrlToChangeTo(urlRegex) {
    var currentUrl;

    return browser.getCurrentUrl().then(function storeCurrentUrl(url) {
            currentUrl = url;
        }
    ).then(function waitForUrlToChangeTo() {
            return browser.wait(function waitForUrlToChangeTo() {
                return browser.getCurrentUrl().then(function compareCurrentUrl(url) {
                    return urlRegex.test(url);
                });
            });
        }
    );
}

Merci @mcalthrop , les deux fonctions fonctionnent plutôt bien !

Excellent! Heureux qu'ils aient aidé.

Merci pour ce @mcalthrop ces deux fonctions se sont avérées très utiles.

Super merci @mcalthrop

Merci, @mcalthrop. Très utile.

Quelqu'un d'entre vous peut-il m'expliquer comment écrire "pageLoadTimeout()" pour le pilote Web Selenium sur Node.JS par Jasmine ?
Merci.

Cela a très bien fonctionné pour moi

`````` js
var attendueUrl = "/url-que-vous-attendez-pour" ;
var source = Rx.Observable
.intervalle(200)
.take(20) // nombre de tentatives / timeout
.flatMap(fonction () {
return browser.driver.getCurrentUrl();
})
.filter(fonction (url) {
URL de retour == URL attendue ; // vous pouvez ajuster ceci
}).take(1) // après avoir obtenu une URL, les correspondances sont terminées
.defaultIfEmpty(); // si après le dépassement du délai d'attente, rien n'est trouvé dans le flux, nous émettons un élément vide

    var subscription = source.subscribe(
        function (url) {
            if (url) {
                next();
            } else {
                next("Timeouted out waiting for url: " + expectedUrl);
            }
        },
        function (err) {
            next(err);
        });```

``````

J'ai dû utiliser browser.driver.wait et browser.driver.getCurrentUrl

Impossible d'utiliser @juliemr attendre l'URL après la promesse de connexion https://github.com/angular/protractor/blob/master/spec/withLoginConf.js#L28 avec @mattfritz cucumber framework https://github.com/mattfritz/ rapporteur-concombre-cadre

Si la promesse et le test sont réussis, il n'y a pas de problème et tout fonctionne plutôt bien. Le problème est lorsque le processus de test d'échec de la promesse s'arrête et que les autres tests ne s'exécutent pas.

Une idée pour maintenir le processus en cours? Ce test échoue mais l'autre pourrait passer.

Par exemple:

[10:54:33] I/hosted - Using the selenium server at http://localhost:4444/wd/hub
[10:54:33] I/launcher - Running 1 instances of WebDriver
Feature: xxx login
    As a user of xxx login
    I should be able to login in xxx using an existent user
  <strong i="13">@critical</strong>
  Scenario: Check xxx login
    Given The xxx login page is open
    Then The title should contain "xxx"
[10:54:57] E/launcher - url has not changed to /lobby/
Wait timed out after 10020ms
[10:54:57] E/launcher - Error: url has not changed to /lobby/
Wait timed out after 10020ms
    at /Users/adolfocabrera/xxx/QA-testing/Selenium/xxx/node_modules/selenium-webdriver/lib/promise.js:2364:22
    at ManagedPromise.invokeCallback_ (/Users/adolfocabrera/xxx/QA-testing/Selenium/xxx/node_modules/selenium-webdriver/lib/promise.js:1379:14)
    at TaskQueue.execute_ (/Users/adolfocabrera/xxx/QA-testing/Selenium/xxx/node_modules/selenium-webdriver/lib/promise.js:2913:14)
    at TaskQueue.executeNext_ (/Users/adolfocabrera/xxx/QA-testing/Selenium/xxx/node_modules/selenium-webdriver/lib/promise.js:2896:21)
    at /Users/adolfocabrera/Mavrix/xxx/Selenium/xxx/node_modules/selenium-webdriver/lib/promise.js:2775:27
    at /Users/adolfocabrera/Mavrixxxx/Selenium/xxx/node_modules/selenium-webdriver/lib/promise.js:639:7
    at process._tickCallback (internal/process/next_tick.js:103:7)
From: Task: url has not changed to /lobby/
    at ControlFlow.wait (/Users/adolfocabrera/xxx/QA-testing/Selenium/xxx/node_modules/selenium-webdriver/lib/promise.js:2352:17)
    at WebDriver.wait (/Users/adolfocabrera/xxx/QA-testing/Selenium/xxx/node_modules/selenium-webdriver/lib/webdriver.js:712:29)
    at ProtractorBrowser.to.(anonymous function) [as wait] (/Users/adolfocabrera/xxx/QA-testing/Selenium/xxx/node_modules/protractor/built/browser.js:68:29)
    at waitForUrlToChangeTo (/Users/adolfocabrera/xxx/QA-testing/Selenium/xxx/features/utils/wait.utils.js:19:32)
    at ManagedPromise.invokeCallback_ (/Users/adolfocabrera/xxx/QA-testing/Selenium/xxx/node_modules/selenium-webdriver/lib/promise.js:1379:14)
    at TaskQueue.execute_ (/Users/adolfocabrera/xxx/QA-testing/Selenium/xxx/node_modules/selenium-webdriver/lib/promise.js:2913:14)
    at TaskQueue.executeNext_ (/Users/adolfocabrera/xxx/QA-testing/Selenium/xxx/node_modules/selenium-webdriver/lib/promise.js:2896:21)
    at /Users/adolfocabrera/xxx/QA-testing/Selenium/xxx/node_modules/selenium-webdriver/lib/promise.js:2775:27
    at /Users/adolfocabrera/xxx/QA-testing/Selenium/xxx/node_modules/selenium-webdriver/lib/promise.js:639:7
    at process._tickCallback (internal/process/next_tick.js:103:7)
[10:54:57] E/launcher - Process exited with error code 199

npm ERR! Darwin 15.6.0
npm ERR! argv "/Users/adolfocabrera/.nvm/versions/node/v5.11.1/bin/node" "/Users/adolfocabrera/.nvm/versions/node/v5.11.1/bin/npm" "run" "test-desktop-local"
npm ERR! node v5.11.1
npm ERR! npm  v3.10.5
npm ERR! code ELIFECYCLE
npm ERR! [email protected] test-desktop-local: `protractor conf.js --seleniumAddress 'http://localhost:4444/wd/hub'`
npm ERR! Exit status 199
npm ERR! 
npm ERR! Failed at the [email protected] test-desktop-local script 'protractor conf.js --seleniumAddress 'http://localhost:4444/wd/hub''.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the protractor-cucumber-tests package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     protractor conf.js --seleniumAddress 'http://localhost:4444/wd/hub'
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs protractor-cucumber-tests
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls protractor-cucumber-tests
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /Users/adolfocabrera/xxx/QA-testing/Selenium/xxx/npm-debug.log

@aluzardo Lorsque vous utilisez protractor-cucumber framework , il est conseillé d'utiliser les délais d'attente cucumberjs plutôt que l'attente du rapporteur, vous devez augmenter votre délai d'attente par défaut pour de tels scénarios, essentiellement lorsque la promesse n'est pas résolue dans le temps par défaut spécifique, c'est-à-dire 5000 ms actuellement dans cucumberJS , vous obtiendrez une telle exception. Je vous suggérerais donc d'augmenter setDefaultTimeout : 60 * 1000 au niveau global afin que vos promesses aient suffisamment de temps pour être résolues et que vos scripts soient exécutés !

Merci @idaneliz

J'ai augmenté le temps il y a quelque temps https://github.com/aluzardo/protractor-cucumber-tests/blob/master/features/support/env.js

J'ai essayé d'augmenter plus le temps mais j'ai eu la même erreur.

@aluzardo Il n'y a aucun problème avec votre configuration. Au lieu d'utiliser des rappels, vous devez renvoyer vos promesses, cucumberjs prend en charge les promesses, c'est juste que votre scénario prend un certain temps pour être résolu, donc votre définition d'étape doit savoir que, actuellement, elle attend le rappel. Pour plus de détails, veuillez consulter ces discussions SO -
tests de concombre de rapporteur montrés réussis
configurer le rapporteur avec le concombre

C'est plus une question de support, vous obtiendrez des réponses plus rapidement si vous la soulevez dans Stackoverflow ou Gitter !

@idaneliz @juliemr et @mattfritz

J'ai trouvé que si j'utilisais la version 3.3.0 du rapporteur, tout fonctionnait plutôt bien.

Le problème est d'utiliser la version ^ 4.0.2

C'est le seul indice que j'ai pu trouver. Je vais utiliser le rapporteur 3.3.0 comme solution temporaire.

J'ai également remarqué que les commandes browser.wait étaient cassées après la mise à niveau vers la version 4.0.4. @juliemr des idées ? Ceux-ci fonctionnaient parfaitement avec l'ancienne version du rapporteur.

Ok, je sais que c'est bien tard, mais je pense que vous pouvez faire quelque chose comme ça:

var EC = browser.ExpectedConditions;
browser.wait(EC.urlContains('Expected URL'), timeout); // Checks that the current URL contains the expected text
browser.wait(EC.urlIs('Expected URL'), timeout); // Checks that the current URL matches the expected text

Merci @pittgoose , ça marche pour moi. J'ai passé quelques jours à chercher une solution.

Au cas où cela pourrait aider d'autres personnes à l'avenir, voici la méthode que j'ai écrite pour attendre que l'URL passe à une valeur particulière (spécifiée par une regex) :

/**
 * <strong i="7">@name</strong> waitForUrlToChangeTo
 * <strong i="8">@description</strong> Wait until the URL changes to match a provided regex
 * <strong i="9">@param</strong> {RegExp} urlRegex wait until the URL changes to match this regex
 * <strong i="10">@returns</strong> {!webdriver.promise.Promise} Promise
 */
function waitForUrlToChangeTo(urlRegex) {
    var currentUrl;

    return browser.getCurrentUrl().then(function storeCurrentUrl(url) {
            currentUrl = url;
        }
    ).then(function waitForUrlToChangeTo() {
            return browser.wait(function waitForUrlToChangeTo() {
                return browser.getCurrentUrl().then(function compareCurrentUrl(url) {
                    return urlRegex.test(url);
                });
            });
        }
    );
}

Nice, pouvez-vous partager où vous avez défini cette méthode globalement ?

Qu'est-ce que c'est
بتاريخ ٠٣‏/١٢‏/٢٠١٩ ١٠:٤٩ م، كتب "Emanuel" [email protected] :

Au cas où cela pourrait aider d'autres personnes à l'avenir, voici la méthode à laquelle j'ai écrit
attendez que l'URL passe à une valeur particulière (spécifiée par une regex) :

/** * @name waitForUrlToChangeTo * @description Attend que l'URL change pour correspondre à une regex fournie * @param {RegExp} urlRegex attend que l'URL change pour correspondre à cette regex * @returns {!webdriver.promise.Promise} Promise */ fonction waitForUrlToChangeTo(urlRegex) {
var URLactuelle ;

return browser.getCurrentUrl().then(function storeCurrentUrl(url) {
        currentUrl = url;
    }
).then(function waitForUrlToChangeTo() {
        return browser.wait(function waitForUrlToChangeTo() {
            return browser.getCurrentUrl().then(function compareCurrentUrl(url) {
                return urlRegex.test(url);
            });
        });
    }
);

}

Nice, pouvez-vous partager où vous avez défini cette méthode globalement ?


Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/angular/protractor/issues/610?email_source=notifications&email_token=ANOOAMURALFHEX4YOP34GXTQW2Z55A5CNFSM4ANFSW6KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEF2S6OQ#issue32comment-561 ,
ou désabonnez-vous
https://github.com/notifications/unsubscribe-auth/ANOOAMQP5Z3PFJACAGR6K7TQW2Z55ANCNFSM4ANFSW6A
.

Cette page vous a été utile?
0 / 5 - 0 notes