Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Screenshot callback halts nightmare from advancing down the chain #934

Closed
tlshaheen opened this issue Dec 26, 2016 · 6 comments
Closed

Screenshot callback halts nightmare from advancing down the chain #934

tlshaheen opened this issue Dec 26, 2016 · 6 comments

Comments

@tlshaheen
Copy link

tlshaheen commented Dec 26, 2016

I have an issue similar to #555, but I'm not sure it's the same cause so I'm opening a new issue. I'm using nightmare v2.9.0. When the following code runs, it takes the screenshot, and "screenshot taken" is loaded to the console - but the window is never closed, run() is never called. If I enter a path like nightmare.png instead of the callback, it works. But the callback seems to freeze Nightmare.

Should I be returning something other than true from my callback, or calling another method inside my screenshot() callback to tell Nightmare to keep moving down the chain?

I tried one suggestion from #555 but no dice.

My end goal from the screenshot callback is to save the screenshot to AWS S3, directly inside the callback. But the problem exists without even having any of the S3 putObject() code in the callback.

var Nightmare = require('nightmare');
var nightmare = Nightmare({ show: true });
nightmare
    .goto('http://www.goldencityfooddelivery.com/index.php?main_page=index&cPath=14')
    .select('select[name="products_id[573]"]', '1')
    .click('#submit2')
    .wait('#cartDefaultHeading')
    .screenshot(function(something, theBuffer) {
        console.log('screenshot taken');
        return true;
    })
    .end()
    .run(function (err, nightmare) {
        if (err) return console.log(err);
        console.log('Done!');
    });
@jekku
Copy link
Contributor

jekku commented Dec 29, 2016

Instead of specifying the 'done' callback exclusively, specify the path and a simple callback

const path = '/some/path/someFileName.jpg';
nightmare.screenshot(path, () => console.log('screenshot taken'));

Correct me if I'm wrong, but .end(), is also a thenable which you can use to do something like:

nightmare.screenshot(path, () => console.log('screenshot taken'))
  .end()
  .then(() => {
    s3Library.uploadToBucket(path); // LOL just guessing some API function names
  });

@jekku
Copy link
Contributor

jekku commented Dec 29, 2016

Please update me. I usually use async-await / generators for nightmareJS but I hope this works for you.

@rosshinkley
Copy link
Contributor

.screenshot() does not take a function callback (at least, not anymore). What version of Nightmare are you using, @tlshaheen?

@jekku
Copy link
Contributor

jekku commented Jan 3, 2017

@rosshinkley https://github.com/segmentio/nightmare/blob/master/lib/actions.js#L600

I think the current branch still does. It just isn't documented. The top level callback is bubbled down as a callback to fs.writeFile.

@rosshinkley
Copy link
Contributor

@jekku I don't think that does what you think it does, and now that you've pointed it out, I think I see the problem. You can pass a function like that, but it will do exactly what @tlshaheen said - it will prevent downstream execution of the Nightmare chain. What that is looking for is the internal done callback as .screenshot() has optional parameters.

To make things clearer, an example might be helpful:

nightmare.goto('http://www.example.org')
  .screenshot((err, buf) => {
    console.log('hello from screenshot callback');
    // do something with the buffer
    return "some value";
  })
  .end()
  .then((something) => console.log(something));

This will print hello from screenshot callback, but will never advance to the .end() because the done callback that tells Nightmare to move onto the next step - the one specified in the line you highlighted - is never called.

So while what i said is technically incorrect - .screenshot() does take a callback, but it's supposed to be internal to make chaining work - I stand by my original statement. I don't think .screenshot() takes a user-passable function callback as originally posted.

For completeness, if you wanted the buffer, the above example is easily fixed:

nightmare.goto('http://www.example.org')
  .screenshot()
  .end()
  .then((buffer) => {
    // do something with the buffer...
  });

I'm still curious what version the original example was written against and/or where the example came from.

@casesandberg
Copy link

Looks like this is resolved. I am going to close this for now but feel free to open a new issue if you are still having problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

4 participants