Skip to content

Instantly share code, notes, and snippets.

@uberbrady
Last active December 21, 2015 05:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save uberbrady/6259024 to your computer and use it in GitHub Desktop.
Save uberbrady/6259024 to your computer and use it in GitHub Desktop.
Very sloppy first stab at node-phantom support for cucumber tests. Requires a *binary* install of phantom-js that is in your PATH, and requires the npm "node-phantom" (npm install node-phantom)
// features/support/after_hooks.js
var myAfterHooks = function () {
this.After(function(callback) {
// Again, "this" is set to the World instance the scenario just finished
// playing with.
// We can then do some cleansing:
//this.emptyDatabase(); //shut down some web server things?
//this.shutdownFullTextSearchServer();
// Release control:
this.phantom.exit();
callback();
});
};
module.exports = myAfterHooks;
var myStepDefinitionsWrapper = function () {
this.World = require("../support/world.js").World; // overwrite default World constructor
// I *HAVE* to do this. Or else I guess I get a "default world" - and really, who wants that?
this.Given(/^I go to "(.*)"$/, function (url,callback) {
this.phantom_page.open(url,callback);
//this.browser.visit(url,callback);
});
this.Given(/^an HTML document like:$/, function(htmlcontents, callback) {
// express the regexp above with the code you wish you had
//console.warn("OH MAH GAH - lookie this doco: "+string);
//callback.pending();
var that=this;
this.phantom_page.set('content',htmlcontents,function (result) {
//onLoadFinished
that.phantom_page.onLoadFinished=function () {
callback();
};
}); //do I callbakc?
});
this.Then(/^I should see "(.*)" as the page title$/, function(title, callback) {
// matching groups are passed as parameters to the step definition
//console.warn("Do we have these method definitions at all? :"+this.has_title+" or visit: "+this.visit);
this.phantom_page.evaluate(function() {return document.title;},function (err,titletext) {
if ( titletext!= title || err) {
// You can make steps fail by calling the `fail()` function on the callback:
callback.fail(new Error("Expected to be on page with title " + title + ", not "+titletext+" (error was: "+err+")"));
} else {
callback();
}
});
});
this.Then(/^I should see "(.*)" on the page$/, function(content,callback) {
this.phantom_page.evaluate(function() {return document.body.innerHTML;},function (err,bodytext) {
console.warn("Errr is: "+err+" and bodytext is: "+bodytext);
if(bodytext.indexOf(content)!= -1) {
callback();
} else {
callback.fail(new Error("Expected to find "+content+" on the page, but got: "+bodytext+"(and error of: "+err+")"));
}
});
})
this.Given(/^I fill out the field "([^"]*)" with "([^"]*)"$/, function(fieldname, fieldvalue, callback) {
// express the regexp above with the code you wish you had
//this.browser.fill(fieldname,fieldvalue,callback);
//callback.pending();
//return;
console.warn("I AM LOOKING TO SET FIELD: "+fieldname+" TO VALUE: "+fieldvalue);
var that=this;
this.phantom_page.evaluate(function (fieldname) {
//THIS IS ALL PHANTOMJS-context, not node!
console.warn("Page-evaluate to set field - trying to set "+fieldname);
var field=document.forms[0].elements[fieldname]; //do this better; not necessarily forms[0], maybe document.getElementById or something similar? Queryselectall?
console.warn("Field is: "+field);
//field.focus();
if(field) {
field.focus();
return true;
} else {
return false;
}
}, function (err,res) {
if(!err && res) {
console.warn("Selecting field went OK");
that.phantom_page.sendEvent("keypress",fieldvalue,null,function (err2) {
console.warn("I think I sent the keypress OK?! Err: "+err2);
if(!err2) {
callback();
} else {
callback.fail(new Error("Couldn't send text: "+fieldvalue+" err: "+err2));
}
});
} else {
callback.fail(new Error("Couldn't select form element '"+fieldname+"' to fill in"));
}
},fieldname);
});
this.Given(/^then I tab off the field "([^"]*)"$/, function(fieldname,callback) {
// express the regexp above with the code you wish you had
//this.browser.blur();
//this.browser.field(this.browser.focused).blur();
//this.browser.fire(this.browser.field(fieldname),"onchange");
this.phantom_page.evaluate(function () {
if(document.activeElement) {
document.activeElement.blur();
}
},function (err) {
if(!err) {
callback();
} else {
callback.fail(new Error("Blur failure: "+err));
}
});
});
this.Then(/^I should see a tag with an id of "([^"]*)" and a class of "([^"]*)"$/, function(id, classname, callback) {
// express the regexp above with the code you wish you had
var selector="#"+id; //+"[class~="+classname+"]"
console.warn("SELECTOR IS: "+selector);
this.phantom_page.evaluate(function (id,classname) {
var elem=document.getElementById(id);
if(!elem) {
return [false,"Coudln't even find an element with id: "+id];
}
var classlist=elem.className;
var classes=classlist.split(" ");
console.warn("CLASSES ARE: "+classes.join(" ANNNNND "));
for(var i=0;i<classes.length;i++) {
console.warn("Checking to see if "+classes[i]+" is equal to "+classname);
if(classes[i]==classname) {
return [true,null];
}
}
return [false,"Couldn't find "+classname+" in classes: "+classlist];
},function (err,res) {
if(!err && res && res[0]) {
callback();
} else {
if(res && res[1]) {
callback.fail(new Error(res[1]));
} else {
callback.fail(new Error("Unknown Error: "+err+" (results are: "+res+")"));
}
}
},id,classname);
/* var query_results=this.browser.queryAll(selector);
if(query_results.length==1) {
var classes=query_results[0].className.split(" ");
if(classes.indexOf(classname)!=-1) {
callback()
} else {
callback.fail(new Error("ClassName '"+classname+"' wasn't found in: '"+classes+"'"));
//console.warn("IS THE CLASS NAME THIS: "+query_results[0].className);
//console.warn("query_results: "+query_results[0]);
//console.warn("Q_R[0]: "+JSON.stringify(query_results[0].attributes));
//callback();
}
} else {
callback.fail(new Error("Found "+query_results.length+" tags with an id of "+id));
} */
});
this.Then(/^I wait for the browser to settle$/, function(callback) {
//this.browser.wait(callback);
//this doesn't work?
this.browser.on("done",function () {
callback();
});
});
this.Then(/^I wait (\d+) seconds$/, function (secs,callback) {
setTimeout(callback,secs*1000);
});
};
module.exports = myStepDefinitionsWrapper;
// features/support/world.js
var phantom = require('node-phantom');
var World = function World(callback) {
var that=this;
phantom.create(function(err,ph) {
//console.log("ERROR IS: "+err);
that.phantom=ph;
ph.createPage(function (err,page) {
// that.page_events = registerCallbacks(page);
page.onConsoleMessage=function (stuff) {
console.warn(stuff);
};
page.onError=function(stuff) {
console.warn("JAVASCRIPT ERROR IN CLIENT: '"+stuff+"'");
}
that.phantom_page=page;
callback();
})
})
};
exports.World = World;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment