mirror of
https://github.com/ariya/phantomjs.git
synced 2024-09-17 15:47:09 +03:00
Importing GhostDriver version 1.0.1
.
Changes are documented here: https://github.com/detro/ghostdriver/issues?labels=1.0.1&state=closed. https://github.com/detro/ghostdriver/issues/130
This commit is contained in:
parent
f5652e5110
commit
027aa93b18
@ -1,10 +1,7 @@
|
||||
2012-11-25 20:54:35
|
||||
2012-12-15 18:59:39
|
||||
|
||||
commit 54876580d0a3886e42850804b03184adbd899d65 (HEAD, tag: refs/tags/1.0.0, refs/remotes/origin/master, refs/remotes/origin/HEAD, refs/heads/master)
|
||||
commit 2676fd4e6410202ec439a235316451ea2c633681 (HEAD, tag: refs/tags/1.0.1, refs/heads/master)
|
||||
Author: Ivan De Marino <ivan.de.marino@gmail.com>
|
||||
Date: Sun Nov 25 19:05:15 2012 +0000
|
||||
Date: Sat Dec 15 18:58:34 2012 +0000
|
||||
|
||||
Updated export script.
|
||||
|
||||
1. Creates the `README.md` to inform PhantomJS developers that the code is automatically exported from GhostDriver
|
||||
2. Adds `--decorate=full` to the line where we populate the `lastupdate` file
|
||||
Preparing GhostDriver version `1.0.1`.
|
||||
|
@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
var ghostdriver = {
|
||||
system : require('system'),
|
||||
hub : require('./hub_register'),
|
||||
version : "1.0.0"
|
||||
version : "1.0.1"
|
||||
},
|
||||
server = require('webserver').create(),
|
||||
router,
|
||||
|
@ -345,7 +345,7 @@ ghostdriver.SessionReqHand = function(session) {
|
||||
var postObj = JSON.parse(req.post),
|
||||
result,
|
||||
timer,
|
||||
scriptTimeout = _session.getTimeout(_session.timeoutNames().SCRIPT),
|
||||
scriptTimeout = _session.getScriptTimeout(),
|
||||
timedOut = false;
|
||||
|
||||
if (typeof(postObj) === "object" && postObj.script && postObj.args) {
|
||||
@ -355,7 +355,7 @@ ghostdriver.SessionReqHand = function(session) {
|
||||
timedOut = true;
|
||||
_errors.handleFailedCommandEH(
|
||||
_errors.FAILED_CMD_STATUS.TIMEOUT,
|
||||
"Script didn't return within "+scriptTimeout+"ms",
|
||||
"Script didn't return within " + scriptTimeout + "ms",
|
||||
req,
|
||||
res,
|
||||
_session,
|
||||
@ -399,14 +399,21 @@ ghostdriver.SessionReqHand = function(session) {
|
||||
"}",
|
||||
postObj.script,
|
||||
postObj.args,
|
||||
_session.getTimeout(_session.timeoutNames().ASYNC_SCRIPT));
|
||||
_session.getAsyncScriptTimeout());
|
||||
} else {
|
||||
throw _errors.createInvalidReqMissingCommandParameterEH(req);
|
||||
}
|
||||
},
|
||||
|
||||
_getWindowHandle = function (req, res) {
|
||||
var handle = _session.getCurrentWindowHandle();
|
||||
var handle;
|
||||
|
||||
// Initialize the Current Window (we need at least that)
|
||||
_session.initCurrentWindowIfNull();
|
||||
|
||||
// Get current window handle
|
||||
handle = _session.getCurrentWindowHandle();
|
||||
|
||||
if (handle !== null) {
|
||||
res.success(_session.getId(), handle);
|
||||
} else {
|
||||
@ -420,6 +427,8 @@ ghostdriver.SessionReqHand = function(session) {
|
||||
},
|
||||
|
||||
_getWindowHandles = function(req, res) {
|
||||
// Initialize the Current Window (we need at least that)
|
||||
_session.initCurrentWindowIfNull();
|
||||
res.success(_session.getId(), _session.getWindowHandles());
|
||||
},
|
||||
|
||||
@ -460,9 +469,7 @@ ghostdriver.SessionReqHand = function(session) {
|
||||
// Request timed out
|
||||
_errors.handleFailedCommandEH(
|
||||
_errors.FAILED_CMD_STATUS.TIMEOUT,
|
||||
"URL '" + postObj.url + "' didn't load within " +
|
||||
_session.getTimeout(_session.timeoutNames().PAGE_LOAD) +
|
||||
"ms",
|
||||
"URL '" + postObj.url + "' didn't load within " + _session.getPageLoadTimeout() + "ms",
|
||||
req,
|
||||
res,
|
||||
_session,
|
||||
@ -478,13 +485,28 @@ ghostdriver.SessionReqHand = function(session) {
|
||||
|
||||
// Normalize the call: the "type" is read from the URL, not a POST parameter
|
||||
if (req.urlParsed.file === _const.IMPLICIT_WAIT) {
|
||||
postObj["type"] = _session.timeoutNames().IMPLICIT;
|
||||
postObj["type"] = _session.timeoutNames.IMPLICIT;
|
||||
} else if (req.urlParsed.file === _const.ASYNC_SCRIPT) {
|
||||
postObj["type"] = _session.timeoutNames().ASYNC_SCRIPT;
|
||||
postObj["type"] = _session.timeoutNames.ASYNC_SCRIPT;
|
||||
}
|
||||
|
||||
if (typeof(postObj["type"]) !== "undefined" && typeof(postObj["ms"]) !== "undefined") {
|
||||
_session.setTimeout(postObj["type"], postObj["ms"]);
|
||||
// Set the right timeout on the Session
|
||||
switch(postObj["type"]) {
|
||||
case _session.timeoutNames.SCRIPT:
|
||||
_session.setScriptTimeout(postObj["ms"]);
|
||||
break;
|
||||
case _session.timeoutNames.ASYNC_SCRIPT:
|
||||
_session.setAsyncScriptTimeout(postObj["ms"]);
|
||||
break;
|
||||
case _session.timeoutNames.IMPLICIT:
|
||||
_session.setImplicitTimeout(postObj["ms"]);
|
||||
break;
|
||||
case _session.timeoutNames.PAGE_LOAD:
|
||||
_session.setPageLoadTimeout(postObj["ms"]);
|
||||
break;
|
||||
}
|
||||
|
||||
res.success(_session.getId());
|
||||
} else {
|
||||
throw _errors.createInvalidReqMissingCommandParameterEH(req);
|
||||
|
@ -34,10 +34,10 @@ ghostdriver.ShutdownReqHand = function() {
|
||||
_protoParent = ghostdriver.ShutdownReqHand.prototype,
|
||||
|
||||
_handle = function(req, res) {
|
||||
_protoParent.handle.call(this, req, res);
|
||||
_protoParent.handle.call(this, req, res);
|
||||
|
||||
if (req.method === "GET" && req.urlParsed.file === "shutdown") {
|
||||
//res.success(null, null);
|
||||
// Any HTTP Request Method will be accepted for this command. Some drivers like HEAD for example...
|
||||
if (req.urlParsed.file === "shutdown") {
|
||||
res.statusCode = 200;
|
||||
res.setHeader("Content-Type", "text/html;charset=UTF-8");
|
||||
res.setHeader("Content-Length", 36);
|
||||
|
@ -348,7 +348,8 @@ ghostdriver.WebElementReqHand = function(idOrElement, session) {
|
||||
require("./webdriver_atoms.js").get("execute_script"),
|
||||
"return arguments[0].isSameNode(arguments[1]);",
|
||||
[_getJSON(), _getJSON(req.urlParsed.file)]);
|
||||
res.success(_session.getId(), result);
|
||||
|
||||
res.respondBasedOnResult(_session, req, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -378,7 +379,7 @@ ghostdriver.WebElementReqHand = function(idOrElement, session) {
|
||||
} else {
|
||||
_errors.handleFailedCommandEH(
|
||||
_errors.FAILED_CMD_STATUS.UNKNOWN_ERROR,
|
||||
"Submit succeded but Load Failed",
|
||||
"Submit succeeded but Load Failed",
|
||||
req,
|
||||
res,
|
||||
_session,
|
||||
@ -401,12 +402,72 @@ ghostdriver.WebElementReqHand = function(idOrElement, session) {
|
||||
});
|
||||
},
|
||||
|
||||
_postClickCommand = function(req, res) {
|
||||
var result = _protoParent.getSessionCurrWindow.call(this, _session, req).evaluate(
|
||||
require("./webdriver_atoms.js").get("click"),
|
||||
_getJSON());
|
||||
_canCausePageLoadOnClick = function(currWindow) {
|
||||
var tagName = _getTagName(currWindow).toLowerCase(),
|
||||
href = _getAttribute(currWindow, "href"),
|
||||
type = _getAttribute(currWindow, "type").toLowerCase();
|
||||
|
||||
res.respondBasedOnResult(_session, req, result);
|
||||
// Return "true" if it's an element that "can cause a page load if clicked"
|
||||
if (tagName === "a" && !!href && href.length > 0) {
|
||||
return true;
|
||||
}
|
||||
if (tagName === "input" && type === "submit") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
_postClickCommand = function(req, res) {
|
||||
var currWindow = _protoParent.getSessionCurrWindow.call(this, _session, req),
|
||||
clickRes,
|
||||
abortCallback = false;
|
||||
|
||||
if (_canCausePageLoadOnClick(currWindow)) {
|
||||
// Clicking on Current Element can cause a page load, hence we need to wait for it to happen
|
||||
currWindow.execFuncAndWaitForLoad(function() {
|
||||
// do the click
|
||||
clickRes = currWindow.evaluate(require("./webdriver_atoms.js").get("click"), _getJSON());
|
||||
|
||||
// If Click was NOT positive, status will be set to something else than '0'
|
||||
clickRes = JSON.parse(clickRes);
|
||||
if (clickRes && clickRes.status !== 0) {
|
||||
abortCallback = true; //< handling the error here
|
||||
res.respondBasedOnResult(_session, req, clickRes);
|
||||
}
|
||||
}, function(status) { //< onLoadFinished
|
||||
// Report about the Load, only if it was not already handled
|
||||
if (!abortCallback) {
|
||||
if (status === "success") {
|
||||
res.success(_session.getId());
|
||||
} else {
|
||||
_errors.handleFailedCommandEH(
|
||||
_errors.FAILED_CMD_STATUS.UNKNOWN_ERROR,
|
||||
"Click succeeded but Load Failed",
|
||||
req,
|
||||
res,
|
||||
_session,
|
||||
"WebElementReqHand");
|
||||
}
|
||||
}
|
||||
}, function() {
|
||||
if (arguments.length === 0) { //< onTimeout
|
||||
// onclick didn't bubble up, but we should still return success
|
||||
res.success(_session.getId());
|
||||
} else { //< onError
|
||||
_errors.handleFailedCommandEH(
|
||||
_errors.FAILED_CMD_STATUS.UNKNOWN_ERROR,
|
||||
"Click failed: " + arguments[0],
|
||||
req,
|
||||
res,
|
||||
_session,
|
||||
"WebElementReqHand");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// By default, clicking on this element can't cause a Page Load: we are done after having clicked
|
||||
clickRes = currWindow.evaluate(require("./webdriver_atoms.js").get("click"), _getJSON());
|
||||
res.respondBasedOnResult(_session, req, clickRes);
|
||||
}
|
||||
},
|
||||
|
||||
_getSelectedCommand = function(req, res) {
|
||||
|
@ -76,11 +76,15 @@ ghostdriver.Session = function(desiredCapabilities) {
|
||||
_defaultCapabilities.proxy :
|
||||
desiredCapabilities.proxy
|
||||
},
|
||||
// NOTE: This value is needed for Timeouts Upper-bound limit.
|
||||
// "setTimeout/setInterval" accept only 32 bit integers, even though Number are all Doubles (go figure!)
|
||||
// Interesting details here: {@link http://stackoverflow.com/a/4995054}.
|
||||
_max32bitInt = Math.pow(2, 31) -1, //< Max 32bit Int
|
||||
_timeouts = {
|
||||
"script" : 500, //< 0.5s
|
||||
"async script" : 5000, //< 5s
|
||||
"script" : _max32bitInt,
|
||||
"async script" : _max32bitInt,
|
||||
"implicit" : 0, //< 0s
|
||||
"page load" : 10000 //< 10s
|
||||
"page load" : _max32bitInt,
|
||||
},
|
||||
_const = {
|
||||
TIMEOUT_NAMES : {
|
||||
@ -95,7 +99,23 @@ ghostdriver.Session = function(desiredCapabilities) {
|
||||
_currentWindowHandle = null,
|
||||
_id = require("./third_party/uuid.js").v1(),
|
||||
_inputs = ghostdriver.Inputs(),
|
||||
_capsPageSettingsPref = "phantomjs.page.settings.",
|
||||
_pageSettings = {},
|
||||
k, settingKey;
|
||||
|
||||
// Searching for `phantomjs.settings.*` in the Desired Capabilities and merging with the Negotiated Capabilities
|
||||
// Possible values: @see https://github.com/ariya/phantomjs/wiki/API-Reference#wiki-webpage-settings.
|
||||
for (k in desiredCapabilities) {
|
||||
if (k.indexOf(_capsPageSettingsPref) === 0) {
|
||||
settingKey = k.substring(_capsPageSettingsPref.length);
|
||||
if (settingKey.length > 0) {
|
||||
_negotiatedCapabilities[k] = desiredCapabilities[k];
|
||||
_pageSettings[settingKey] = desiredCapabilities[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var
|
||||
/**
|
||||
* Executes a function and waits for Load to happen.
|
||||
*
|
||||
@ -110,6 +130,7 @@ ghostdriver.Session = function(desiredCapabilities) {
|
||||
var args = Array.prototype.splice.call(arguments, 0),
|
||||
timer,
|
||||
loadingNewPage = false,
|
||||
pageLoadNotTriggered = true,
|
||||
thisPage = this;
|
||||
|
||||
// Normalize "execTypeOpt" value
|
||||
@ -139,10 +160,12 @@ ghostdriver.Session = function(desiredCapabilities) {
|
||||
// callback.
|
||||
this.setOneShotCallback("onLoadStarted", function () {
|
||||
// console.log("onLoadStarted");
|
||||
pageLoadNotTriggered = false;
|
||||
loadingNewPage = true;
|
||||
});
|
||||
this.setOneShotCallback("onUrlChanged", function () {
|
||||
// console.log("onUrlChanged");
|
||||
pageLoadNotTriggered = false;
|
||||
|
||||
// If "not loading a new page" it's just a fragment change
|
||||
// and we should call "onLoadFunc()"
|
||||
@ -168,6 +191,7 @@ ghostdriver.Session = function(desiredCapabilities) {
|
||||
// message += " in " + item["function"];
|
||||
// console.log(" " + message);
|
||||
// });
|
||||
pageLoadNotTriggered = false;
|
||||
|
||||
thisPage.stop(); //< stop the page from loading
|
||||
clearTimeout(timer);
|
||||
@ -177,12 +201,13 @@ ghostdriver.Session = function(desiredCapabilities) {
|
||||
});
|
||||
|
||||
// Starting timer
|
||||
// console.log("Setting timer to: " + _getPageLoadTimeout());
|
||||
timer = setTimeout(function() {
|
||||
thisPage.stop(); //< stop the page from loading
|
||||
thisPage.resetOneShotCallbacks();
|
||||
|
||||
onErrorFunc.apply(thisPage, arguments);
|
||||
}, _getTimeout(_const.TIMEOUT_NAMES.PAGE_LOAD));
|
||||
}, _getPageLoadTimeout());
|
||||
|
||||
// We are ready to execute
|
||||
if (execTypeOpt === "eval") {
|
||||
@ -192,6 +217,15 @@ ghostdriver.Session = function(desiredCapabilities) {
|
||||
// "Apply" the provided function
|
||||
func.apply(this, args);
|
||||
}
|
||||
|
||||
// In case a Page Load is not triggered at all (within 0.5s), we assume it's done and move on
|
||||
setTimeout(function() {
|
||||
if (pageLoadNotTriggered) {
|
||||
clearTimeout(timer);
|
||||
thisPage.resetOneShotCallbacks();
|
||||
onLoadFunc.call(thisPage, "success");
|
||||
}
|
||||
}, 500);
|
||||
},
|
||||
|
||||
_oneShotCallbackFactory = function(page, callbackName) {
|
||||
@ -239,6 +273,8 @@ ghostdriver.Session = function(desiredCapabilities) {
|
||||
},
|
||||
|
||||
_decorateNewWindow = function(page) {
|
||||
var k;
|
||||
|
||||
// Decorating:
|
||||
// 0. Pages lifetime will be managed by Driver, not the pages
|
||||
page.ownsPages = false;
|
||||
@ -258,8 +294,16 @@ ghostdriver.Session = function(desiredCapabilities) {
|
||||
page.onPageCreated = _addNewPage;
|
||||
// 5. Remove every closing page
|
||||
page.onClosing = _deleteClosingPage;
|
||||
// 6. Applying Page settings received via capabilities
|
||||
for (k in _pageSettings) {
|
||||
// Apply setting only if really supported by PhantomJS
|
||||
if (p.settings.hasOwnProperty(k)) {
|
||||
page.settings[k] = _pageSettings[k];
|
||||
}
|
||||
}
|
||||
|
||||
// page.onConsoleMessage = function(msg) { console.log(msg); };
|
||||
// console.log("New Window/Page settings: " + JSON.stringify(page.settings, null, " "));
|
||||
|
||||
return page;
|
||||
},
|
||||
@ -284,14 +328,21 @@ ghostdriver.Session = function(desiredCapabilities) {
|
||||
return page;
|
||||
},
|
||||
|
||||
_getCurrentWindow = function() {
|
||||
var page = null;
|
||||
_initCurrentWindowIfNull = function() {
|
||||
// Ensure a Current Window is available, if it's found to be `null`
|
||||
if (_currentWindowHandle === null) {
|
||||
// First call to get the current window: need to create one
|
||||
page = _decorateNewWindow(require("webpage").create());
|
||||
_currentWindowHandle = page.windowHandle;
|
||||
_windows[_currentWindowHandle] = page;
|
||||
} else if (_windows.hasOwnProperty(_currentWindowHandle)) {
|
||||
}
|
||||
},
|
||||
|
||||
_getCurrentWindow = function() {
|
||||
var page = null;
|
||||
|
||||
_initCurrentWindowIfNull();
|
||||
if (_windows.hasOwnProperty(_currentWindowHandle)) {
|
||||
page = _windows[_currentWindowHandle];
|
||||
}
|
||||
|
||||
@ -306,6 +357,8 @@ ghostdriver.Session = function(desiredCapabilities) {
|
||||
if (page !== null) {
|
||||
// Switch current window and return "true"
|
||||
_currentWindowHandle = page.windowHandle;
|
||||
// Switch to the Main Frame of that window
|
||||
page.switchToMainFrame();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -353,15 +406,48 @@ ghostdriver.Session = function(desiredCapabilities) {
|
||||
},
|
||||
|
||||
_setTimeout = function(type, ms) {
|
||||
_timeouts[type] = ms;
|
||||
// In case the chosen timeout is less than 0, we reset it to `_max32bitInt`
|
||||
if (ms < 0) {
|
||||
_timeouts[type] = _max32bitInt;
|
||||
} else {
|
||||
_timeouts[type] = ms;
|
||||
}
|
||||
},
|
||||
|
||||
_getTimeout = function(type) {
|
||||
return _timeouts[type];
|
||||
},
|
||||
|
||||
_timeoutNames = function() {
|
||||
return _const.TIMEOUT_NAMES;
|
||||
_getScriptTimeout = function() {
|
||||
return _getTimeout(_const.TIMEOUT_NAMES.SCRIPT);
|
||||
},
|
||||
|
||||
_getAsyncScriptTimeout = function() {
|
||||
return _getTimeout(_const.TIMEOUT_NAMES.ASYNC_SCRIPT);
|
||||
},
|
||||
|
||||
_getImplicitTimeout = function() {
|
||||
return _getTimeout(_const.TIMEOUT_NAMES.IMPLICIT);
|
||||
},
|
||||
|
||||
_getPageLoadTimeout = function() {
|
||||
return _getTimeout(_const.TIMEOUT_NAMES.PAGE_LOAD);
|
||||
},
|
||||
|
||||
_setScriptTimeout = function(ms) {
|
||||
_setTimeout(_const.TIMEOUT_NAMES.SCRIPT, ms);
|
||||
},
|
||||
|
||||
_setAsyncScriptTimeout = function(ms) {
|
||||
_setTimeout(_const.TIMEOUT_NAMES.ASYNC_SCRIPT, ms);
|
||||
},
|
||||
|
||||
_setImplicitTimeout = function(ms) {
|
||||
_setTimeout(_const.TIMEOUT_NAMES.IMPLICIT, ms);
|
||||
},
|
||||
|
||||
_setPageLoadTimeout = function(ms) {
|
||||
_setTimeout(_const.TIMEOUT_NAMES.PAGE_LOAD, ms);
|
||||
},
|
||||
|
||||
_aboutToDelete = function() {
|
||||
@ -389,14 +475,21 @@ ghostdriver.Session = function(desiredCapabilities) {
|
||||
getWindow : _getWindow,
|
||||
closeWindow : _closeWindow,
|
||||
getWindowsCount : _getWindowsCount,
|
||||
initCurrentWindowIfNull : _initCurrentWindowIfNull,
|
||||
getCurrentWindowHandle : _getCurrentWindowHandle,
|
||||
getWindowHandles: _getWindowHandles,
|
||||
isValidWindowHandle: _isValidWindowHandle,
|
||||
getWindowHandles : _getWindowHandles,
|
||||
isValidWindowHandle : _isValidWindowHandle,
|
||||
aboutToDelete : _aboutToDelete,
|
||||
setTimeout : _setTimeout,
|
||||
getTimeout : _getTimeout,
|
||||
timeoutNames : _timeoutNames,
|
||||
inputs: _inputs
|
||||
inputs : _inputs,
|
||||
setScriptTimeout : _setScriptTimeout,
|
||||
setAsyncScriptTimeout : _setAsyncScriptTimeout,
|
||||
setImplicitTimeout : _setImplicitTimeout,
|
||||
setPageLoadTimeout : _setPageLoadTimeout,
|
||||
getScriptTimeout : _getScriptTimeout,
|
||||
getAsyncScriptTimeout : _getAsyncScriptTimeout,
|
||||
getImplicitTimeout : _getImplicitTimeout,
|
||||
getPageLoadTimeout : _getPageLoadTimeout,
|
||||
timeoutNames : _const.TIMEOUT_NAMES
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -207,7 +207,7 @@ ghostdriver.WebElementLocator = function(session) {
|
||||
elementOrElements.hasOwnProperty("value")) {
|
||||
|
||||
// return if elements found OR we passed the "stopSearchByTime"
|
||||
stopSearchByTime = searchStartTime + _session.getTimeout(_session.timeoutNames().IMPLICIT);
|
||||
stopSearchByTime = searchStartTime + _session.getImplicitTimeout();
|
||||
if (elementOrElements.value.length !== 0 || new Date().getTime() > stopSearchByTime) {
|
||||
res.success(_session.getId(), elementOrElements.value);
|
||||
return;
|
||||
@ -215,7 +215,7 @@ ghostdriver.WebElementLocator = function(session) {
|
||||
}
|
||||
|
||||
// retry if we haven't passed "stopSearchByTime"
|
||||
stopSearchByTime = searchStartTime + _session.getTimeout(_session.timeoutNames().IMPLICIT);
|
||||
stopSearchByTime = searchStartTime + _session.getImplicitTimeout();
|
||||
if (stopSearchByTime >= new Date().getTime()) {
|
||||
// Recursive call in 50ms
|
||||
setTimeout(function(){
|
||||
|
Loading…
Reference in New Issue
Block a user