How to make nightmare forcefully timeout
Asked Answered
K

1

2

As the title implies I am trying to make my script timeout forcefully, specifically if a condition (that returns done()) isn't met.

Here is some code:

import * as Nightmare from "nightmare";

describe("Login Page", function() {
  this.timeout("30s");

  let nightmare = null;
  beforeEach(() => {
    nightmare = new Nightmare({ show: true });
  });

  let pageUrl;

  describe("give correct details", () => {
    it("should log-in, check for current page url", done => {
      nightmare
        .goto(www.example.com/log-in)
        .wait(5000)
        .type(".input[type='email']", "username")
        .type(".input[type='password']", "password")
        .click(".submit")
        .wait(3000)
        .url()
        .exists(".navbar")
        .then(function(result) {
          if (result) {
            done();
          } else {
            console.log("failure");
                // I want it to timeout here
          }
        })
        .catch(done);
    })
        .end()
        .then(url => {
          pageUrl = url;
          console.log(pageUrl);
        })
  });
});

If I have any other mistakes in my code feel free to let me know.

Kella answered 26/4, 2018 at 1:54 Comment(2)
You will need to show us some of your actual nightmare code and then add some explanation about what exactly in the code you want a timeout for in order for us to be able to help you with any level of specifics.Haplography
@Haplography done.Kella
H
3

You can use Promise.race() to implement a timeout. I don't know your testing code so I'll show just the inner part that gives you a timeout on the nightmare request and you can insert that into your test framework.

// utility function that returns a rejected promise after a timeout time
function timeout(t, msg) {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            reject(new Error(msg));
        }, t);
    });
}

Promise.race([
    nightmare
        .goto(www.example.com / log - in )
        .wait(5000)
        .type(".input[type='email']", "username")
        .type(".input[type='password']", "password")
        .click(".submit")
        .wait(3000)
        .url()
        .exists(".navbar")
        .end()
    , timeout(5000, "nightmare timeout")
]).then(result => {
    // process successful result here
}).catch(err => {
    // process error here (could be either nightmare error or timeout error)
});

The concept here is that you create a race between the promise from your nightmare request and a promise from the timeout. Whichever one resolves or rejects first wins and causes the end of the promise processing. If the Promise.race(...).then() handler triggers, then it's because your nightmare request finished before the timeout. If the Promise.race(...).catch() handler fires, then it's because either the nightmare request failed or you hit the timeout. You can tell which it is by looking at the error object you get with the reject.

Note, there are also all sorts of timeout options built into nightmare as described in the doc here. You may also find one of those built-in options suits whatever the exact purpose of your timeout is.

Haplography answered 26/4, 2018 at 5:24 Comment(7)
I don't have time to test this now, I added my test code if you need to update your answer. I will test It tomorrow, thanks for the answerKella
This won't work as you are taking .then and .catch out of the scope of nightmare (which I need a .catch in the scope of it to catch .done() to finish the script)Kella
@AidanelGoste - The Promise.race returns a promise that you can use .then and .catch on. That's the entire point here. I don't see any scope issue. Both .then and .catch will tell you when nightmare is done.Haplography
The issue is the comma you use at .end() because the promise.race ends just after the timeout() it errors everything under it out. I am using typescript so that might be the main issueKella
@AidanelGoste - That comma is because we're declaring an array of two items. One item is the return value from .end() which is a promise. The other is the timeout promise. We pass this array to Promise.race and it watches both promises for us and notifies on .then and .catch from the promise it returns.Haplography
@AidanelGoste - Please read about what Promise.race does. It sounds like you dont really understand that and how it is being used here. I'm on my phone so can't type a lot.Haplography
I'll get back to you soon, I see where I went wrongKella

© 2022 - 2024 — McMap. All rights reserved.