Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Nightmare – Simple browser automation (nightmarejs.org)
429 points by pkrein on Oct 6, 2014 | hide | past | web | favorite | 70 comments

Even after substituting the fancy ampersands on your homepage, and requiring nightmare your example still does not run:

  var Nightmare = require('nightmare');
  new Nightmare()
    .type('input[title="Search"]', 'github nightmare')

  node yahoo.js
  phantom stdout: TypeError: 'null' is not an object (evaluating 'element.value = text')
  phantom stdout:   phantomjs://webpage.evaluate():3
        throw er; // Unhandled stream error in pipe.
  TypeError: undefined is not a function
      at next (/private/tmp/night/node_modules/nightmare/lib/index.js:56:23)
      at f (/private/tmp/night/node_modules/nightmare/node_modules/once/once.js:16:25)
      at Proto.apply (/private/tmp/night/node_modules/nightmare/node_modules/phantom/node_modules/dnode/node_modules/dnode-protocol/index.js:123:13)
      at Proto.handle (/private/tmp/night/node_modules/nightmare/node_modules/phantom/node_modules/dnode/node_modules/dnode-protocol/index.js:99:19)
      at D.dnode.handle (/private/tmp/night/node_modules/nightmare/node_modules/phantom/node_modules/dnode/lib/dnode.js:140:21)
      at D.dnode.write (/private/tmp/night/node_modules/nightmare/node_modules/phantom/node_modules/dnode/lib/dnode.js:128:22)
      at SockJSConnection.ondata (stream.js:51:26)
      at SockJSConnection.EventEmitter.emit (events.js:107:17)
      at Session.didMessage (/private/tmp/night/node_modules/nightmare/node_modules/phantom/node_modules/shoe/node_modules/sockjs/lib/transport.js:220:25)
      at WebSocketReceiver.didMessage (/private/tmp/night/node_modules/nightmare/node_modules/phantom/node_modules/shoe/node_modules/sockjs/lib/trans-websocket.js:102:40)
The examples in the githubs pages readme don't run either. I am too lazy to debug this.

hey sorry about that, just realized i forgot to npm publish v1.1.0 -- published now hope that helps

Hey, I'm working on this atm:


which should help matters. Will reply when done.

I got it to run by providing a callback to the 'run' function: run(function(){ console.log('done'); });

By default there is no indication of completion, hence the log.

Quick example of how we use this at Segment... for each integration (https://segment.io/integrations) we need to create a vector logo. This got a bit tedious after the first 50 :) so we built nightmare + nightmare-swiftly so that our chat bot could "auto-generate" vector logos: https://cloudup.com/cEA-dTd3glM

Hope it's helpful!

Please note that because you used the base "phantom" library from npm it won't ever work with cluster (because node doesn't do the right thing with port=0 under cluster).

You'd have to switch to node-phantom-simple. Which might be worthwhile anyway because the phantom library you've used proved massively unstable at scale for us - I wrote it because of the need to work under cluster, and because dnode communication was bloated and unstable.

Hey Peter,

Swiftly lead dev here. Just wanted to say this is very cool! I was a little bit surprised to see us in your examples.

We've been looking into improving our end-to-end testing tools, but it looks like you guys have already taken care of it. Nice work! ;-)

Is it doing this by checking colored pixel areas and making SVG shapes for them? If so, whatever you use should replace Illustrator's Image Trace functionality, cause that is so bad at creating crisp vector copies of things.

Looks like they are submitting it to Swiftly, and then a human does it.

