How to wait for the backend in Protractor?

2019-06-08 05:14发布

I'm testing a web page where the user can send a message to another via a textinput. A POST request is then send on the server and the message is dumped on the disk in the var/mail/new folder.

After automatising the sending of the message in the page with Protractor I'm calling browser.waitForAngular() and browser.driver.sleep(4000) to leave time for the backend to write the mail on the disk.

After these calls the check of the email's presence fails. When looking in the Unix shell, I can confirm that the email was sent and also the next test marked with in Jasmine with it confirms the presence of the email.

Why is browser.driver.sleep(4000) not effective to wait for the backend to proceed? How can I correct the following code?

it("is possible to send a message", function() {
    shared.loginContributor();

    var mailsBeforeMessaging =
        fs.readdirSync(browser.params.mail.queue_path + "/new");
    console.log('mailsBeforeMessaging');
    console.log(mailsBeforeMessaging.length);
    console.log(fs.lstatSync(browser.params.mail.queue_path + "/new"));

    var usersListing = new UserPages.UsersListing().get();
    var annotatorPage = usersListing.getUserPage("annotator");

    annotatorPage.sendMessage("title5", "content64");

    exec("/tmp/check.sh");

    // we expect the message widget to disappear
    var button = element(by.css(".user-profile-info-button"));
    console.log('waiting');
    browser.wait(EC.elementToBeClickable(button), 5000);
    console.log('waiting is finished');
    expect(EC.elementToBeClickable(button)).toBeTruthy();

    // wait for mail to be dumped on the disk?
    browser.waitForAngular();
    browser.driver.sleep(4000);

    exec("/tmp/check.sh");

    var mailsAfterMessaging =
        fs.readdirSync(browser.params.mail.queue_path + "/new");
    console.log('mailsAfterMessaging');
    // ERROR: here the number of emails is NOT incremented
    console.log(mailsAfterMessaging.length);
    console.log(fs.lstatSync(browser.params.mail.queue_path + "/new"));
});

it("xyz", function() {

    console.log(fs.lstatSync(browser.params.mail.queue_path + "/new"));
    // here the number of emails is incremented
    var mailsAfterMessaging =
        fs.readdirSync(browser.params.mail.queue_path + "/new");
    console.log('mailsAfterMessaging');
    console.log(mailsAfterMessaging.length);
});

1条回答
ゆ 、 Hurt°
2楼-- · 2019-06-08 05:44

Most of the Protractor functions do not do anything. They queue something up to be done later, and return promise to do it. After an it block schedules a bunch of things to do, they actually start happening (via the promises they registered in the ControlFlow).

Your checks, however, are all executing immediately. So, they are happening before any of the protractor calls accomplish anything.

Use then to make the waiting and dependencies explicit in your test. Like this:

annotatorPage.sendMessage("title5", "content64").then(function() {
    exec("/tmp/check.sh");
});

or:

browser.wait(EC.elementToBeClickable(button), 5000).then(function() {
   console.log('wait-for-clickable has completed'); // B
});
console.log('wait-for-clickable has been scheduled'); // A

See the Protractor Control Flow documentation and the Webdriver JS API doc.

Its not you. This is a crazy API to learn because it does not act at all like anyone familiar with normal synchronous programming would expect.

查看更多
登录 后发表回答