aboutsummaryrefslogtreecommitdiff
path: root/node_modules/selenium-webdriver/phantomjs.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/selenium-webdriver/phantomjs.js')
-rw-r--r--node_modules/selenium-webdriver/phantomjs.js289
1 files changed, 289 insertions, 0 deletions
diff --git a/node_modules/selenium-webdriver/phantomjs.js b/node_modules/selenium-webdriver/phantomjs.js
new file mode 100644
index 000000000..2de5364de
--- /dev/null
+++ b/node_modules/selenium-webdriver/phantomjs.js
@@ -0,0 +1,289 @@
+// Licensed to the Software Freedom Conservancy (SFC) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The SFC licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+/**
+ * @fileoverview Defines a {@linkplain Driver WebDriver} client for the
+ * PhantomJS web browser. By default, it is expected that the PhantomJS
+ * executable can be located on your
+ * [PATH](https://en.wikipedia.org/wiki/PATH_(variable))
+ *
+ * __Using a Custom PhantomJS Binary__
+ *
+ * If you have PhantomJS.exe placed somewhere other than the root of your
+ * working directory, you can build a custom Capability and attach the
+ * executable's location to the Capability
+ *
+ * For example, if you're using the
+ * [phantomjs-prebuilt](https://www.npmjs.com/package/phantomjs-prebuilt) module
+ * from npm:
+ *
+ * //setup custom phantomJS capability
+ * var phantomjs_exe = require('phantomjs-prebuilt').path;
+ * var customPhantom = selenium.Capabilities.phantomjs();
+ * customPhantom.set("phantomjs.binary.path", phantomjs_exe);
+ * //build custom phantomJS driver
+ * var driver = new selenium.Builder().
+ * withCapabilities(customPhantom).
+ * build();
+ *
+ */
+
+'use strict';
+
+const fs = require('fs');
+
+const http = require('./http'),
+ io = require('./io'),
+ capabilities = require('./lib/capabilities'),
+ command = require('./lib/command'),
+ logging = require('./lib/logging'),
+ promise = require('./lib/promise'),
+ webdriver = require('./lib/webdriver'),
+ portprober = require('./net/portprober'),
+ remote = require('./remote');
+
+
+/**
+ * Name of the PhantomJS executable.
+ * @type {string}
+ * @const
+ */
+const PHANTOMJS_EXE =
+ process.platform === 'win32' ? 'phantomjs.exe' : 'phantomjs';
+
+
+/**
+ * Capability that designates the location of the PhantomJS executable to use.
+ * @type {string}
+ * @const
+ */
+const BINARY_PATH_CAPABILITY = 'phantomjs.binary.path';
+
+
+/**
+ * Capability that designates the CLI arguments to pass to PhantomJS.
+ * @type {string}
+ * @const
+ */
+const CLI_ARGS_CAPABILITY = 'phantomjs.cli.args';
+
+
+/**
+ * Custom command names supported by PhantomJS.
+ * @enum {string}
+ */
+const Command = {
+ EXECUTE_PHANTOM_SCRIPT: 'executePhantomScript'
+};
+
+
+/**
+ * Finds the PhantomJS executable.
+ * @param {string=} opt_exe Path to the executable to use.
+ * @return {string} The located executable.
+ * @throws {Error} If the executable cannot be found on the PATH, or if the
+ * provided executable path does not exist.
+ */
+function findExecutable(opt_exe) {
+ var exe = opt_exe || io.findInPath(PHANTOMJS_EXE, true);
+ if (!exe) {
+ throw Error(
+ 'The PhantomJS executable could not be found on the current PATH. ' +
+ 'Please download the latest version from ' +
+ 'http://phantomjs.org/download.html and ensure it can be found on ' +
+ 'your PATH. For more information, see ' +
+ 'https://github.com/ariya/phantomjs/wiki');
+ }
+ if (!fs.existsSync(exe)) {
+ throw Error('File does not exist: ' + exe);
+ }
+ return exe;
+}
+
+
+/**
+ * Maps WebDriver logging level name to those recognised by PhantomJS.
+ * @const {!Map<string, string>}
+ */
+const WEBDRIVER_TO_PHANTOMJS_LEVEL = new Map([
+ [logging.Level.ALL.name, 'DEBUG'],
+ [logging.Level.DEBUG.name, 'DEBUG'],
+ [logging.Level.INFO.name, 'INFO'],
+ [logging.Level.WARNING.name, 'WARN'],
+ [logging.Level.SEVERE.name, 'ERROR']]);
+
+
+/**
+ * Creates a command executor with support for PhantomJS' custom commands.
+ * @param {!Promise<string>} url The server's URL.
+ * @return {!command.Executor} The new command executor.
+ */
+function createExecutor(url) {
+ let client = url.then(url => new http.HttpClient(url));
+ let executor = new http.Executor(client);
+
+ executor.defineCommand(
+ Command.EXECUTE_PHANTOM_SCRIPT,
+ 'POST', '/session/:sessionId/phantom/execute');
+
+ return executor;
+}
+
+/**
+ * Creates a new WebDriver client for PhantomJS.
+ */
+class Driver extends webdriver.WebDriver {
+ /**
+ * @param {capabilities.Capabilities=} opt_capabilities The desired
+ * capabilities.
+ * @param {promise.ControlFlow=} opt_flow The control flow to use,
+ * or {@code null} to use the currently active flow.
+ * @param {string=} opt_logFile Path to the log file for the phantomjs
+ * executable's output. For convenience, this may be set at runtime with
+ * the `SELENIUM_PHANTOMJS_LOG` environment variable.
+ */
+ constructor(opt_capabilities, opt_flow, opt_logFile) {
+ // TODO: add an Options class for consistency with the other driver types.
+
+ var caps = opt_capabilities || capabilities.Capabilities.phantomjs();
+ var exe = findExecutable(caps.get(BINARY_PATH_CAPABILITY));
+ var args = [];
+
+ var logPrefs = caps.get(capabilities.Capability.LOGGING_PREFS);
+ if (logPrefs instanceof logging.Preferences) {
+ logPrefs = logPrefs.toJSON();
+ }
+
+ if (logPrefs && logPrefs[logging.Type.DRIVER]) {
+ let level = WEBDRIVER_TO_PHANTOMJS_LEVEL.get(
+ logPrefs[logging.Type.DRIVER]);
+ if (level) {
+ args.push('--webdriver-loglevel=' + level);
+ }
+ }
+
+ opt_logFile = process.env['SELENIUM_PHANTOMJS_LOG'] || opt_logFile;
+ if (typeof opt_logFile === 'string') {
+ args.push('--webdriver-logfile=' + opt_logFile);
+ }
+
+ var proxy = caps.get(capabilities.Capability.PROXY);
+ if (proxy) {
+ switch (proxy.proxyType) {
+ case 'manual':
+ if (proxy.httpProxy) {
+ args.push(
+ '--proxy-type=http',
+ '--proxy=' + proxy.httpProxy);
+ console.log(args);
+ }
+ break;
+ case 'pac':
+ throw Error('PhantomJS does not support Proxy PAC files');
+ case 'system':
+ args.push('--proxy-type=system');
+ break;
+ case 'direct':
+ args.push('--proxy-type=none');
+ break;
+ }
+ }
+ args = args.concat(caps.get(CLI_ARGS_CAPABILITY) || []);
+
+ var port = portprober.findFreePort();
+ var service = new remote.DriverService(exe, {
+ port: port,
+ stdio: 'inherit',
+ args: Promise.resolve(port).then(function(port) {
+ args.push('--webdriver=' + port);
+ return args;
+ })
+ });
+
+ var executor = createExecutor(service.start());
+ var driver = webdriver.WebDriver.createSession(executor, caps, opt_flow);
+
+ super(driver.getSession(), executor, driver.controlFlow());
+
+ var boundQuit = this.quit.bind(this);
+
+ /** @override */
+ this.quit = function() {
+ let killService = () => service.kill();
+ return boundQuit().then(killService, killService);
+ };
+ }
+
+ /**
+ * This function is a no-op as file detectors are not supported by this
+ * implementation.
+ * @override
+ */
+ setFileDetector() {}
+
+ /**
+ * Executes a PhantomJS fragment. This method is similar to
+ * {@link #executeScript}, except it exposes the
+ * <a href="http://phantomjs.org/api/">PhantomJS API</a> to the injected
+ * script.
+ *
+ * <p>The injected script will execute in the context of PhantomJS's
+ * {@code page} variable. If a page has not been loaded before calling this
+ * method, one will be created.</p>
+ *
+ * <p>Be sure to wrap callback definitions in a try/catch block, as failures
+ * may cause future WebDriver calls to fail.</p>
+ *
+ * <p>Certain callbacks are used by GhostDriver (the PhantomJS WebDriver
+ * implementation) and overriding these may cause the script to fail. It is
+ * recommended that you check for existing callbacks before defining your own.
+ * </p>
+ *
+ * As with {@link #executeScript}, the injected script may be defined as
+ * a string for an anonymous function body (e.g. "return 123;"), or as a
+ * function. If a function is provided, it will be decompiled to its original
+ * source. Note that injecting functions is provided as a convenience to
+ * simplify defining complex scripts. Care must be taken that the function
+ * only references variables that will be defined in the page's scope and
+ * that the function does not override {@code Function.prototype.toString}
+ * (overriding toString() will interfere with how the function is
+ * decompiled.
+ *
+ * @param {(string|!Function)} script The script to execute.
+ * @param {...*} var_args The arguments to pass to the script.
+ * @return {!promise.Promise<T>} A promise that resolve to the
+ * script's return value.
+ * @template T
+ */
+ executePhantomJS(script, var_args) {
+ if (typeof script === 'function') {
+ script = 'return (' + script + ').apply(this, arguments);';
+ }
+ var args = arguments.length > 1
+ ? Array.prototype.slice.call(arguments, 1) : [];
+ return this.schedule(
+ new command.Command(Command.EXECUTE_PHANTOM_SCRIPT)
+ .setParameter('script', script)
+ .setParameter('args', args),
+ 'Driver.executePhantomJS()');
+ }
+}
+
+
+// PUBLIC API
+
+exports.Driver = Driver;