:( - I was hoping for a cool algorithm to determine that. Haha maybe I'll write one.

yep this

Could I accomplish multi-page form automation doing something like:

    // page 1
    .type('selector', 'value')

    // page 2
    .type('selector', 'value')
etc. ?

If so, that seems super easy and more straightforward than vanilla Shadow or even Casper.

that's exactly right

Thanks, this should be absolutely perfect for a project I've been procrastinating on :)

I've been wanting to programmatically get my transaction details from my bank for a while. I knew about phantomJS but never got around to trying it out. When I saw this I decided to give it a shot, and within half an hour I was able to log into my bank's website (a complicated multi-step process that I had failed to achieve with just POST requests).

Nice tool, thanks. The debugging could use a bit of work - whenever something went wrong it just spit out a bunch of "null is not an object" messages from phantom. Overall it was very easy to use though.

I really want to do this with the two accounts I have at different banks. Neither makes it easy to automatically download my transactions. What I want is to run a command to run to download the latest transactions and output some simple ledger-like[1] output.

When I have tried to do double entry account before it was tricky to keep up. I would spent a lot of time trying to figure out what I had already reconciled and what I had not.

1: http://www.ledger-cli.org/

Whats a good way to automate this to run? I see the getting started in the documentation says "Save it as hello.js and then run it from the command line" but Iwasnt sure if there are tools like CRON in Linux to automate the script.

That is the documentation for phantomjs, which is a stand-alone process. Nightmare is a package for nodejs (that interacts with a phantomjs process), so your code runs in a node context, where there are plenty of scheduling options, e.g. the node-cron package, or just plain setInterval().

Looks like DalekJS (http://dalekjs.com/)

Looks good, but my god that site is hard to look at.

Except without the cross-browser part.

I'm using casper now but this seems like it may be even easier.

Yeah, there's a ton of "easier to use" libraries atop Phantom. CasperJS is by far the most recognized and community-backed. Not sure what value all of these others provide.

I am one of the founders of a startup that sells a similar, proprietary library for Python and Java: http://heliumhq.com. Maybe some of the people reading this will find it interesting.

It's a polished website... and I know what javascript is, but they didn't do a good job of explaining what it is.

Browser automation? Is this a test suite of some sort, something like selenium? Or is it more like Mechanize?

I do like the work they've done with Phantom but the API is horrendous and I found myself wrapping the parts I used. Nightmare looks more complete and probably better tested than my wrapper. Well done.

Looks like an interesting library. I have no use for it right now but maybe one day. Definitely can see why this would be useful for some people though.

Their website has some serious style. It looks cool and original. Which raises a meta-issue that has been bugging me for a while. This is the bar you have to meet for even an open source project nowadays. It's not enough for you to pour your blood sweat and tears into something and then give it away for free. You then have to create slick looking site to market it and get people's attention.

Not really... Counterexample: http://www.haproxy.org/ :)

I think most of the people don't care about the fab wrap, as long as the product works properly.

obligatory self-promotion, for those interested in an easy to use PhantomJs: https://PhantomJsCloud.com

oh, and I'd love to let my users use nightmare in their scrips, but I don't know an easy way to sandbox the requested phantomjs instance :(

I use Ubuntu Linux, and I've got PhantomJS installed. Whether I use Nightmare, Nightmarejs, or Phantomjs on the command line this is what I get: ReferenceError: Can't find variable: Nightmare

Should there be more instructions for installing? I believe the brew command is something for Mac users only...

Shameless plug: I maintain Node-huxley (https://github.com/chenglou/node-huxley), which accomplishes what this project does, but without the need for writing automation code. Also compares previous/next screenshots for you automatically.

How is it different from http://nightwatchjs.org/ ?

Nightwatch runs against Selenium, Nightmare uses Phantom.js

With Selenium you have full cross browser support, while Phantom is Webkit based.

nightwatch looks awesome for testing, nightmare is for automation... building APIs for services that don't have them.

I currently only have experience using CasperJS which also wraps-around PhantomJS. This has different goals (simpler) and therefore a simpler API, though. The use case at Segment (automatically generating vector logos from a given graphic) is even cooler though, I think! Thanks for sharing!

Nice work!

Can you please provide an example for using `evaluate()` to get the page's content?

I tried this, but didn't get anything:

  new Nightmare()
    .evaluate(function (page) { return this.content; }, function (res) {console.log(res);})

extracting stuff seems to be a common use case so added an example to the readme for ya: https://github.com/segmentio/nightmare#examples

And, if you want a very very thin wrapper around Phantom (essentially a phantom script manager), feel free to have a look at this instead:


Pardon the shameless plug.

What is the project's background image (http://www.nightmarejs.org/nightmarejs.org/images/ground.jpg)?

That's a photo that Frank Hurley took on his (nearly doomed) antarctic adventure with Ernest Shackleton. You can find scads more photos here: http://www.kodak.com/US/en/corp/features/endurance/

Wow, thanks for the info! What an amazing story, and photos.

It really is. Hurley is one of my favorite photographers of all time; his stuff just captured the essence of the time so well!

As someone entirely unfamiliar with both Nightmare and PhantomJS, what is the typical use case? It isn't obvious to me from the examples or FAQs. Why prefer these over something like Selenium?

I assume because it's more light-weight and hence suited better for certain needs.

Very nice. FYI best practices are to have a CTA or indicator on your site to scroll down, so no one leaves thinking the whole site is just an image and title.

Segment usually puts out great tools and crisp sites!

Does anyone know how this compares to zombie js? I'm new to headless browser testing so apologies if question isn't relevant

I'm building a bot using this, any idea of proxies i can use to change the source ip's and how i can use it with a proxy?

Fantastic easy tool! There is a way to pass phantomjs command line options (eg. --ssl-protocol=X ) through nightmarejs?

Found it, line 108 in lib/index.js

  - phantom.create({ port: port }, function(instance) {
  + phantom.create({ port: port}, "--ssl-protocol=X", function(instance) {

Have you tried this? It's not working for me :|

I'm getting about:blank everytime I hit a web address using ssl.

Extra points for page design!

so... how does one query the DOM? It looks it has been left out of the api. Does this mean that Nightmare is only able to do brainless automation without checking browser results?

Interesting background... creepy is good.

Very nice!

Ordinarily I would file a website bug, but this happens so often I'm mentioning it here to hopefully stop others from doing it, too.

Please don't use fancy quotes or the fancy apostrophe for code examples on your webpage. It looks out-of-place with the rest of the fixed width font and, most importantly, it stops folks from being able to copy-and-paste your examples into their terminal or editor.

Sounds like a browser level or OS level plugin could be useful to check paste buffers and swap to|from fancy quotes.

the problem with Phantom.js is that compared to an actual browser it still falls short. I've given up on Phantom.js all together because it is actually not a true replacement for Selenium running on an actual browser. I found it far more reliable to have Firefox running on Xvfb for when I'm testing without worrying about Phantom.js behaving wildly.

It's definitely for a different use case. Phantom/Nightmare is for automating web page interaction, whereas Selenium is for cross-browser testing.

You can use Selenium for automation and web page interaction. There is just an overhead of running Xvfb but it's trivial to setup.

What I mean is that PhantomJS engine still falls short of a real browser. Advantage of running a real browser with Xvfb is that you won't ever have to worry about if the page is going to render properly or have it behave the way you expect it to. The overhead is not of a big deal, in fact it's a tradeoff for rendering accuracy.

Don't get me wrong headless browser like PhantomJS is headed in the right direction but if compatibility with website is crucial for your success, it is not enough and I just don't have a lot of confidence that it will replace a real browser with Xvfb.

Basically the Javascript libraries are reinventing a lot of the wheels that have already been done in other languages before the explosion of Node.js.

How is it not a real browser? It's basically a full WebKit based browser.

PhantomJS 1.9.7 is based on an ancient version of WebKit that lacks ES5 functions like Function.prototype.bind. It also crashes pretty frequently.

I can absolutely concur that it crashes frequently. I have high hopes v2 fixes this. Most of the crashes are due to WebKit bugs that have since been resolved in QT5.

I waited and waited but just gave up. I really hope they bring it up to speed.

I've reached the same conclusion for our suite of UI tests (which are based on Cucumber + Capybara + SitePrism) - Phantom has random issues that don't occur with any other browser/driver (e.g. elements not being found even if you add a long wait - our app is rich client side Angular so I suspect some JS issue is happening) and it's too hard to debug what is going on compared to Firefox + Xvfb (where you can just redirect the display to a real X display and see what is going on).

Yes, with selenium you can actually watch the entire test happen and see where things go wrong. Very easy to debug and understand but PhantomJS makes it really tough to find out why something failed because its headless. Sometimes I would try to take screenshots to figure out what was going on and even that would fail at times.

Maybe you'd be able to run more instances with PhantomJS compared to running Xvfb and a real browser because of lower memory consumption. I don't know if this is true.

How about slimer.js for FF?

firefoxdriver already exists in many other languages, I don't know what is the point of writing it all over again for javascript. The callback stuff gets messy. I still much prefer Python or even Java to write my tests.

Applications are open for YC Winter 2020

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact