Horseman/PhantomJS - How to check for errors and prevent creating cookies?

309 Views Asked by At

I'm using node-horseman on a project that creates RSS Alerts on Google Alerts. The user that hasn't connected yet must log-in with his/her Google account through our application, to then be able to retrieve the feed list (s)he has. The application is basically used to auto-post on Facebook Pages news about any RSS feed created.

So far, the login function is the following:

* login() {
  if (!this.email || !this.password) {
    this.addError(HTTPResponse.STATUS_FORBIDDEN, 'E-mail and Password are necessary')

    return false
  }

  const horseman = new Horseman({ cookiesFile })

  return new Promise((resolve, reject) => {
    horseman
      .open('https://accounts.google.com')
      .type('input[type="email"]', this.email)
      .click('#next')
      .wait(1000)
      .type('input[type="password"]', this.password)
      .click('#signIn')
      .wait(3000)
      .close()

    setTimeout(function() {
      resolve(true)
    }, 3000)
  })
}

Very simple. It logs in and create a cookiesFile to be able to create new feeds and retrieve the existing ones. But it's totally not fail proof since there's no way to check for errors, and I couldn't find an example or make anything wok. I tried to use evaluate() and check if there's the .error_msg tag, but it throws an error in the phantomJS Unhandled rejection fn:

...
.wait(1000)
.evaluate(function() {
  if (jQuery('.error-msg').length > 0) {
    this.addError(HTTPResponse.STATUS_INTERNAL_SERVER_ERROR, 'Error!')
    return false
  }
})
...

It doesn't throw any errors not interrupts the execution and still creates a bad cookies file.

1

There are 1 best solutions below

4
Vaviloff On BEST ANSWER

When working with PhantomJS-like libraries it's very important to get the concept of two main different contexts: one is the context of the script (which you write to automate dealing with a target site) and the other is the context of the target site's page. These contexts to do not intersect, they have different variables and capabilities.

Everything that happens inside of page.evaluate(), happens in the context of a browser page. You can actually visualise that code as being executed in console of your (Chrome|Firefox|Safari) browser at that site.

You can execute this in console at Google login page

if (jQuery('.error-msg').length > 0) {
   // ...
}

But when you write

  if (jQuery('.error-msg').length > 0) {
    this.addError(HTTPResponse.STATUS_INTERNAL_SERVER_ERROR, 'Error!')
    return false
  }

it will throw an error, because you've mixed the two contexts. There is no .addError method on that Google page, it's in your script context.

Instead you could write

.evaluate(function() {
  if (jQuery('.error-msg').length > 0) {
    return { 
      errors : jQuery('.error-msg').length,
      message : "Some message about errors"
    }
  }
})
.then(function(result){
  if(result.errors > 0)
  {
     // ...
  }
})

See the docs on using evaluate in Horseman: https://github.com/johntitus/node-horseman#evaluatefn-arg1-arg2