Jason Yost
Jason Yost

Reputation: 4937

PhantomJS pass argument to evaluate

I have a small test app using NightmareJS as a wrapper for PhantomJS I want to test for the existence of a class on an element. I have this code:

new Nightmare()
  .goto(baseURL)
  .evaluate(function() {
    return document.querySelector('body');
  }, function(element) {
    element.className.should.equal(expected)
    callback();
  })
  .run();

How can I pass an argument to the querySelector method rather than hardcoding the tag?

I have tried

var tag = body;
new Nightmare()
      .goto(baseURL)
      .evaluate(function() {
        return document.querySelector(tag);
      }, function(element) {
        element.className.should.equal(expected)
        callback();
      })
      .run();

However PhantomJS always returns an error that it cannot find the variable.

How can I accomplish passing a variable argument to the querySelector method?

Upvotes: 2

Views: 1776

Answers (1)

Artjom B.
Artjom B.

Reputation: 61892

PhantomJS has two contexts. The DOM context (or page context) is sandboxed and is only accessible through evaluate(). evaluate() takes a function that is evaluated in the page, so the code inside cannot reference any variables or functions that are defined outside of it.

The signature of Nightmare's evaluate() function is the following:

function evaluate(func, callback/**, arg1, arg2...*/)

It means that additional values can be passed directly into the function as additional arguments. func, callback and arg1, arg2, ... are passed through phantomjs-node (which is used by Nightmare to actually interface with PhantomJS) and func, arg1, arg2, ... are then passed to PhantomJS's evaluate().

Note: The arguments and the return value to the evaluate function must be a simple primitive object. The rule of thumb: if it can be serialized via JSON, then it is fine.

Closures, functions, DOM nodes, etc. will not work!

Proper usage would be:

var tag = "body";
new Nightmare()
  .goto(baseURL)
  .evaluate(function(innertag) {
    return document.querySelector(innertag).className;
  }, function(className) {
    className.should.equal(expected);
    callback();
  }, tag)
  .run();

Upvotes: 7

Related Questions