diff --git a/bridge.js b/bridge.js index 3af46e2..7b7e9b9 100644 --- a/bridge.js +++ b/bridge.js @@ -66,6 +66,33 @@ function page_open(res, page, args) { })); } +function page_get_page(res, page, args) { + var new_page; + var error; + var id = null; + + try { + new_page = page.getPage.apply(page, args); + } catch (err) { + error = err; + } + + if (new_page) { + id = setup_page(new_page); + } + + res.setHeader('Content-Type', 'application/json'); + if (error) { + res.statusCode = 500; + res.write(JSON.stringify(error)); + } else { + res.statusCode = 200; + res.write(JSON.stringify({ data: id })); + } + + res.close(); +} + function include_js(res, page, args) { res.statusCode = 200; res.setHeader('Content-Type', 'application/json'); @@ -110,6 +137,9 @@ webserver.listen('127.0.0.1:0', function (req, res) { } else if (request.method === 'includeJs') { include_js(res, pages[request.page], request.args); return; + } else if (request.method === 'getPage') { // special case due to retrieving page + page_get_page(res, pages[request.page], request.args); + return; } try { output = pages[request.page][request.method].apply(pages[request.page], request.args); diff --git a/node-phantom-simple.js b/node-phantom-simple.js index ecaf33f..ed7271d 100644 --- a/node-phantom-simple.js +++ b/node-phantom-simple.js @@ -288,7 +288,7 @@ exports.create = function (options, callback) { var methods = [ 'addCookie', 'childFramesCount', 'childFramesName', 'clearCookies', 'close', 'currentFrameName', 'deleteCookie', 'evaluateJavaScript', - 'evaluateAsync', 'getPage', 'go', 'goBack', 'goForward', 'includeJs', + 'evaluateAsync', 'go', 'goBack', 'goForward', 'includeJs', 'injectJs', 'open', 'openUrl', 'release', 'reload', 'render', 'renderBase64', 'sendEvent', 'setContent', 'stop', 'switchToFocusedFrame', 'switchToFrame', 'switchToFrame', 'switchToChildFrame', 'switchToChildFrame', 'switchToMainFrame', @@ -348,6 +348,33 @@ exports.create = function (options, callback) { request_queue.push([ [ id, 'evaluate', fn.toString() ].concat(extra_args), callbackOrDummy(cb, poll_func) ]); }, + getPage: function (name, cb) { + if (typeof cb !== 'function') { + cb = function () {}; + } + + // Create a wrapper function that setups + // new page if phantom finds a page, + // otherwise send null + var wrapperFn = function (err, page_id) { + if (err) { + cb(err, null); + return; + } + + if (!page_id && page_id !== 0) { + cb(null, null); + return; + } + + var new_page = setup_new_page(page_id); + + cb(null, new_page); + }; + + request_queue.push([ [ id, 'getPage', name ], callbackOrDummy(wrapperFn, poll_func) ]); + }, + waitForSelector: function (selector, timeout, cb) { if (cb && Object.prototype.toString.call(timeout) === '[object Function]') { pageWaitForSelectorDeprecatedFn(); diff --git a/test/test_page_get_page.js b/test/test_page_get_page.js new file mode 100644 index 0000000..e48cffb --- /dev/null +++ b/test/test_page_get_page.js @@ -0,0 +1,97 @@ +'use strict'; + + +var assert = require('assert'); +var driver = require('../'); + +describe('page.getPage()', function () { + + it('should retrieve pages as actual node-phantom-simple pages (#131)', function (done) { + var path = require(process.env.ENGINE || 'phantomjs').path; + driver.create({ path: path }, function (err, browser) { + if (err) { + done(err); + return; + } + + browser.createPage(function (err, page) { + if (err) { + done(err); + return; + } + + var child_page_name = 'child_page'; + // this should be called when + // window.open is executed + page.onPageCreated = function (childPage) { + // Set the name of the child so it can be retrieved + childPage.evaluate(function (name_to_use) { + window.name = name_to_use; + window.special_recognisable_property = 5; + }, child_page_name, function () { + // Retrieve the previous childPage, now through getPage + page.getPage(child_page_name, function (err, new_child_page) { + if (err) { + done(err); + return; + } + + assert.strictEqual(typeof new_child_page, 'object'); + assert.strictEqual(typeof new_child_page.evaluate, 'function'); + new_child_page.evaluate(function () { + // tried using window.name, but slimerjs returns empty string, + // but still matches the correct page + return window.special_recognisable_property; + }, function (err, special_prop) { + if (err) { + done(err); + return; + } + + assert.strictEqual(special_prop, 5); + browser.exit(done); + }); + }); + }); + }; + + // open an empty new page + page.evaluate(function () { + window.open(''); + }, function (err) { + if (err) { + done(err); + return; + } + }); + }); + }); + }); + + it('should return null when page with given name cannot be found', function (done) { + var path = require(process.env.ENGINE || 'phantomjs').path; + driver.create({ path: path }, function (err, browser) { + if (err) { + done(err); + return; + } + + browser.createPage(function (err, page) { + if (err) { + done(err); + return; + } + + page.getPage('some-name', function (err, child_page) { + if (err) { + done(err); + return; + } + + assert.strictEqual(child_page, null); + browser.exit(done); + }); + }); + }); + }); +});