Update to Drupal 8.0.0-rc3. For more information, see https://www.drupal.org/node/2608078
This commit is contained in:
parent
6419a031d7
commit
4afb23bbd3
762 changed files with 20080 additions and 6368 deletions
2
vendor/composer/autoload_psr4.php
vendored
2
vendor/composer/autoload_psr4.php
vendored
|
@ -6,6 +6,8 @@ $vendorDir = dirname(dirname(__FILE__));
|
|||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Zumba\\Mink\\Driver\\' => array($vendorDir . '/jcalderonzumba/mink-phantomjs-driver/src'),
|
||||
'Zumba\\GastonJS\\' => array($vendorDir . '/jcalderonzumba/gastonjs/src'),
|
||||
'Zend\\Stdlib\\' => array($vendorDir . '/zendframework/zend-stdlib/src'),
|
||||
'Zend\\Hydrator\\' => array($vendorDir . '/zendframework/zend-hydrator/src'),
|
||||
'Zend\\Feed\\' => array($vendorDir . '/zendframework/zend-feed/src'),
|
||||
|
|
124
vendor/composer/installed.json
vendored
124
vendor/composer/installed.json
vendored
|
@ -107,7 +107,7 @@
|
|||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/wikimedia/composer-merge-plugin/zipball/47bb3388cfeae41a38087ac8465a7d08fa92ea2e",
|
||||
"url": "https://api.github.com/repos/wikimedia/composer-merge-plugin/zipball/6196fdb001faf681f92db2ae10abafb5815affde",
|
||||
"reference": "47bb3388cfeae41a38087ac8465a7d08fa92ea2e",
|
||||
"shasum": ""
|
||||
},
|
||||
|
@ -3757,5 +3757,127 @@
|
|||
],
|
||||
"description": "Symfony EventDispatcher Component",
|
||||
"homepage": "https://symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "jcalderonzumba/gastonjs",
|
||||
"version": "dev-master",
|
||||
"version_normalized": "9999999-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jcalderonzumba/gastonjs.git",
|
||||
"reference": "5e231b4df98275c404e1371fc5fadd34f6a121ad"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/jcalderonzumba/gastonjs/zipball/5e231b4df98275c404e1371fc5fadd34f6a121ad",
|
||||
"reference": "5e231b4df98275c404e1371fc5fadd34f6a121ad",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"guzzlehttp/guzzle": "~5.0|~6.0",
|
||||
"php": ">=5.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.6",
|
||||
"silex/silex": "~1.2",
|
||||
"symfony/phpunit-bridge": "~2.7",
|
||||
"symfony/process": "~2.1"
|
||||
},
|
||||
"time": "2015-10-07 11:40:41",
|
||||
"type": "phantomjs-api",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.1.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "source",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Zumba\\GastonJS\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Juan Francisco Calderón Zumba",
|
||||
"email": "juanfcz@gmail.com",
|
||||
"homepage": "http://github.com/jcalderonzumba"
|
||||
}
|
||||
],
|
||||
"description": "PhantomJS API based server for webpage automation",
|
||||
"homepage": "https://github.com/jcalderonzumba/gastonjs",
|
||||
"keywords": [
|
||||
"api",
|
||||
"automation",
|
||||
"browser",
|
||||
"headless",
|
||||
"phantomjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "jcalderonzumba/mink-phantomjs-driver",
|
||||
"version": "dev-master",
|
||||
"version_normalized": "9999999-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jcalderonzumba/MinkPhantomJSDriver.git",
|
||||
"reference": "10d7c48c9a4129463052321b52450d98983c4332"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/jcalderonzumba/MinkPhantomJSDriver/zipball/10d7c48c9a4129463052321b52450d98983c4332",
|
||||
"reference": "10d7c48c9a4129463052321b52450d98983c4332",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"behat/mink": "~1.6",
|
||||
"jcalderonzumba/gastonjs": "~1.0",
|
||||
"php": ">=5.4",
|
||||
"twig/twig": "~1.8"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.6",
|
||||
"silex/silex": "~1.2",
|
||||
"symfony/css-selector": "~2.1",
|
||||
"symfony/phpunit-bridge": "~2.7",
|
||||
"symfony/process": "~2.3"
|
||||
},
|
||||
"time": "2015-10-05 18:24:44",
|
||||
"type": "mink-driver",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.4.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "source",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Zumba\\Mink\\Driver\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Juan Francisco Calderón Zumba",
|
||||
"email": "juanfcz@gmail.com",
|
||||
"homepage": "http://github.com/jcalderonzumba"
|
||||
}
|
||||
],
|
||||
"description": "PhantomJS driver for Mink framework",
|
||||
"homepage": "http://mink.behat.org/",
|
||||
"keywords": [
|
||||
"ajax",
|
||||
"browser",
|
||||
"headless",
|
||||
"javascript",
|
||||
"phantomjs",
|
||||
"testing"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
37
vendor/jcalderonzumba/gastonjs/.travis.yml
vendored
Normal file
37
vendor/jcalderonzumba/gastonjs/.travis.yml
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
language: php
|
||||
|
||||
php:
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- hhvm
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- php: 5.4
|
||||
env: COMPOSER_FLAGS='--prefer-lowest --prefer-stable' SYMFONY_DEPRECATIONS_HELPER=weak
|
||||
- php: 5.6
|
||||
env: DEPENDENCIES=dev
|
||||
allow_failures:
|
||||
- php: 7.0
|
||||
- php: hhvm
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache/files
|
||||
|
||||
before_install:
|
||||
- composer self-update
|
||||
- if [ "$DEPENDENCIES" = "dev" ]; then perl -pi -e 's/^}$/,"minimum-stability":"dev"}/' composer.json; fi;
|
||||
|
||||
install:
|
||||
- composer update $COMPOSER_FLAGS
|
||||
|
||||
script:
|
||||
- bin/run-tests.sh
|
||||
|
||||
after_script:
|
||||
- ps axo pid,command | grep phantomjs | grep -v grep | awk '{print $1}' | xargs -I {} kill {}
|
||||
- ps axo pid,command | grep php | grep -v grep | awk '{print $1}' | xargs -I {} kill {}
|
21
vendor/jcalderonzumba/gastonjs/LICENSE
vendored
Normal file
21
vendor/jcalderonzumba/gastonjs/LICENSE
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Juan Francisco Calderón Zumba
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
8
vendor/jcalderonzumba/gastonjs/README.md
vendored
Normal file
8
vendor/jcalderonzumba/gastonjs/README.md
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
GastonJS for Webpage automation
|
||||
================================
|
||||
[](https://travis-ci.org/jcalderonzumba/gastonjs)
|
||||
[](https://packagist.org/packages/jcalderonzumba/gastonjs)
|
||||
[](https://packagist.org/packages/jcalderonzumba/gastonjs)
|
||||
|
||||
|
||||
For full documentation go to [GastonJS doc](http://gastonjs.readthedocs.org/en/latest/)
|
26
vendor/jcalderonzumba/gastonjs/bin/run-tests.sh
vendored
Executable file
26
vendor/jcalderonzumba/gastonjs/bin/run-tests.sh
vendored
Executable file
|
@ -0,0 +1,26 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
start_browser_api(){
|
||||
CURRENT_DIR=$(pwd)
|
||||
LOCAL_PHANTOMJS="${CURRENT_DIR}/bin/phantomjs"
|
||||
if [ -f ${LOCAL_PHANTOMJS} ]; then
|
||||
${LOCAL_PHANTOMJS} --ssl-protocol=any --ignore-ssl-errors=true src/Client/main.js 8510 1024 768 2>&1 &
|
||||
else
|
||||
phantomjs --ssl-protocol=any --ignore-ssl-errors=true src/Client/main.js 8510 1024 768 2>&1 >> /dev/null &
|
||||
fi
|
||||
sleep 2
|
||||
}
|
||||
|
||||
stop_services(){
|
||||
ps axo pid,command | grep phantomjs | grep -v grep | awk '{print $1}' | xargs -I {} kill {}
|
||||
ps axo pid,command | grep php | grep -v grep | grep -v phpstorm | awk '{print $1}' | xargs -I {} kill {}
|
||||
sleep 2
|
||||
}
|
||||
|
||||
mkdir -p /tmp/jcalderonzumba/phantomjs
|
||||
stop_services
|
||||
start_browser_api
|
||||
CURRENT_DIR=$(pwd)
|
||||
${CURRENT_DIR}/bin/phpunit --configuration unit_tests.xml
|
||||
|
49
vendor/jcalderonzumba/gastonjs/composer.json
vendored
Normal file
49
vendor/jcalderonzumba/gastonjs/composer.json
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"name": "jcalderonzumba/gastonjs",
|
||||
"description": "PhantomJS API based server for webpage automation",
|
||||
"keywords": [
|
||||
"phantomjs",
|
||||
"headless",
|
||||
"api",
|
||||
"automation",
|
||||
"browser"
|
||||
],
|
||||
"homepage": "https://github.com/jcalderonzumba/gastonjs",
|
||||
"type": "phantomjs-api",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Juan Francisco Calderón Zumba",
|
||||
"email": "juanfcz@gmail.com",
|
||||
"homepage": "http://github.com/jcalderonzumba"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.4",
|
||||
"guzzlehttp/guzzle": "~5.0|~6.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/process": "~2.1",
|
||||
"symfony/phpunit-bridge": "~2.7",
|
||||
"phpunit/phpunit": "~4.6",
|
||||
"silex/silex": "~1.2"
|
||||
},
|
||||
"config": {
|
||||
"bin-dir": "bin"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Zumba\\GastonJS\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Zumba\\GastonJS\\Tests\\": "tests/unit"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.1.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
40
vendor/jcalderonzumba/gastonjs/mkdocs.yml
vendored
Normal file
40
vendor/jcalderonzumba/gastonjs/mkdocs.yml
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
site_name: GastonJS Documentation
|
||||
pages:
|
||||
- GastonJS introduction: index.md
|
||||
- GastonJS API :
|
||||
- 'Introduction': api/index.md
|
||||
- 'Available commands': api/command-list.md
|
||||
- 'Navigation commands':
|
||||
- 'visit': api/commands/navigation/visit.md
|
||||
- 'current_url': api/commands/navigation/current_url.md
|
||||
- 'reload': api/commands/navigation/reload.md
|
||||
- 'go_back': api/commands/navigation/go_back.md
|
||||
- 'go_forward': api/commands/navigation/go_forward.md
|
||||
- 'Header commands' :
|
||||
- 'get_headers': api/commands/headers/get_headers.md
|
||||
- 'response_headers': api/commands/headers/response_headers.md
|
||||
- 'set_headers': api/commands/headers/set_headers.md
|
||||
- 'add_headers': api/commands/headers/add_headers.md
|
||||
- 'add_header': api/commands/headers/add_header.md
|
||||
- 'Javascript commands' :
|
||||
- 'add_extension': api/commands/javascript/add_extension.md
|
||||
- 'execute': api/commands/javascript/execute.md
|
||||
- 'evaluate': api/commands/javascript/evaluate.md
|
||||
- 'set_js_errors': api/commands/javascript/set_js_errors.md
|
||||
- 'Cookies commands' :
|
||||
- 'cookies': api/commands/cookies/cookies.md
|
||||
- 'clear_cookies': api/commands/cookies/clear_cookies.md
|
||||
- 'cookies_enabled': api/commands/cookies/cookies_enabled.md
|
||||
- 'remove_cookie': api/commands/cookies/remove_cookie.md
|
||||
- 'set_cookie': api/commands/cookies/set_cookie.md
|
||||
- 'Mouse commands':
|
||||
- 'click': api/commands/mouse/click.md
|
||||
- 'right_click': api/commands/mouse/right_click.md
|
||||
- 'hover': api/commands/mouse/hover.md
|
||||
- 'double_click': api/commands/mouse/double_click.md
|
||||
- 'click_coordinates': api/commands/mouse/click_coordinates.md
|
||||
- 'mouse_event': api/commands/mouse/mouse_event.md
|
||||
- 'Render commands':
|
||||
- 'render': api/commands/render/render.md
|
||||
- 'render_base64': api/commands/render/render_base64.md
|
||||
- GastonJS PHP client: clients/php/index.md
|
120
vendor/jcalderonzumba/gastonjs/src/Browser/Browser.php
vendored
Normal file
120
vendor/jcalderonzumba/gastonjs/src/Browser/Browser.php
vendored
Normal file
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Browser;
|
||||
|
||||
/**
|
||||
* Class Browser
|
||||
* @package Zumba\GastonJS
|
||||
*/
|
||||
class Browser extends BrowserBase {
|
||||
|
||||
use BrowserAuthenticationTrait;
|
||||
use BrowserConfigurationTrait;
|
||||
use BrowserCookieTrait;
|
||||
use BrowserFileTrait;
|
||||
use BrowserFrameTrait;
|
||||
use BrowserHeadersTrait;
|
||||
use BrowserMouseEventTrait;
|
||||
use BrowserNavigateTrait;
|
||||
use BrowserNetworkTrait;
|
||||
use BrowserPageElementTrait;
|
||||
use BrowserPageTrait;
|
||||
use BrowserRenderTrait;
|
||||
use BrowserScriptTrait;
|
||||
use BrowserWindowTrait;
|
||||
|
||||
/**
|
||||
* @param string $phantomJSHost
|
||||
* @param mixed $logger
|
||||
*/
|
||||
public function __construct($phantomJSHost, $logger = null) {
|
||||
$this->phantomJSHost = $phantomJSHost;
|
||||
$this->logger = $logger;
|
||||
$this->debug = false;
|
||||
$this->createApiClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a given element in a page
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @return mixed
|
||||
*/
|
||||
public function value($pageId, $elementId) {
|
||||
return $this->command('value', $pageId, $elementId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a value to a given element in a given page
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @param $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function set($pageId, $elementId, $value) {
|
||||
return $this->command('set', $pageId, $elementId, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether an element on a page is visible or not
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @return bool
|
||||
*/
|
||||
public function isVisible($pageId, $elementId) {
|
||||
return $this->command('visible', $pageId, $elementId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @return bool
|
||||
*/
|
||||
public function isDisabled($pageId, $elementId) {
|
||||
return $this->command('disabled', $pageId, $elementId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drag an element to a another in a given page
|
||||
* @param $pageId
|
||||
* @param $fromId
|
||||
* @param $toId
|
||||
* @return mixed
|
||||
*/
|
||||
public function drag($pageId, $fromId, $toId) {
|
||||
return $this->command('drag', $pageId, $fromId, $toId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects a value in the given element and page
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @param $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function select($pageId, $elementId, $value) {
|
||||
return $this->command('select', $pageId, $elementId, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers an event to a given element on the given page
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @param $event
|
||||
* @return mixed
|
||||
*/
|
||||
public function trigger($pageId, $elementId, $event) {
|
||||
return $this->command('trigger', $pageId, $elementId, $event);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: not sure what this does, needs to do normalizeKeys
|
||||
* @param int $pageId
|
||||
* @param int $elementId
|
||||
* @param array $keys
|
||||
* @return mixed
|
||||
*/
|
||||
public function sendKeys($pageId, $elementId, $keys) {
|
||||
return $this->command('send_keys', $pageId, $elementId, $this->normalizeKeys($keys));
|
||||
}
|
||||
}
|
19
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserAuthenticationTrait.php
vendored
Normal file
19
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserAuthenticationTrait.php
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Browser;
|
||||
|
||||
/**
|
||||
* Trait BrowserAuthenticationTrait
|
||||
* @package Zumba\GastonJS\Browser
|
||||
*/
|
||||
trait BrowserAuthenticationTrait {
|
||||
/**
|
||||
* Sets basic HTTP authentication
|
||||
* @param $user
|
||||
* @param $password
|
||||
* @return bool
|
||||
*/
|
||||
public function setHttpAuth($user, $password) {
|
||||
return $this->command('set_http_auth', $user, $password);
|
||||
}
|
||||
}
|
124
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserBase.php
vendored
Normal file
124
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserBase.php
vendored
Normal file
|
@ -0,0 +1,124 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Browser;
|
||||
|
||||
use Zumba\GastonJS\Exception\BrowserError;
|
||||
use Zumba\GastonJS\Exception\DeadClient;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\ConnectException;
|
||||
use GuzzleHttp\Exception\ServerException;
|
||||
|
||||
/**
|
||||
* Class BrowserBase
|
||||
* @package Zumba\GastonJS\Browser
|
||||
*/
|
||||
class BrowserBase {
|
||||
/** @var mixed */
|
||||
protected $logger;
|
||||
/** @var bool */
|
||||
protected $debug;
|
||||
/** @var string */
|
||||
protected $phantomJSHost;
|
||||
/** @var Client */
|
||||
protected $apiClient;
|
||||
|
||||
/**
|
||||
* Creates an http client to consume the phantomjs API
|
||||
*/
|
||||
protected function createApiClient() {
|
||||
// Provide a BC switch between guzzle 5 and guzzle 6.
|
||||
if (class_exists('GuzzleHttp\Psr7\Response')) {
|
||||
$this->apiClient = new Client(array("base_uri" => $this->getPhantomJSHost()));
|
||||
}
|
||||
else {
|
||||
$this->apiClient = new Client(array("base_url" => $this->getPhantomJSHost()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: not sure how to do the normalizeKeys stuff fix when needed
|
||||
* @param $keys
|
||||
* @return mixed
|
||||
*/
|
||||
protected function normalizeKeys($keys) {
|
||||
return $keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Client
|
||||
*/
|
||||
public function getApiClient() {
|
||||
return $this->apiClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPhantomJSHost() {
|
||||
return $this->phantomJSHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLogger() {
|
||||
return $this->logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restarts the browser
|
||||
*/
|
||||
public function restart() {
|
||||
//TODO: Do we really need to do this?, we are just a client
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a command to the browser
|
||||
* @throws BrowserError
|
||||
* @throws \Exception
|
||||
* @return mixed
|
||||
*/
|
||||
public function command() {
|
||||
try {
|
||||
$args = func_get_args();
|
||||
$commandName = $args[0];
|
||||
array_shift($args);
|
||||
$messageToSend = json_encode(array('name' => $commandName, 'args' => $args));
|
||||
/** @var $commandResponse \GuzzleHttp\Psr7\Response|\GuzzleHttp\Message\Response */
|
||||
$commandResponse = $this->getApiClient()->post("/api", array("body" => $messageToSend));
|
||||
$jsonResponse = json_decode($commandResponse->getBody(), TRUE);
|
||||
} catch (ServerException $e) {
|
||||
$jsonResponse = json_decode($e->getResponse()->getBody()->getContents(), true);
|
||||
} catch (ConnectException $e) {
|
||||
throw new DeadClient($e->getMessage(), $e->getCode(), $e);
|
||||
} catch (\Exception $e) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
if (isset($jsonResponse['error'])) {
|
||||
throw $this->getErrorClass($jsonResponse);
|
||||
}
|
||||
|
||||
return $jsonResponse['response'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $error
|
||||
* @return BrowserError
|
||||
*/
|
||||
protected function getErrorClass($error) {
|
||||
$errorClassMap = array(
|
||||
'Poltergeist.JavascriptError' => "Zumba\\GastonJS\\Exception\\JavascriptError",
|
||||
'Poltergeist.FrameNotFound' => "Zumba\\GastonJS\\Exception\\FrameNotFound",
|
||||
'Poltergeist.InvalidSelector' => "Zumba\\GastonJS\\Exception\\InvalidSelector",
|
||||
'Poltergeist.StatusFailError' => "Zumba\\GastonJS\\Exception\\StatusFailError",
|
||||
'Poltergeist.NoSuchWindowError' => "Zumba\\GastonJS\\Exception\\NoSuchWindowError",
|
||||
'Poltergeist.ObsoleteNode' => "Zumba\\GastonJS\\Exception\\ObsoleteNode"
|
||||
);
|
||||
if (isset($error['error']['name']) && isset($errorClassMap[$error["error"]["name"]])) {
|
||||
return new $errorClassMap[$error["error"]["name"]]($error);
|
||||
}
|
||||
|
||||
return new BrowserError($error);
|
||||
}
|
||||
}
|
39
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserConfigurationTrait.php
vendored
Normal file
39
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserConfigurationTrait.php
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Browser;
|
||||
|
||||
|
||||
/**
|
||||
* Trait BrowserConfigurationTrait
|
||||
* @package Zumba\GastonJS\Browser
|
||||
*/
|
||||
trait BrowserConfigurationTrait {
|
||||
/**
|
||||
* Set whether to fail or not on javascript errors found on the page
|
||||
* @param bool $enabled
|
||||
* @return bool
|
||||
*/
|
||||
public function jsErrors($enabled = true) {
|
||||
return $this->command('set_js_errors', $enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a blacklist of urls that we are not supposed to load
|
||||
* @param array $blackList
|
||||
* @return bool
|
||||
*/
|
||||
public function urlBlacklist($blackList) {
|
||||
return $this->command('set_url_blacklist', $blackList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the debug mode on the browser
|
||||
* @param bool $enable
|
||||
* @return bool
|
||||
*/
|
||||
public function debug($enable = false) {
|
||||
$this->debug = $enable;
|
||||
return $this->command('set_debug', $this->debug);
|
||||
}
|
||||
|
||||
}
|
65
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserCookieTrait.php
vendored
Normal file
65
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserCookieTrait.php
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Browser;
|
||||
|
||||
use Zumba\GastonJS\Cookie;
|
||||
|
||||
/**
|
||||
* Trait BrowserCookieTrait
|
||||
* @package Zumba\GastonJS\Browser
|
||||
*/
|
||||
trait BrowserCookieTrait {
|
||||
/**
|
||||
* Gets the cookies on the browser
|
||||
*
|
||||
* @return Cookie[]
|
||||
*/
|
||||
public function cookies() {
|
||||
$cookies = $this->command('cookies');
|
||||
$objCookies = array();
|
||||
foreach ($cookies as $cookie) {
|
||||
$objCookies[$cookie["name"]] = new Cookie($cookie);
|
||||
}
|
||||
return $objCookies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a cookie on the browser, expires times is set in seconds
|
||||
* @param $cookie
|
||||
* @return mixed
|
||||
*/
|
||||
public function setCookie($cookie) {
|
||||
//TODO: add error control when the cookie array is not valid
|
||||
if (isset($cookie["expires"])) {
|
||||
$cookie["expires"] = intval($cookie["expires"]) * 1000;
|
||||
}
|
||||
$cookie['value'] = urlencode($cookie['value']);
|
||||
return $this->command('set_cookie', $cookie);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a cookie on the browser if exists
|
||||
* @param $cookieName
|
||||
* @return bool
|
||||
*/
|
||||
public function removeCookie($cookieName) {
|
||||
return $this->command('remove_cookie', $cookieName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all the cookies
|
||||
* @return bool
|
||||
*/
|
||||
public function clearCookies() {
|
||||
return $this->command('clear_cookies');
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the cookies con phantomjs
|
||||
* @param bool $enabled
|
||||
* @return bool
|
||||
*/
|
||||
public function cookiesEnabled($enabled = true) {
|
||||
return $this->command('cookies_enabled', $enabled);
|
||||
}
|
||||
}
|
20
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserFileTrait.php
vendored
Normal file
20
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserFileTrait.php
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Browser;
|
||||
|
||||
/**
|
||||
* Trait BrowserFileTrait
|
||||
* @package Zumba\GastonJS\Browser
|
||||
*/
|
||||
trait BrowserFileTrait {
|
||||
/**
|
||||
* Selects a file to send to the browser to a given page
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @param $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function selectFile($pageId, $elementId, $value) {
|
||||
return $this->command('select_file', $pageId, $elementId, $value);
|
||||
}
|
||||
}
|
31
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserFrameTrait.php
vendored
Normal file
31
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserFrameTrait.php
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Browser;
|
||||
|
||||
/**
|
||||
* Trait BrowserFrameTrait
|
||||
* @package Zumba\GastonJS\Browser
|
||||
*/
|
||||
trait BrowserFrameTrait {
|
||||
/**
|
||||
* Back to the parent of the iframe if possible
|
||||
* @return mixed
|
||||
* @throws \Zumba\GastonJS\Exception\BrowserError
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function popFrame() {
|
||||
return $this->command("pop_frame");
|
||||
}
|
||||
|
||||
/**
|
||||
* Goes into the iframe to do stuff
|
||||
* @param string $name
|
||||
* @param int $timeout
|
||||
* @return mixed
|
||||
* @throws \Zumba\GastonJS\Exception\BrowserError
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function pushFrame($name, $timeout = null) {
|
||||
return $this->command("push_frame", $name, $timeout);
|
||||
}
|
||||
}
|
53
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserHeadersTrait.php
vendored
Normal file
53
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserHeadersTrait.php
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Browser;
|
||||
|
||||
/**
|
||||
* Trait BrowserHeadersTrait
|
||||
* @package Zumba\GastonJS\Browser
|
||||
*/
|
||||
trait BrowserHeadersTrait {
|
||||
/**
|
||||
* Returns the headers of the current page that will be used the next request
|
||||
* @return mixed
|
||||
*/
|
||||
public function getHeaders() {
|
||||
return $this->command('get_headers');
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array of headers, set such headers for the requests, removing all others
|
||||
* @param array $headers
|
||||
* @return mixed
|
||||
*/
|
||||
public function setHeaders($headers) {
|
||||
return $this->command('set_headers', $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds headers to current page overriding the existing ones for the next requests
|
||||
* @param $headers
|
||||
* @return mixed
|
||||
*/
|
||||
public function addHeaders($headers) {
|
||||
return $this->command('add_headers', $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a header to the page making it permanent if needed
|
||||
* @param $header
|
||||
* @param $permanent
|
||||
* @return mixed
|
||||
*/
|
||||
public function addHeader($header, $permanent = false) {
|
||||
return $this->command('add_header', $header, $permanent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the response headers after a request
|
||||
* @return mixed
|
||||
*/
|
||||
public function responseHeaders() {
|
||||
return $this->command('response_headers');
|
||||
}
|
||||
}
|
69
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserMouseEventTrait.php
vendored
Normal file
69
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserMouseEventTrait.php
vendored
Normal file
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Browser;
|
||||
|
||||
/**
|
||||
* Trait BrowserMouseEventTrait
|
||||
* @package Zumba\GastonJS\Browser
|
||||
*/
|
||||
trait BrowserMouseEventTrait {
|
||||
/**
|
||||
* Click on a given page and element
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @return mixed
|
||||
*/
|
||||
public function click($pageId, $elementId) {
|
||||
return $this->command('click', $pageId, $elementId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers a right click on a page an element
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @return mixed
|
||||
*/
|
||||
public function rightClick($pageId, $elementId) {
|
||||
return $this->command('right_click', $pageId, $elementId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers a double click in a given page and element
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @return mixed
|
||||
*/
|
||||
public function doubleClick($pageId, $elementId) {
|
||||
return $this->command('double_click', $pageId, $elementId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hovers over an element in a given page
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @return mixed
|
||||
*/
|
||||
public function hover($pageId, $elementId) {
|
||||
return $this->command('hover', $pageId, $elementId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Click on given coordinates, THIS DOES NOT depend on the page, it just clicks on where we are right now
|
||||
* @param $coordX
|
||||
* @param $coordY
|
||||
* @return mixed
|
||||
*/
|
||||
public function clickCoordinates($coordX, $coordY) {
|
||||
return $this->command('click_coordinates', $coordX, $coordY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrolls the page by a given left and top coordinates
|
||||
* @param $left
|
||||
* @param $top
|
||||
* @return mixed
|
||||
*/
|
||||
public function scrollTo($left, $top) {
|
||||
return $this->command('scroll_to', $left, $top);
|
||||
}
|
||||
}
|
56
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserNavigateTrait.php
vendored
Normal file
56
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserNavigateTrait.php
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Browser;
|
||||
|
||||
use Zumba\GastonJS\Exception\BrowserError;
|
||||
|
||||
/**
|
||||
* Trait BrowserNavigateTrait
|
||||
* @package Zumba\GastonJS\Browser
|
||||
*/
|
||||
trait BrowserNavigateTrait {
|
||||
|
||||
/**
|
||||
* Send a visit command to the browser
|
||||
* @param $url
|
||||
* @return mixed
|
||||
*/
|
||||
public function visit($url) {
|
||||
return $this->command('visit', $url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current url we are in
|
||||
* @return mixed
|
||||
*/
|
||||
public function currentUrl() {
|
||||
return $this->command('current_url');
|
||||
}
|
||||
|
||||
/**
|
||||
* Goes back on the browser history if possible
|
||||
* @return bool
|
||||
* @throws BrowserError
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function goBack() {
|
||||
return $this->command('go_back');
|
||||
}
|
||||
|
||||
/**
|
||||
* Goes forward on the browser history if possible
|
||||
* @return mixed
|
||||
* @throws BrowserError
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function goForward() {
|
||||
return $this->command('go_forward');
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads the current page we are in
|
||||
*/
|
||||
public function reload() {
|
||||
return $this->command('reload');
|
||||
}
|
||||
}
|
39
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserNetworkTrait.php
vendored
Normal file
39
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserNetworkTrait.php
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Browser;
|
||||
|
||||
use Zumba\GastonJS\NetworkTraffic\Request;
|
||||
|
||||
/**
|
||||
* Trait BrowserNetworkTrait
|
||||
* @package Zumba\GastonJS\Browser
|
||||
*/
|
||||
trait BrowserNetworkTrait {
|
||||
/**
|
||||
* Get all the network traffic that the page have created
|
||||
* @return array
|
||||
*/
|
||||
public function networkTraffic() {
|
||||
$networkTraffic = $this->command('network_traffic');
|
||||
$requestTraffic = array();
|
||||
|
||||
if (count($networkTraffic) === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach ($networkTraffic as $traffic) {
|
||||
$requestTraffic[] = new Request($traffic["request"], $traffic["responseParts"]);
|
||||
}
|
||||
|
||||
return $requestTraffic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the network traffic data stored on the phantomjs code
|
||||
* @return mixed
|
||||
*/
|
||||
public function clearNetworkTraffic() {
|
||||
return $this->command('clear_network_traffic');
|
||||
}
|
||||
|
||||
}
|
193
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserPageElementTrait.php
vendored
Normal file
193
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserPageElementTrait.php
vendored
Normal file
|
@ -0,0 +1,193 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Browser;
|
||||
|
||||
/**
|
||||
* Trait BrowserPageElementTrait
|
||||
* @package Zumba\GastonJS\Browser
|
||||
*/
|
||||
trait BrowserPageElementTrait {
|
||||
/**
|
||||
* Find elements given a method and a selector
|
||||
* @param $method
|
||||
* @param $selector
|
||||
* @return array
|
||||
*/
|
||||
public function find($method, $selector) {
|
||||
$result = $this->command('find', $method, $selector);
|
||||
$found["page_id"] = $result["page_id"];
|
||||
foreach ($result["ids"] as $id) {
|
||||
$found["ids"][] = $id;
|
||||
}
|
||||
return $found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find elements within a page, method and selector
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @param $method
|
||||
* @param $selector
|
||||
* @return mixed
|
||||
*/
|
||||
public function findWithin($pageId, $elementId, $method, $selector) {
|
||||
return $this->command('find_within', $pageId, $elementId, $method, $selector);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @return mixed
|
||||
*/
|
||||
public function getParents($pageId, $elementId) {
|
||||
return $this->command('parents', $pageId, $elementId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text of a given page and element
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @return mixed
|
||||
*/
|
||||
public function allText($pageId, $elementId) {
|
||||
return $this->command('all_text', $pageId, $elementId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inner or outer html of the given page and element
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @param $type
|
||||
* @return mixed
|
||||
* @throws \Zumba\GastonJS\Exception\BrowserError
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function allHtml($pageId, $elementId, $type = "inner") {
|
||||
return $this->command('all_html', $pageId, $elementId, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns ONLY the visible text of a given page and element
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @return mixed
|
||||
*/
|
||||
public function visibleText($pageId, $elementId) {
|
||||
return $this->command('visible_text', $pageId, $elementId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the text of a given page and element
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @return mixed
|
||||
*/
|
||||
public function deleteText($pageId, $elementId) {
|
||||
return $this->command('delete_text', $pageId, $elementId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the tag name of a given element and page
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @return string
|
||||
*/
|
||||
public function tagName($pageId, $elementId) {
|
||||
return strtolower($this->command('tag_name', $pageId, $elementId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if two elements are the same on a give
|
||||
* @param $pageId
|
||||
* @param $firstId
|
||||
* @param $secondId
|
||||
* @return bool
|
||||
*/
|
||||
public function equals($pageId, $firstId, $secondId) {
|
||||
return $this->command('equals', $pageId, $firstId, $secondId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attributes of an element in a given page
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @return mixed
|
||||
*/
|
||||
public function attributes($pageId, $elementId) {
|
||||
return $this->command('attributes', $pageId, $elementId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attribute of an element by name in a given page
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @param $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function attribute($pageId, $elementId, $name) {
|
||||
return $this->command('attribute', $pageId, $elementId, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an attribute to the given element in the given page
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @param $name
|
||||
* @param $value
|
||||
* @return mixed
|
||||
* @throws \Zumba\GastonJS\Exception\BrowserError
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function setAttribute($pageId, $elementId, $name, $value) {
|
||||
return $this->command('set_attribute', $pageId, $elementId, $name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an attribute for a given page and element
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @param $name
|
||||
* @return mixed
|
||||
* @throws \Zumba\GastonJS\Exception\BrowserError
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function removeAttribute($pageId, $elementId, $name) {
|
||||
return $this->command('remove_attribute', $pageId, $elementId, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an element is visible or not
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @return boolean
|
||||
*/
|
||||
public function isVisible($pageId, $elementId) {
|
||||
return $this->command("visible", $pageId, $elementId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the order to execute a key event on a given element
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @param $keyEvent
|
||||
* @param $key
|
||||
* @param $modifier
|
||||
* @return mixed
|
||||
*/
|
||||
public function keyEvent($pageId, $elementId, $keyEvent, $key, $modifier) {
|
||||
return $this->command("key_event", $pageId, $elementId, $keyEvent, $key, $modifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the command to select and option given a value
|
||||
* @param $pageId
|
||||
* @param $elementId
|
||||
* @param $value
|
||||
* @param bool $multiple
|
||||
* @return mixed
|
||||
*/
|
||||
public function selectOption($pageId, $elementId, $value, $multiple = false) {
|
||||
return $this->command("select_option", $pageId, $elementId, $value, $multiple);
|
||||
}
|
||||
|
||||
}
|
59
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserPageTrait.php
vendored
Normal file
59
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserPageTrait.php
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Browser;
|
||||
|
||||
/**
|
||||
* Trait BrowserPageTrait
|
||||
* @package Zumba\GastonJS\Browser
|
||||
*/
|
||||
trait BrowserPageTrait {
|
||||
/**
|
||||
* Gets the status code of the request we are currently in
|
||||
* @return mixed
|
||||
*/
|
||||
public function getStatusCode() {
|
||||
return $this->command('status_code');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the body of the response to a given browser request
|
||||
* @return mixed
|
||||
*/
|
||||
public function getBody() {
|
||||
return $this->command('body');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the source of the current page
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSource() {
|
||||
return $this->command('source');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current page title
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTitle() {
|
||||
return $this->command('title');
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize the current page
|
||||
* @param $width
|
||||
* @param $height
|
||||
* @return mixed
|
||||
*/
|
||||
public function resize($width, $height) {
|
||||
return $this->command('resize', $width, $height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the page we are in to a clean slate
|
||||
* @return mixed
|
||||
*/
|
||||
public function reset() {
|
||||
return $this->command('reset');
|
||||
}
|
||||
}
|
65
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserRenderTrait.php
vendored
Normal file
65
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserRenderTrait.php
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Browser;
|
||||
|
||||
/**
|
||||
* Trait BrowserRenderTrait
|
||||
* @package Zumba\GastonJS\Browser
|
||||
*/
|
||||
trait BrowserRenderTrait {
|
||||
/**
|
||||
* Check and fix render options
|
||||
* @param $options
|
||||
* @return mixed
|
||||
*/
|
||||
protected function checkRenderOptions($options) {
|
||||
//Default is full and no selection
|
||||
if (count($options) === 0) {
|
||||
$options["full"] = true;
|
||||
$options["selector"] = null;
|
||||
}
|
||||
|
||||
if (isset($options["full"]) && isset($options["selector"])) {
|
||||
if ($options["full"]) {
|
||||
//Whatever it is, full is more powerful than selection
|
||||
$options["selector"] = null;
|
||||
}
|
||||
} else {
|
||||
if (!isset($options["full"]) && isset($options["selector"])) {
|
||||
$options["full"] = false;
|
||||
}
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a page or selection to a file given by path
|
||||
* @param string $path
|
||||
* @param array $options
|
||||
* @return mixed
|
||||
*/
|
||||
public function render($path, $options = array()) {
|
||||
$fixedOptions = $this->checkRenderOptions($options);
|
||||
return $this->command('render', $path, $fixedOptions["full"], $fixedOptions["selector"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders base64 a page or selection to a file given by path
|
||||
* @param string $imageFormat (PNG, GIF, JPEG)
|
||||
* @param array $options
|
||||
* @return mixed
|
||||
*/
|
||||
public function renderBase64($imageFormat, $options = array()) {
|
||||
$fixedOptions = $this->checkRenderOptions($options);
|
||||
return $this->command('render_base64', $imageFormat, $fixedOptions["full"], $fixedOptions["selector"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the paper size, useful when saving to PDF
|
||||
* @param $paperSize
|
||||
* @return mixed
|
||||
*/
|
||||
public function setPaperSize($paperSize) {
|
||||
return $this->command('set_paper_size', $paperSize);
|
||||
}
|
||||
}
|
41
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserScriptTrait.php
vendored
Normal file
41
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserScriptTrait.php
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Browser;
|
||||
|
||||
/**
|
||||
* Trait BrowserScriptTrait
|
||||
* @package Zumba\GastonJS\Browser
|
||||
*/
|
||||
trait BrowserScriptTrait {
|
||||
/**
|
||||
* Evaluates a script on the browser
|
||||
* @param $script
|
||||
* @return mixed
|
||||
*/
|
||||
public function evaluate($script) {
|
||||
return $this->command('evaluate', $script);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a script on the browser
|
||||
* @param $script
|
||||
* @return mixed
|
||||
*/
|
||||
public function execute($script) {
|
||||
return $this->command('execute', $script);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add desired extensions to phantomjs
|
||||
* @param $extensions
|
||||
* @return bool
|
||||
*/
|
||||
public function extensions($extensions) {
|
||||
//TODO: add error control for when extensions do not exist physically
|
||||
foreach ($extensions as $extensionName) {
|
||||
$this->command('add_extension', $extensionName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
81
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserWindowTrait.php
vendored
Normal file
81
vendor/jcalderonzumba/gastonjs/src/Browser/BrowserWindowTrait.php
vendored
Normal file
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Browser;
|
||||
|
||||
/**
|
||||
* Class BrowserWindowTrait
|
||||
* @package Zumba\GastonJS\Browser
|
||||
*/
|
||||
trait BrowserWindowTrait {
|
||||
/**
|
||||
* Returns the current window handle name in the browser
|
||||
* @param string $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function windowHandle($name = null) {
|
||||
return $this->command('window_handle', $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the window handles present in the browser
|
||||
* @return array
|
||||
*/
|
||||
public function windowHandles() {
|
||||
return $this->command('window_handles');
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the browser focus to another window
|
||||
* @param $windowHandleName
|
||||
* @return mixed
|
||||
*/
|
||||
public function switchToWindow($windowHandleName) {
|
||||
return $this->command('switch_to_window', $windowHandleName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a new window on the browser
|
||||
* @return mixed
|
||||
*/
|
||||
public function openNewWindow() {
|
||||
return $this->command('open_new_window');
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes a window on the browser by a given handler name
|
||||
* @param $windowHandleName
|
||||
* @return mixed
|
||||
*/
|
||||
public function closeWindow($windowHandleName) {
|
||||
return $this->command('close_window', $windowHandleName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current request window name
|
||||
* @return string
|
||||
* @throws \Zumba\GastonJS\Exception\BrowserError
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function windowName() {
|
||||
return $this->command('window_name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Zoom factor for a web page
|
||||
* @param $zoomFactor
|
||||
* @return mixed
|
||||
*/
|
||||
public function setZoomFactor($zoomFactor) {
|
||||
return $this->command('set_zoom_factor', $zoomFactor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the window size
|
||||
* @param $windowHandleName
|
||||
* @return mixed
|
||||
*/
|
||||
public function windowSize($windowHandleName) {
|
||||
return $this->command('window_size', $windowHandleName);
|
||||
}
|
||||
|
||||
}
|
17
vendor/jcalderonzumba/gastonjs/src/Client/Errors/browser_error.js
vendored
Normal file
17
vendor/jcalderonzumba/gastonjs/src/Client/Errors/browser_error.js
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
Poltergeist.BrowserError = (function (_super) {
|
||||
__extends(BrowserError, _super);
|
||||
|
||||
function BrowserError(message, stack) {
|
||||
this.message = message;
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
BrowserError.prototype.name = "Poltergeist.BrowserError";
|
||||
|
||||
BrowserError.prototype.args = function () {
|
||||
return [this.message, this.stack];
|
||||
};
|
||||
|
||||
return BrowserError;
|
||||
|
||||
})(Poltergeist.Error);
|
10
vendor/jcalderonzumba/gastonjs/src/Client/Errors/error.js
vendored
Normal file
10
vendor/jcalderonzumba/gastonjs/src/Client/Errors/error.js
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* Poltergeist base error class
|
||||
*/
|
||||
Poltergeist.Error = (function () {
|
||||
function Error() {
|
||||
}
|
||||
|
||||
return Error;
|
||||
|
||||
})();
|
16
vendor/jcalderonzumba/gastonjs/src/Client/Errors/frame_not_found.js
vendored
Normal file
16
vendor/jcalderonzumba/gastonjs/src/Client/Errors/frame_not_found.js
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
Poltergeist.FrameNotFound = (function (_super) {
|
||||
__extends(FrameNotFound, _super);
|
||||
|
||||
function FrameNotFound(frameName) {
|
||||
this.frameName = frameName;
|
||||
}
|
||||
|
||||
FrameNotFound.prototype.name = "Poltergeist.FrameNotFound";
|
||||
|
||||
FrameNotFound.prototype.args = function () {
|
||||
return [this.frameName];
|
||||
};
|
||||
|
||||
return FrameNotFound;
|
||||
|
||||
})(Poltergeist.Error);
|
17
vendor/jcalderonzumba/gastonjs/src/Client/Errors/invalid_selector.js
vendored
Normal file
17
vendor/jcalderonzumba/gastonjs/src/Client/Errors/invalid_selector.js
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
Poltergeist.InvalidSelector = (function (_super) {
|
||||
__extends(InvalidSelector, _super);
|
||||
|
||||
function InvalidSelector(method, selector) {
|
||||
this.method = method;
|
||||
this.selector = selector;
|
||||
}
|
||||
|
||||
InvalidSelector.prototype.name = "Poltergeist.InvalidSelector";
|
||||
|
||||
InvalidSelector.prototype.args = function () {
|
||||
return [this.method, this.selector];
|
||||
};
|
||||
|
||||
return InvalidSelector;
|
||||
|
||||
})(Poltergeist.Error);
|
16
vendor/jcalderonzumba/gastonjs/src/Client/Errors/javascript_error.js
vendored
Normal file
16
vendor/jcalderonzumba/gastonjs/src/Client/Errors/javascript_error.js
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
Poltergeist.JavascriptError = (function (_super) {
|
||||
__extends(JavascriptError, _super);
|
||||
|
||||
function JavascriptError(errors) {
|
||||
this.errors = errors;
|
||||
}
|
||||
|
||||
JavascriptError.prototype.name = "Poltergeist.JavascriptError";
|
||||
|
||||
JavascriptError.prototype.args = function () {
|
||||
return [this.errors];
|
||||
};
|
||||
|
||||
return JavascriptError;
|
||||
|
||||
})(Poltergeist.Error);
|
18
vendor/jcalderonzumba/gastonjs/src/Client/Errors/mouse_event_failed.js
vendored
Normal file
18
vendor/jcalderonzumba/gastonjs/src/Client/Errors/mouse_event_failed.js
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
Poltergeist.MouseEventFailed = (function (_super) {
|
||||
__extends(MouseEventFailed, _super);
|
||||
|
||||
function MouseEventFailed(eventName, selector, position) {
|
||||
this.eventName = eventName;
|
||||
this.selector = selector;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
MouseEventFailed.prototype.name = "Poltergeist.MouseEventFailed";
|
||||
|
||||
MouseEventFailed.prototype.args = function () {
|
||||
return [this.eventName, this.selector, this.position];
|
||||
};
|
||||
|
||||
return MouseEventFailed;
|
||||
|
||||
})(Poltergeist.Error);
|
17
vendor/jcalderonzumba/gastonjs/src/Client/Errors/no_such_window_error.js
vendored
Normal file
17
vendor/jcalderonzumba/gastonjs/src/Client/Errors/no_such_window_error.js
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
Poltergeist.NoSuchWindowError = (function (_super) {
|
||||
__extends(NoSuchWindowError, _super);
|
||||
|
||||
function NoSuchWindowError() {
|
||||
_ref2 = NoSuchWindowError.__super__.constructor.apply(this, arguments);
|
||||
return _ref2;
|
||||
}
|
||||
|
||||
NoSuchWindowError.prototype.name = "Poltergeist.NoSuchWindowError";
|
||||
|
||||
NoSuchWindowError.prototype.args = function () {
|
||||
return [];
|
||||
};
|
||||
|
||||
return NoSuchWindowError;
|
||||
|
||||
})(Poltergeist.Error);
|
21
vendor/jcalderonzumba/gastonjs/src/Client/Errors/obsolete_node.js
vendored
Normal file
21
vendor/jcalderonzumba/gastonjs/src/Client/Errors/obsolete_node.js
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
Poltergeist.ObsoleteNode = (function (_super) {
|
||||
__extends(ObsoleteNode, _super);
|
||||
|
||||
function ObsoleteNode() {
|
||||
_ref = ObsoleteNode.__super__.constructor.apply(this, arguments);
|
||||
return _ref;
|
||||
}
|
||||
|
||||
ObsoleteNode.prototype.name = "Poltergeist.ObsoleteNode";
|
||||
|
||||
ObsoleteNode.prototype.args = function () {
|
||||
return [];
|
||||
};
|
||||
|
||||
ObsoleteNode.prototype.toString = function () {
|
||||
return this.name;
|
||||
};
|
||||
|
||||
return ObsoleteNode;
|
||||
|
||||
})(Poltergeist.Error);
|
17
vendor/jcalderonzumba/gastonjs/src/Client/Errors/status_fail_error.js
vendored
Normal file
17
vendor/jcalderonzumba/gastonjs/src/Client/Errors/status_fail_error.js
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
Poltergeist.StatusFailError = (function (_super) {
|
||||
__extends(StatusFailError, _super);
|
||||
|
||||
function StatusFailError() {
|
||||
_ref1 = StatusFailError.__super__.constructor.apply(this, arguments);
|
||||
return _ref1;
|
||||
}
|
||||
|
||||
StatusFailError.prototype.name = "Poltergeist.StatusFailError";
|
||||
|
||||
StatusFailError.prototype.args = function () {
|
||||
return [];
|
||||
};
|
||||
|
||||
return StatusFailError;
|
||||
|
||||
})(Poltergeist.Error);
|
80
vendor/jcalderonzumba/gastonjs/src/Client/Server/server.js
vendored
Normal file
80
vendor/jcalderonzumba/gastonjs/src/Client/Server/server.js
vendored
Normal file
|
@ -0,0 +1,80 @@
|
|||
Poltergeist.Server = (function () {
|
||||
|
||||
/**
|
||||
* Server constructor
|
||||
* @param owner
|
||||
* @param port
|
||||
* @constructor
|
||||
*/
|
||||
function Server(owner, port) {
|
||||
this.server = require('webserver').create();
|
||||
this.port = port;
|
||||
this.owner = owner;
|
||||
this.webServer = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the web server
|
||||
*/
|
||||
Server.prototype.start = function () {
|
||||
var self = this;
|
||||
this.webServer = this.server.listen(this.port, function (request, response) {
|
||||
self.handleRequest(request, response);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Send error back with code and message
|
||||
* @param response
|
||||
* @param code
|
||||
* @param message
|
||||
* @return {boolean}
|
||||
*/
|
||||
Server.prototype.sendError = function (response, code, message) {
|
||||
response.statusCode = code;
|
||||
response.setHeader('Content-Type', 'application/json');
|
||||
response.write(JSON.stringify(message, null, 4));
|
||||
response.close();
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Send response back to the client
|
||||
* @param response
|
||||
* @param data
|
||||
* @return {boolean}
|
||||
*/
|
||||
Server.prototype.send = function (response, data) {
|
||||
console.log("RESPONSE: " + JSON.stringify(data, null, 4).substr(0, 200));
|
||||
|
||||
response.statusCode = 200;
|
||||
response.setHeader('Content-Type', 'application/json');
|
||||
response.write(JSON.stringify(data, null, 4));
|
||||
response.close();
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles a request to the server
|
||||
* @param request
|
||||
* @param response
|
||||
* @return {boolean}
|
||||
*/
|
||||
Server.prototype.handleRequest = function (request, response) {
|
||||
var commandData;
|
||||
if (request.method !== "POST") {
|
||||
return this.sendError(response, 405, "Only POST method is allowed in the service");
|
||||
}
|
||||
console.log("REQUEST: " + request.post + "\n");
|
||||
try {
|
||||
commandData = JSON.parse(request.post);
|
||||
} catch (parseError) {
|
||||
return this.sendError(response, 400, "JSON data invalid error: " + parseError.message);
|
||||
}
|
||||
|
||||
return this.owner.serverRunCommand(commandData, response);
|
||||
};
|
||||
|
||||
return Server;
|
||||
})();
|
28
vendor/jcalderonzumba/gastonjs/src/Client/Tools/inherit.js
vendored
Normal file
28
vendor/jcalderonzumba/gastonjs/src/Client/Tools/inherit.js
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
var __extends;
|
||||
/**
|
||||
* Helper function so objects can inherit from another
|
||||
* @param child
|
||||
* @param parent
|
||||
* @return {Object}
|
||||
* @private
|
||||
*/
|
||||
__extends = function (child, parent) {
|
||||
var __hasProp;
|
||||
__hasProp = {}.hasOwnProperty;
|
||||
for (var key in parent) {
|
||||
if (parent.hasOwnProperty(key)) {
|
||||
if (__hasProp.call(parent, key)) {
|
||||
child[key] = parent[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ClassConstructor() {
|
||||
this.constructor = child;
|
||||
}
|
||||
|
||||
ClassConstructor.prototype = parent.prototype;
|
||||
child.prototype = new ClassConstructor();
|
||||
child.__super__ = parent.prototype;
|
||||
return child;
|
||||
};
|
896
vendor/jcalderonzumba/gastonjs/src/Client/agent.js
vendored
Normal file
896
vendor/jcalderonzumba/gastonjs/src/Client/agent.js
vendored
Normal file
|
@ -0,0 +1,896 @@
|
|||
var PoltergeistAgent;
|
||||
|
||||
PoltergeistAgent = (function () {
|
||||
function PoltergeistAgent() {
|
||||
this.elements = [];
|
||||
this.nodes = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes an external call done from the web page class
|
||||
* @param name
|
||||
* @param args
|
||||
* @return {*}
|
||||
*/
|
||||
PoltergeistAgent.prototype.externalCall = function (name, args) {
|
||||
var error;
|
||||
try {
|
||||
return {
|
||||
value: this[name].apply(this, args)
|
||||
};
|
||||
} catch (_error) {
|
||||
error = _error;
|
||||
return {
|
||||
error: {
|
||||
message: error.toString(),
|
||||
stack: error.stack
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Object stringifycation
|
||||
* @param object
|
||||
* @return {*}
|
||||
*/
|
||||
PoltergeistAgent.stringify = function (object) {
|
||||
var error;
|
||||
try {
|
||||
return JSON.stringify(object, function (key, value) {
|
||||
if (Array.isArray(this[key])) {
|
||||
return this[key];
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
});
|
||||
} catch (_error) {
|
||||
error = _error;
|
||||
if (error instanceof TypeError) {
|
||||
return '"(cyclic structure)"';
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Name speaks for itself
|
||||
* @return {string}
|
||||
*/
|
||||
PoltergeistAgent.prototype.currentUrl = function () {
|
||||
return encodeURI(decodeURI(window.location.href));
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a method of selection (xpath or css), a selector and a possible element to search
|
||||
* tries to find the elements that matches such selection
|
||||
* @param method
|
||||
* @param selector
|
||||
* @param within
|
||||
* @return {Array}
|
||||
*/
|
||||
PoltergeistAgent.prototype.find = function (method, selector, within) {
|
||||
var elementForXpath, error, i, results, xpath, _i, _len, _results;
|
||||
if (within == null) {
|
||||
within = document;
|
||||
}
|
||||
try {
|
||||
if (method === "xpath") {
|
||||
xpath = document.evaluate(selector, within, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
||||
results = (function () {
|
||||
var _i, _ref, _results;
|
||||
_results = [];
|
||||
for (i = _i = 0, _ref = xpath.snapshotLength; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
|
||||
_results.push(xpath.snapshotItem(i));
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
} else {
|
||||
results = within.querySelectorAll(selector);
|
||||
}
|
||||
_results = [];
|
||||
for (_i = 0, _len = results.length; _i < _len; _i++) {
|
||||
elementForXpath = results[_i];
|
||||
_results.push(this.register(elementForXpath));
|
||||
}
|
||||
return _results;
|
||||
} catch (_error) {
|
||||
error = _error;
|
||||
if (error.code === DOMException.SYNTAX_ERR || error.code === 51) {
|
||||
throw new PoltergeistAgent.InvalidSelector;
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Register the element in the agent
|
||||
* @param element
|
||||
* @return {number}
|
||||
*/
|
||||
PoltergeistAgent.prototype.register = function (element) {
|
||||
this.elements.push(element);
|
||||
return this.elements.length - 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the size of the document
|
||||
* @return {{height: number, width: number}}
|
||||
*/
|
||||
PoltergeistAgent.prototype.documentSize = function () {
|
||||
return {
|
||||
height: document.documentElement.scrollHeight || document.documentElement.clientHeight,
|
||||
width: document.documentElement.scrollWidth || document.documentElement.clientWidth
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets a Node by a given id
|
||||
* @param id
|
||||
* @return {PoltergeistAgent.Node}
|
||||
*/
|
||||
PoltergeistAgent.prototype.get = function (id) {
|
||||
if (typeof this.nodes[id] == "undefined" || this.nodes[id] === null) {
|
||||
//Let's try now the elements approach
|
||||
if (typeof this.elements[id] == "undefined" || this.elements[id] === null) {
|
||||
throw new PoltergeistAgent.ObsoleteNode;
|
||||
}
|
||||
return new PoltergeistAgent.Node(this, this.elements[id]);
|
||||
}
|
||||
|
||||
return this.nodes[id];
|
||||
};
|
||||
|
||||
/**
|
||||
* Calls a Node agent function from the Node caller via delegates
|
||||
* @param id
|
||||
* @param name
|
||||
* @param args
|
||||
* @return {*}
|
||||
*/
|
||||
PoltergeistAgent.prototype.nodeCall = function (id, name, args) {
|
||||
var node;
|
||||
|
||||
node = this.get(id);
|
||||
if (node.isObsolete()) {
|
||||
throw new PoltergeistAgent.ObsoleteNode;
|
||||
}
|
||||
//TODO: add some error control here, we might not be able to call name function
|
||||
return node[name].apply(node, args);
|
||||
};
|
||||
|
||||
PoltergeistAgent.prototype.beforeUpload = function (id) {
|
||||
return this.get(id).setAttribute('_poltergeist_selected', '');
|
||||
};
|
||||
|
||||
PoltergeistAgent.prototype.afterUpload = function (id) {
|
||||
return this.get(id).removeAttribute('_poltergeist_selected');
|
||||
};
|
||||
|
||||
PoltergeistAgent.prototype.clearLocalStorage = function () {
|
||||
//TODO: WTF where is variable...
|
||||
return localStorage.clear();
|
||||
};
|
||||
|
||||
return PoltergeistAgent;
|
||||
|
||||
})();
|
||||
|
||||
PoltergeistAgent.ObsoleteNode = (function () {
|
||||
function ObsoleteNode() {
|
||||
}
|
||||
|
||||
ObsoleteNode.prototype.toString = function () {
|
||||
return "PoltergeistAgent.ObsoleteNode";
|
||||
};
|
||||
|
||||
return ObsoleteNode;
|
||||
|
||||
})();
|
||||
|
||||
PoltergeistAgent.InvalidSelector = (function () {
|
||||
function InvalidSelector() {
|
||||
}
|
||||
|
||||
InvalidSelector.prototype.toString = function () {
|
||||
return "PoltergeistAgent.InvalidSelector";
|
||||
};
|
||||
|
||||
return InvalidSelector;
|
||||
|
||||
})();
|
||||
|
||||
PoltergeistAgent.Node = (function () {
|
||||
|
||||
Node.EVENTS = {
|
||||
FOCUS: ['blur', 'focus', 'focusin', 'focusout'],
|
||||
MOUSE: ['click', 'dblclick', 'mousedown', 'mouseenter', 'mouseleave', 'mousemove', 'mouseover', 'mouseout', 'mouseup', 'contextmenu'],
|
||||
FORM: ['submit']
|
||||
};
|
||||
|
||||
function Node(agent, element) {
|
||||
this.agent = agent;
|
||||
this.element = element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Give me the node id of the parent of this node
|
||||
* @return {number}
|
||||
*/
|
||||
Node.prototype.parentId = function () {
|
||||
return this.agent.register(this.element.parentNode);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns all the node parents ids up to first child of the dom
|
||||
* @return {Array}
|
||||
*/
|
||||
Node.prototype.parentIds = function () {
|
||||
var ids, parent;
|
||||
ids = [];
|
||||
parent = this.element.parentNode;
|
||||
while (parent !== document) {
|
||||
ids.push(this.agent.register(parent));
|
||||
parent = parent.parentNode;
|
||||
}
|
||||
return ids;
|
||||
};
|
||||
|
||||
/**
|
||||
* Finds and returns the node ids that matches the selector within this node
|
||||
* @param method
|
||||
* @param selector
|
||||
* @return {Array}
|
||||
*/
|
||||
Node.prototype.find = function (method, selector) {
|
||||
return this.agent.find(method, selector, this.element);
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks whether the node is obsolete or not
|
||||
* @return boolean
|
||||
*/
|
||||
Node.prototype.isObsolete = function () {
|
||||
var obsolete;
|
||||
|
||||
obsolete = function (element) {
|
||||
if (element.parentNode != null) {
|
||||
if (element.parentNode === document) {
|
||||
return false;
|
||||
} else {
|
||||
return obsolete(element.parentNode);
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
return obsolete(this.element);
|
||||
};
|
||||
|
||||
Node.prototype.changed = function () {
|
||||
var event;
|
||||
event = document.createEvent('HTMLEvents');
|
||||
event.initEvent('change', true, false);
|
||||
return this.element.dispatchEvent(event);
|
||||
};
|
||||
|
||||
Node.prototype.input = function () {
|
||||
var event;
|
||||
event = document.createEvent('HTMLEvents');
|
||||
event.initEvent('input', true, false);
|
||||
return this.element.dispatchEvent(event);
|
||||
};
|
||||
|
||||
Node.prototype.keyupdowned = function (eventName, keyCode) {
|
||||
var event;
|
||||
event = document.createEvent('UIEvents');
|
||||
event.initEvent(eventName, true, true);
|
||||
event.keyCode = keyCode;
|
||||
event.which = keyCode;
|
||||
event.charCode = 0;
|
||||
return this.element.dispatchEvent(event);
|
||||
};
|
||||
|
||||
Node.prototype.keypressed = function (altKey, ctrlKey, shiftKey, metaKey, keyCode, charCode) {
|
||||
var event;
|
||||
event = document.createEvent('UIEvents');
|
||||
event.initEvent('keypress', true, true);
|
||||
event.window = this.agent.window;
|
||||
event.altKey = altKey;
|
||||
event.ctrlKey = ctrlKey;
|
||||
event.shiftKey = shiftKey;
|
||||
event.metaKey = metaKey;
|
||||
event.keyCode = keyCode;
|
||||
event.charCode = charCode;
|
||||
event.which = keyCode;
|
||||
return this.element.dispatchEvent(event);
|
||||
};
|
||||
|
||||
/**
|
||||
* Tells if the node is inside the body of the document and not somewhere else
|
||||
* @return {boolean}
|
||||
*/
|
||||
Node.prototype.insideBody = function () {
|
||||
return this.element === document.body || document.evaluate('ancestor::body', this.element, null, XPathResult.BOOLEAN_TYPE, null).booleanValue;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns all text visible or not of the node
|
||||
* @return {string}
|
||||
*/
|
||||
Node.prototype.allText = function () {
|
||||
return this.element.textContent;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the inner html our outer
|
||||
* @returns {string}
|
||||
*/
|
||||
Node.prototype.allHTML = function (type) {
|
||||
var returnType = type || 'inner';
|
||||
|
||||
if (returnType === "inner") {
|
||||
return this.element.innerHTML;
|
||||
}
|
||||
|
||||
if (returnType === "outer") {
|
||||
if (this.element.outerHTML) {
|
||||
return this.element.outerHTML;
|
||||
}
|
||||
// polyfill:
|
||||
var wrapper = document.createElement('div');
|
||||
wrapper.appendChild(this.element.cloneNode(true));
|
||||
return wrapper.innerHTML;
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
/**
|
||||
* If the element is visible then we return the text
|
||||
* @return {string}
|
||||
*/
|
||||
Node.prototype.visibleText = function () {
|
||||
if (!this.isVisible(null)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this.element.nodeName === "TEXTAREA") {
|
||||
return this.element.textContent;
|
||||
}
|
||||
|
||||
return this.element.innerText;
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes the actual text being represented by a selection object from the node's element DOM.
|
||||
* @return {*}
|
||||
*/
|
||||
Node.prototype.deleteText = function () {
|
||||
var range;
|
||||
range = document.createRange();
|
||||
range.selectNodeContents(this.element);
|
||||
window.getSelection().removeAllRanges();
|
||||
window.getSelection().addRange(range);
|
||||
return window.getSelection().deleteFromDocument();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns all the attributes {name:value} in the element
|
||||
* @return {{}}
|
||||
*/
|
||||
Node.prototype.getAttributes = function () {
|
||||
var attributes, i, elementAttributes;
|
||||
|
||||
elementAttributes = this.element.attributes;
|
||||
attributes = {};
|
||||
for (i = 0; i < elementAttributes.length; i++) {
|
||||
attributes[elementAttributes[i].name] = elementAttributes[i].value.replace("\n", "\\n");
|
||||
}
|
||||
|
||||
return attributes;
|
||||
};
|
||||
|
||||
/**
|
||||
* Name speaks for it self, returns the value of a given attribute by name
|
||||
* @param name
|
||||
* @return {string}
|
||||
*/
|
||||
Node.prototype.getAttribute = function (name) {
|
||||
if (name === 'checked' || name === 'selected' || name === 'multiple') {
|
||||
return this.element[name];
|
||||
}
|
||||
return this.element.getAttribute(name);
|
||||
};
|
||||
|
||||
/**
|
||||
* Scrolls the current element into the visible area of the browser window
|
||||
* @return {*}
|
||||
*/
|
||||
Node.prototype.scrollIntoView = function () {
|
||||
return this.element.scrollIntoViewIfNeeded();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the element.value property with special treatment if the element is a select
|
||||
* @return {*}
|
||||
*/
|
||||
Node.prototype.value = function () {
|
||||
var options, i, values;
|
||||
|
||||
if (this.element.tagName.toLowerCase() === 'select' && this.element.multiple) {
|
||||
values = [];
|
||||
options = this.element.children;
|
||||
for (i = 0; i < options.length; i++) {
|
||||
if (options[i].selected) {
|
||||
values.push(options[i].value);
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
return this.element.value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets a given value in the element value property by simulation key interaction
|
||||
* @param value
|
||||
* @return {*}
|
||||
*/
|
||||
Node.prototype.set = function (value) {
|
||||
var char, keyCode, i, len;
|
||||
|
||||
if (this.element.readOnly) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//respect the maxLength property if present
|
||||
if (this.element.maxLength >= 0) {
|
||||
value = value.substr(0, this.element.maxLength);
|
||||
}
|
||||
|
||||
this.element.value = '';
|
||||
this.trigger('focus');
|
||||
|
||||
if (this.element.type === 'number') {
|
||||
this.element.value = value;
|
||||
} else {
|
||||
for (i = 0, len = value.length; i < len; i++) {
|
||||
char = value[i];
|
||||
keyCode = this.characterToKeyCode(char);
|
||||
this.keyupdowned('keydown', keyCode);
|
||||
this.element.value += char;
|
||||
this.keypressed(false, false, false, false, char.charCodeAt(0), char.charCodeAt(0));
|
||||
this.keyupdowned('keyup', keyCode);
|
||||
}
|
||||
}
|
||||
|
||||
this.changed();
|
||||
this.input();
|
||||
|
||||
return this.trigger('blur');
|
||||
};
|
||||
|
||||
/**
|
||||
* Is the node multiple
|
||||
* @return {boolean}
|
||||
*/
|
||||
Node.prototype.isMultiple = function () {
|
||||
return this.element.multiple;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the value of an attribute given by name
|
||||
* @param name
|
||||
* @param value
|
||||
* @return {boolean}
|
||||
*/
|
||||
Node.prototype.setAttribute = function (name, value) {
|
||||
if (value === null) {
|
||||
return this.removeAttribute(name);
|
||||
}
|
||||
|
||||
this.element.setAttribute(name, value);
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes and attribute by name
|
||||
* @param name
|
||||
* @return {boolean}
|
||||
*/
|
||||
Node.prototype.removeAttribute = function (name) {
|
||||
this.element.removeAttribute(name);
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Selects the current node
|
||||
* @param value
|
||||
* @return {boolean}
|
||||
*/
|
||||
Node.prototype.select = function (value) {
|
||||
if (value === false && !this.element.parentNode.multiple) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.element.selected = value;
|
||||
this.changed();
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Selects the radio button that has the defined value
|
||||
* @param value
|
||||
* @return {boolean}
|
||||
*/
|
||||
Node.prototype.selectRadioValue = function (value) {
|
||||
if (this.element.value == value) {
|
||||
this.element.checked = true;
|
||||
this.trigger('focus');
|
||||
this.trigger('click');
|
||||
this.changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
var formElements = this.element.form.elements;
|
||||
var name = this.element.getAttribute('name');
|
||||
var element, i;
|
||||
|
||||
var deselectAllRadios = function (elements, radioName) {
|
||||
var inputRadioElement;
|
||||
|
||||
for (i = 0; i < elements.length; i++) {
|
||||
inputRadioElement = elements[i];
|
||||
if (inputRadioElement.tagName.toLowerCase() == 'input' && inputRadioElement.type.toLowerCase() == 'radio' && inputRadioElement.name == radioName) {
|
||||
inputRadioElement.checked = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var radioChange = function (radioElement) {
|
||||
var radioEvent;
|
||||
radioEvent = document.createEvent('HTMLEvents');
|
||||
radioEvent.initEvent('change', true, false);
|
||||
return radioElement.dispatchEvent(radioEvent);
|
||||
};
|
||||
|
||||
var radioClickEvent = function (radioElement, name) {
|
||||
var radioEvent;
|
||||
radioEvent = document.createEvent('MouseEvent');
|
||||
radioEvent.initMouseEvent(name, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
|
||||
return radioElement.dispatchEvent(radioEvent);
|
||||
};
|
||||
|
||||
if (!name) {
|
||||
throw new Poltergeist.BrowserError('The radio button does not have the value "' + value + '"');
|
||||
}
|
||||
|
||||
for (i = 0; i < formElements.length; i++) {
|
||||
element = formElements[i];
|
||||
if (element.tagName.toLowerCase() == 'input' && element.type.toLowerCase() == 'radio' && element.name === name) {
|
||||
if (value === element.value) {
|
||||
deselectAllRadios(formElements, name);
|
||||
element.checked = true;
|
||||
radioClickEvent(element, 'click');
|
||||
radioChange(element);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new Poltergeist.BrowserError('The radio group "' + name + '" does not have an option "' + value + '"');
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks or uncheck a radio option
|
||||
* @param value
|
||||
* @return {boolean}
|
||||
*/
|
||||
Node.prototype.checked = function (value) {
|
||||
//TODO: add error control for the checked stuff
|
||||
this.element.checked = value;
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the element tag name as is, no transformations done
|
||||
* @return {string}
|
||||
*/
|
||||
Node.prototype.tagName = function () {
|
||||
return this.element.tagName;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if the element is visible either by itself of because the parents are visible
|
||||
* @param element
|
||||
* @return {boolean}
|
||||
*/
|
||||
Node.prototype.isVisible = function (element) {
|
||||
var nodeElement = element || this.element;
|
||||
|
||||
if (window.getComputedStyle(nodeElement).display === 'none') {
|
||||
return false;
|
||||
} else if (nodeElement.parentElement) {
|
||||
return this.isVisible(nodeElement.parentElement);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Is the node disabled for operations with it?
|
||||
* @return {boolean}
|
||||
*/
|
||||
Node.prototype.isDisabled = function () {
|
||||
return this.element.disabled || this.element.tagName === 'OPTION' && this.element.parentNode.disabled;
|
||||
};
|
||||
|
||||
/**
|
||||
* Does the node contains the selections
|
||||
* @return {boolean}
|
||||
*/
|
||||
Node.prototype.containsSelection = function () {
|
||||
var selectedNode;
|
||||
|
||||
selectedNode = document.getSelection().focusNode;
|
||||
if (!selectedNode) {
|
||||
return false;
|
||||
}
|
||||
//this magic number is NODE.TEXT_NODE
|
||||
if (selectedNode.nodeType === 3) {
|
||||
selectedNode = selectedNode.parentNode;
|
||||
}
|
||||
|
||||
return this.element.contains(selectedNode);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the offset of the node in relation to the current frame
|
||||
* @return {{top: number, left: number}}
|
||||
*/
|
||||
Node.prototype.frameOffset = function () {
|
||||
var offset, rect, style, win;
|
||||
win = window;
|
||||
offset = {
|
||||
top: 0,
|
||||
left: 0
|
||||
};
|
||||
while (win.frameElement) {
|
||||
rect = win.frameElement.getClientRects()[0];
|
||||
style = win.getComputedStyle(win.frameElement);
|
||||
win = win.parent;
|
||||
offset.top += rect.top + parseInt(style.getPropertyValue("padding-top"), 10);
|
||||
offset.left += rect.left + parseInt(style.getPropertyValue("padding-left"), 10);
|
||||
}
|
||||
return offset;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the object position in relation to the window
|
||||
* @return {{top: *, right: *, left: *, bottom: *, width: *, height: *}}
|
||||
*/
|
||||
Node.prototype.position = function () {
|
||||
var frameOffset, pos, rect;
|
||||
|
||||
rect = this.element.getClientRects()[0];
|
||||
if (!rect) {
|
||||
throw new PoltergeistAgent.ObsoleteNode;
|
||||
}
|
||||
|
||||
frameOffset = this.frameOffset();
|
||||
pos = {
|
||||
top: rect.top + frameOffset.top,
|
||||
right: rect.right + frameOffset.left,
|
||||
left: rect.left + frameOffset.left,
|
||||
bottom: rect.bottom + frameOffset.top,
|
||||
width: rect.width,
|
||||
height: rect.height
|
||||
};
|
||||
|
||||
return pos;
|
||||
};
|
||||
|
||||
/**
|
||||
* Triggers a DOM event related to the node element
|
||||
* @param name
|
||||
* @return {boolean}
|
||||
*/
|
||||
Node.prototype.trigger = function (name) {
|
||||
var event;
|
||||
if (Node.EVENTS.MOUSE.indexOf(name) !== -1) {
|
||||
event = document.createEvent('MouseEvent');
|
||||
event.initMouseEvent(name, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
|
||||
} else if (Node.EVENTS.FOCUS.indexOf(name) !== -1) {
|
||||
event = this.obtainEvent(name);
|
||||
} else if (Node.EVENTS.FORM.indexOf(name) !== -1) {
|
||||
event = this.obtainEvent(name);
|
||||
} else {
|
||||
throw "Unknown event";
|
||||
}
|
||||
return this.element.dispatchEvent(event);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a generic HTMLEvent to be use in the node element
|
||||
* @param name
|
||||
* @return {Event}
|
||||
*/
|
||||
Node.prototype.obtainEvent = function (name) {
|
||||
var event;
|
||||
event = document.createEvent('HTMLEvents');
|
||||
event.initEvent(name, true, true);
|
||||
return event;
|
||||
};
|
||||
|
||||
/**
|
||||
* Does a check to see if the coordinates given
|
||||
* match the node element or some of the parents chain
|
||||
* @param x
|
||||
* @param y
|
||||
* @return {*}
|
||||
*/
|
||||
Node.prototype.mouseEventTest = function (x, y) {
|
||||
var elementForXpath, frameOffset, origEl;
|
||||
|
||||
frameOffset = this.frameOffset();
|
||||
x -= frameOffset.left;
|
||||
y -= frameOffset.top;
|
||||
|
||||
elementForXpath = origEl = document.elementFromPoint(x, y);
|
||||
while (elementForXpath) {
|
||||
if (elementForXpath === this.element) {
|
||||
return {
|
||||
status: 'success'
|
||||
};
|
||||
} else {
|
||||
elementForXpath = elementForXpath.parentNode;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failure',
|
||||
selector: origEl && this.getSelector(origEl)
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the node selector in CSS style (NO xpath)
|
||||
* @param elementForXpath
|
||||
* @return {string}
|
||||
*/
|
||||
Node.prototype.getSelector = function (elementForXpath) {
|
||||
var className, selector, i, len, classNames;
|
||||
|
||||
selector = elementForXpath.tagName !== 'HTML' ? this.getSelector(elementForXpath.parentNode) + ' ' : '';
|
||||
selector += elementForXpath.tagName.toLowerCase();
|
||||
|
||||
if (elementForXpath.id) {
|
||||
selector += "#" + elementForXpath.id;
|
||||
}
|
||||
|
||||
classNames = elementForXpath.classList;
|
||||
for (i = 0, len = classNames.length; i < len; i++) {
|
||||
className = classNames[i];
|
||||
selector += "." + className;
|
||||
}
|
||||
|
||||
return selector;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the key code that represents the character
|
||||
* @param character
|
||||
* @return {number}
|
||||
*/
|
||||
Node.prototype.characterToKeyCode = function (character) {
|
||||
var code, specialKeys;
|
||||
code = character.toUpperCase().charCodeAt(0);
|
||||
specialKeys = {
|
||||
96: 192,
|
||||
45: 189,
|
||||
61: 187,
|
||||
91: 219,
|
||||
93: 221,
|
||||
92: 220,
|
||||
59: 186,
|
||||
39: 222,
|
||||
44: 188,
|
||||
46: 190,
|
||||
47: 191,
|
||||
127: 46,
|
||||
126: 192,
|
||||
33: 49,
|
||||
64: 50,
|
||||
35: 51,
|
||||
36: 52,
|
||||
37: 53,
|
||||
94: 54,
|
||||
38: 55,
|
||||
42: 56,
|
||||
40: 57,
|
||||
41: 48,
|
||||
95: 189,
|
||||
43: 187,
|
||||
123: 219,
|
||||
125: 221,
|
||||
124: 220,
|
||||
58: 186,
|
||||
34: 222,
|
||||
60: 188,
|
||||
62: 190,
|
||||
63: 191
|
||||
};
|
||||
return specialKeys[code] || code;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if one element is equal to other given by its node id
|
||||
* @param other_id
|
||||
* @return {boolean}
|
||||
*/
|
||||
Node.prototype.isDOMEqual = function (other_id) {
|
||||
return this.element === this.agent.get(other_id).element;
|
||||
};
|
||||
|
||||
/**
|
||||
* The following function allows one to pass an element and an XML document to find a unique string XPath expression leading back to that element.
|
||||
* @param element
|
||||
* @return {string}
|
||||
*/
|
||||
Node.prototype.getXPathForElement = function (element) {
|
||||
var elementForXpath = element || this.element;
|
||||
var xpath = '';
|
||||
var pos, tempitem2;
|
||||
|
||||
while (elementForXpath !== document.documentElement) {
|
||||
pos = 0;
|
||||
tempitem2 = elementForXpath;
|
||||
while (tempitem2) {
|
||||
if (tempitem2.nodeType === 1 && tempitem2.nodeName === elementForXpath.nodeName) { // If it is ELEMENT_NODE of the same name
|
||||
pos += 1;
|
||||
}
|
||||
tempitem2 = tempitem2.previousSibling;
|
||||
}
|
||||
|
||||
xpath = "*[name()='" + elementForXpath.nodeName + "' and namespace-uri()='" + (elementForXpath.namespaceURI === null ? '' : elementForXpath.namespaceURI) + "'][" + pos + ']' + '/' + xpath;
|
||||
|
||||
elementForXpath = elementForXpath.parentNode;
|
||||
}
|
||||
|
||||
xpath = '/*' + "[name()='" + document.documentElement.nodeName + "' and namespace-uri()='" + (elementForXpath.namespaceURI === null ? '' : elementForXpath.namespaceURI) + "']" + '/' + xpath;
|
||||
xpath = xpath.replace(/\/$/, '');
|
||||
return xpath;
|
||||
};
|
||||
|
||||
/**
|
||||
* Deselect all the options for this element
|
||||
*/
|
||||
Node.prototype.deselectAllOptions = function () {
|
||||
//TODO: error control when the node is not a select node
|
||||
var i, l = this.element.options.length;
|
||||
for (i = 0; i < l; i++) {
|
||||
this.element.options[i].selected = false;
|
||||
}
|
||||
};
|
||||
|
||||
return Node;
|
||||
|
||||
})();
|
||||
|
||||
window.__poltergeist = new PoltergeistAgent;
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
return console.log('__DOMContentLoaded');
|
||||
});
|
||||
|
||||
window.confirm = function (message) {
|
||||
return true;
|
||||
};
|
||||
|
||||
window.prompt = function (message, _default) {
|
||||
return _default || null;
|
||||
};
|
1293
vendor/jcalderonzumba/gastonjs/src/Client/browser.js
vendored
Normal file
1293
vendor/jcalderonzumba/gastonjs/src/Client/browser.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
29
vendor/jcalderonzumba/gastonjs/src/Client/main.js
vendored
Normal file
29
vendor/jcalderonzumba/gastonjs/src/Client/main.js
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
var Poltergeist, system, _ref, _ref1, _ref2;
|
||||
|
||||
//Inheritance tool
|
||||
phantom.injectJs("" + phantom.libraryPath + "/Tools/inherit.js");
|
||||
|
||||
//Poltergeist main object
|
||||
phantom.injectJs("" + phantom.libraryPath + "/poltergeist.js");
|
||||
|
||||
//Errors that are controller in the poltergeist code
|
||||
phantom.injectJs("" + phantom.libraryPath + "/Errors/error.js");
|
||||
phantom.injectJs("" + phantom.libraryPath + "/Errors/obsolete_node.js");
|
||||
phantom.injectJs("" + phantom.libraryPath + "/Errors/invalid_selector.js");
|
||||
phantom.injectJs("" + phantom.libraryPath + "/Errors/frame_not_found.js");
|
||||
phantom.injectJs("" + phantom.libraryPath + "/Errors/mouse_event_failed.js");
|
||||
phantom.injectJs("" + phantom.libraryPath + "/Errors/javascript_error.js");
|
||||
phantom.injectJs("" + phantom.libraryPath + "/Errors/browser_error.js");
|
||||
phantom.injectJs("" + phantom.libraryPath + "/Errors/status_fail_error.js");
|
||||
phantom.injectJs("" + phantom.libraryPath + "/Errors/no_such_window_error.js");
|
||||
|
||||
//web server to control the commands
|
||||
phantom.injectJs("" + phantom.libraryPath + "/Server/server.js");
|
||||
|
||||
phantom.injectJs("" + phantom.libraryPath + "/web_page.js");
|
||||
phantom.injectJs("" + phantom.libraryPath + "/node.js");
|
||||
phantom.injectJs("" + phantom.libraryPath + "/browser.js");
|
||||
|
||||
system = require('system');
|
||||
|
||||
new Poltergeist(system.args[1], system.args[2], system.args[3]);
|
161
vendor/jcalderonzumba/gastonjs/src/Client/node.js
vendored
Normal file
161
vendor/jcalderonzumba/gastonjs/src/Client/node.js
vendored
Normal file
|
@ -0,0 +1,161 @@
|
|||
var __slice = [].slice;
|
||||
|
||||
Poltergeist.Node = (function () {
|
||||
var name, _fn, _i, _len, _ref;
|
||||
var xpathStringLiteral;
|
||||
|
||||
Node.DELEGATES = ['allText', 'visibleText', 'getAttribute', 'value', 'set', 'checked',
|
||||
'setAttribute', 'isObsolete', 'removeAttribute', 'isMultiple',
|
||||
'select', 'tagName', 'find', 'getAttributes', 'isVisible',
|
||||
'position', 'trigger', 'input', 'parentId', 'parentIds', 'mouseEventTest',
|
||||
'scrollIntoView', 'isDOMEqual', 'isDisabled', 'deleteText', 'selectRadioValue',
|
||||
'containsSelection', 'allHTML', 'changed', 'getXPathForElement', 'deselectAllOptions'];
|
||||
|
||||
function Node(page, id) {
|
||||
this.page = page;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent Node of this Node
|
||||
* @return {Poltergeist.Node}
|
||||
*/
|
||||
Node.prototype.parent = function () {
|
||||
return new Poltergeist.Node(this.page, this.parentId());
|
||||
};
|
||||
|
||||
_ref = Node.DELEGATES;
|
||||
|
||||
_fn = function (name) {
|
||||
return Node.prototype[name] = function () {
|
||||
var args = [];
|
||||
if (arguments.length >= 1) {
|
||||
args = __slice.call(arguments, 0)
|
||||
}
|
||||
return this.page.nodeCall(this.id, name, args);
|
||||
};
|
||||
};
|
||||
|
||||
//Adding all the delegates from the agent Node to this Node
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
name = _ref[_i];
|
||||
_fn(name);
|
||||
}
|
||||
|
||||
xpathStringLiteral = function (s) {
|
||||
if (s.indexOf('"') === -1)
|
||||
return '"' + s + '"';
|
||||
if (s.indexOf("'") === -1)
|
||||
return "'" + s + "'";
|
||||
return 'concat("' + s.replace(/"/g, '",\'"\',"') + '")';
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets an x,y position tailored for mouse event actions
|
||||
* @return {{x, y}}
|
||||
*/
|
||||
Node.prototype.mouseEventPosition = function () {
|
||||
var middle, pos, viewport;
|
||||
|
||||
viewport = this.page.viewportSize();
|
||||
pos = this.position();
|
||||
middle = function (start, end, size) {
|
||||
return start + ((Math.min(end, size) - start) / 2);
|
||||
};
|
||||
|
||||
return {
|
||||
x: middle(pos.left, pos.right, viewport.width),
|
||||
y: middle(pos.top, pos.bottom, viewport.height)
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Executes a phantomjs native mouse event
|
||||
* @param name
|
||||
* @return {{x, y}}
|
||||
*/
|
||||
Node.prototype.mouseEvent = function (name) {
|
||||
var pos, test;
|
||||
|
||||
this.scrollIntoView();
|
||||
pos = this.mouseEventPosition();
|
||||
test = this.mouseEventTest(pos.x, pos.y);
|
||||
|
||||
if (test.status === 'success') {
|
||||
if (name === 'rightclick') {
|
||||
this.page.mouseEvent('click', pos.x, pos.y, 'right');
|
||||
this.trigger('contextmenu');
|
||||
} else {
|
||||
this.page.mouseEvent(name, pos.x, pos.y);
|
||||
}
|
||||
return pos;
|
||||
} else {
|
||||
throw new Poltergeist.MouseEventFailed(name, test.selector, pos);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Executes a mouse based drag from one node to another
|
||||
* @param other
|
||||
* @return {{x, y}}
|
||||
*/
|
||||
Node.prototype.dragTo = function (other) {
|
||||
var otherPosition, position;
|
||||
|
||||
this.scrollIntoView();
|
||||
position = this.mouseEventPosition();
|
||||
otherPosition = other.mouseEventPosition();
|
||||
this.page.mouseEvent('mousedown', position.x, position.y);
|
||||
return this.page.mouseEvent('mouseup', otherPosition.x, otherPosition.y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if one node is equal to another
|
||||
* @param other
|
||||
* @return {boolean}
|
||||
*/
|
||||
Node.prototype.isEqual = function (other) {
|
||||
return this.page === other.page && this.isDOMEqual(other.id);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The value to select
|
||||
* @param value
|
||||
* @param multiple
|
||||
*/
|
||||
Node.prototype.select_option = function (value, multiple) {
|
||||
var tagName = this.tagName().toLowerCase();
|
||||
|
||||
if (tagName === "select") {
|
||||
var escapedOption = xpathStringLiteral(value);
|
||||
// The value of an option is the normalized version of its text when it has no value attribute
|
||||
var optionQuery = ".//option[@value = " + escapedOption + " or (not(@value) and normalize-space(.) = " + escapedOption + ")]";
|
||||
var ids = this.find("xpath", optionQuery);
|
||||
var polterNode = this.page.get(ids[0]);
|
||||
|
||||
if (multiple || !this.getAttribute('multiple')) {
|
||||
if (!polterNode.getAttribute('selected')) {
|
||||
polterNode.select(value);
|
||||
this.trigger('click');
|
||||
this.input();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
this.deselectAllOptions();
|
||||
polterNode.select(value);
|
||||
this.trigger('click');
|
||||
this.input();
|
||||
return true;
|
||||
} else if (tagName === "input" && this.getAttribute("type").toLowerCase() === "radio") {
|
||||
return this.selectRadioValue(value);
|
||||
}
|
||||
|
||||
throw new Poltergeist.BrowserError("The element is not a select or radio input");
|
||||
|
||||
};
|
||||
|
||||
return Node;
|
||||
|
||||
}).call(this);
|
77
vendor/jcalderonzumba/gastonjs/src/Client/poltergeist.js
vendored
Normal file
77
vendor/jcalderonzumba/gastonjs/src/Client/poltergeist.js
vendored
Normal file
|
@ -0,0 +1,77 @@
|
|||
Poltergeist = (function () {
|
||||
|
||||
/**
|
||||
* The MAIN class of the project
|
||||
* @param port
|
||||
* @param width
|
||||
* @param height
|
||||
* @constructor
|
||||
*/
|
||||
function Poltergeist(port, width, height) {
|
||||
var self;
|
||||
this.browser = new Poltergeist.Browser(this, width, height);
|
||||
|
||||
this.commandServer = new Poltergeist.Server(this, port);
|
||||
this.commandServer.start();
|
||||
|
||||
self = this;
|
||||
|
||||
phantom.onError = function (message, stack) {
|
||||
return self.onError(message, stack);
|
||||
};
|
||||
|
||||
this.running = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to execute a command send by a client and returns the command response
|
||||
* or error if something happened
|
||||
* @param command
|
||||
* @param serverResponse
|
||||
* @return {boolean}
|
||||
*/
|
||||
Poltergeist.prototype.serverRunCommand = function (command, serverResponse) {
|
||||
var error;
|
||||
this.running = true;
|
||||
try {
|
||||
return this.browser.serverRunCommand(command, serverResponse);
|
||||
} catch (_error) {
|
||||
error = _error;
|
||||
if (error instanceof Poltergeist.Error) {
|
||||
return this.serverSendError(error, serverResponse);
|
||||
}
|
||||
return this.serverSendError(new Poltergeist.BrowserError(error.toString(), error.stack), serverResponse);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sends error back to the client
|
||||
* @param error
|
||||
* @param serverResponse
|
||||
* @return {boolean}
|
||||
*/
|
||||
Poltergeist.prototype.serverSendError = function (error, serverResponse) {
|
||||
var errorObject;
|
||||
errorObject = {
|
||||
error: {
|
||||
name: error.name || 'Generic',
|
||||
args: error.args && error.args() || [error.toString()]
|
||||
}
|
||||
};
|
||||
return this.commandServer.sendError(serverResponse, 500, errorObject);
|
||||
};
|
||||
|
||||
/**
|
||||
* Send the response back to the client
|
||||
* @param response Data to send to the client
|
||||
* @param serverResponse Phantomjs response object associated to the client request
|
||||
* @return {boolean}
|
||||
*/
|
||||
Poltergeist.prototype.serverSendResponse = function (response, serverResponse) {
|
||||
return this.commandServer.send(serverResponse, {response: response});
|
||||
};
|
||||
|
||||
return Poltergeist;
|
||||
})();
|
||||
|
||||
window.Poltergeist = Poltergeist;
|
829
vendor/jcalderonzumba/gastonjs/src/Client/web_page.js
vendored
Normal file
829
vendor/jcalderonzumba/gastonjs/src/Client/web_page.js
vendored
Normal file
|
@ -0,0 +1,829 @@
|
|||
var __slice = [].slice;
|
||||
var __indexOf = [].indexOf || function (item) {
|
||||
for (var i = 0, l = this.length; i < l; i++) {
|
||||
if (i in this && this[i] === item) return i;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
Poltergeist.WebPage = (function () {
|
||||
var command, delegate, commandFunctionBind, delegateFunctionBind, i, j, commandsLength, delegatesRefLength, commandsRef, delegatesRef,
|
||||
_this = this;
|
||||
|
||||
//Native or not webpage callbacks
|
||||
WebPage.CALLBACKS = ['onAlert', 'onConsoleMessage', 'onLoadFinished', 'onInitialized', 'onLoadStarted', 'onResourceRequested',
|
||||
'onResourceReceived', 'onError', 'onNavigationRequested', 'onUrlChanged', 'onPageCreated', 'onClosing'];
|
||||
|
||||
// Delegates the execution to the phantomjs page native functions but directly available in the WebPage object
|
||||
WebPage.DELEGATES = ['open', 'sendEvent', 'uploadFile', 'release', 'render', 'renderBase64', 'goBack', 'goForward', 'reload'];
|
||||
|
||||
//Commands to execute on behalf of the browser but on the current page
|
||||
WebPage.COMMANDS = ['currentUrl', 'find', 'nodeCall', 'documentSize', 'beforeUpload', 'afterUpload', 'clearLocalStorage'];
|
||||
|
||||
WebPage.EXTENSIONS = [];
|
||||
|
||||
function WebPage(nativeWebPage) {
|
||||
var callback, i, callBacksLength, callBacksRef;
|
||||
|
||||
//Lets create the native phantomjs webpage
|
||||
if (nativeWebPage === null || typeof nativeWebPage == "undefined") {
|
||||
this._native = require('webpage').create();
|
||||
} else {
|
||||
this._native = nativeWebPage;
|
||||
}
|
||||
|
||||
this.id = 0;
|
||||
this.source = null;
|
||||
this.closed = false;
|
||||
this.state = 'default';
|
||||
this.urlBlacklist = [];
|
||||
this.frames = [];
|
||||
this.errors = [];
|
||||
this._networkTraffic = {};
|
||||
this._tempHeaders = {};
|
||||
this._blockedUrls = [];
|
||||
|
||||
callBacksRef = WebPage.CALLBACKS;
|
||||
for (i = 0, callBacksLength = callBacksRef.length; i < callBacksLength; i++) {
|
||||
callback = callBacksRef[i];
|
||||
this.bindCallback(callback);
|
||||
}
|
||||
}
|
||||
|
||||
//Bind the commands we can run from the browser to the current page
|
||||
commandsRef = WebPage.COMMANDS;
|
||||
commandFunctionBind = function (command) {
|
||||
return WebPage.prototype[command] = function () {
|
||||
var args;
|
||||
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
||||
return this.runCommand(command, args);
|
||||
};
|
||||
};
|
||||
for (i = 0, commandsLength = commandsRef.length; i < commandsLength; i++) {
|
||||
command = commandsRef[i];
|
||||
commandFunctionBind(command);
|
||||
}
|
||||
|
||||
//Delegates bind applications
|
||||
delegatesRef = WebPage.DELEGATES;
|
||||
delegateFunctionBind = function (delegate) {
|
||||
return WebPage.prototype[delegate] = function () {
|
||||
return this._native[delegate].apply(this._native, arguments);
|
||||
};
|
||||
};
|
||||
for (j = 0, delegatesRefLength = delegatesRef.length; j < delegatesRefLength; j++) {
|
||||
delegate = delegatesRef[j];
|
||||
delegateFunctionBind(delegate);
|
||||
}
|
||||
|
||||
/**
|
||||
* This callback is invoked after the web page is created but before a URL is loaded.
|
||||
* The callback may be used to change global objects.
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.onInitializedNative = function () {
|
||||
this.id += 1;
|
||||
this.source = null;
|
||||
this.injectAgent();
|
||||
this.removeTempHeaders();
|
||||
return this.setScrollPosition({
|
||||
left: 0,
|
||||
top: 0
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* This callback is invoked when the WebPage object is being closed,
|
||||
* either via page.close in the PhantomJS outer space or via window.close in the page's client-side.
|
||||
* @return {boolean}
|
||||
*/
|
||||
WebPage.prototype.onClosingNative = function () {
|
||||
this.handle = null;
|
||||
return this.closed = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* This callback is invoked when there is a JavaScript console message on the web page.
|
||||
* The callback may accept up to three arguments: the string for the message, the line number, and the source identifier.
|
||||
* @param message
|
||||
* @param line
|
||||
* @param sourceId
|
||||
* @return {boolean}
|
||||
*/
|
||||
WebPage.prototype.onConsoleMessageNative = function (message, line, sourceId) {
|
||||
if (message === '__DOMContentLoaded') {
|
||||
this.source = this._native.content;
|
||||
return false;
|
||||
}
|
||||
console.log(message);
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* This callback is invoked when the page starts the loading. There is no argument passed to the callback.
|
||||
* @return {number}
|
||||
*/
|
||||
WebPage.prototype.onLoadStartedNative = function () {
|
||||
this.state = 'loading';
|
||||
return this.requestId = this.lastRequestId;
|
||||
};
|
||||
|
||||
/**
|
||||
* This callback is invoked when the page finishes the loading.
|
||||
* It may accept a single argument indicating the page's status: 'success' if no network errors occurred, otherwise 'fail'.
|
||||
* @param status
|
||||
* @return {string}
|
||||
*/
|
||||
WebPage.prototype.onLoadFinishedNative = function (status) {
|
||||
this.status = status;
|
||||
this.state = 'default';
|
||||
|
||||
if (this.source === null || typeof this.source == "undefined") {
|
||||
this.source = this._native.content;
|
||||
} else {
|
||||
this.source = this._native.content;
|
||||
}
|
||||
|
||||
return this.source;
|
||||
};
|
||||
|
||||
/**
|
||||
* This callback is invoked when there is a JavaScript execution error.
|
||||
* It is a good way to catch problems when evaluating a script in the web page context.
|
||||
* The arguments passed to the callback are the error message and the stack trace [as an Array].
|
||||
* @param message
|
||||
* @param stack
|
||||
* @return {Number}
|
||||
*/
|
||||
WebPage.prototype.onErrorNative = function (message, stack) {
|
||||
var stackString;
|
||||
|
||||
stackString = message;
|
||||
stack.forEach(function (frame) {
|
||||
stackString += "\n";
|
||||
stackString += " at " + frame.file + ":" + frame.line;
|
||||
if (frame["function"] && frame["function"] !== '') {
|
||||
return stackString += " in " + frame["function"];
|
||||
}
|
||||
});
|
||||
|
||||
return this.errors.push({
|
||||
message: message,
|
||||
stack: stackString
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* This callback is invoked when the page requests a resource.
|
||||
* The first argument to the callback is the requestData metadata object.
|
||||
* The second argument is the networkRequest object itself.
|
||||
* @param requestData
|
||||
* @param networkRequest
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.onResourceRequestedNative = function (requestData, networkRequest) {
|
||||
var abort;
|
||||
|
||||
abort = this.urlBlacklist.some(function (blacklistedUrl) {
|
||||
return requestData.url.indexOf(blacklistedUrl) !== -1;
|
||||
});
|
||||
|
||||
if (abort) {
|
||||
if (this._blockedUrls.indexOf(requestData.url) === -1) {
|
||||
this._blockedUrls.push(requestData.url);
|
||||
}
|
||||
//TODO: check this, as it raises onResourceError
|
||||
return networkRequest.abort();
|
||||
}
|
||||
|
||||
this.lastRequestId = requestData.id;
|
||||
if (requestData.url === this.redirectURL) {
|
||||
this.redirectURL = null;
|
||||
this.requestId = requestData.id;
|
||||
}
|
||||
|
||||
return this._networkTraffic[requestData.id] = {
|
||||
request: requestData,
|
||||
responseParts: []
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* This callback is invoked when a resource requested by the page is received.
|
||||
* The only argument to the callback is the response metadata object.
|
||||
* @param response
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.onResourceReceivedNative = function (response) {
|
||||
var networkTrafficElement;
|
||||
|
||||
if ((networkTrafficElement = this._networkTraffic[response.id]) != null) {
|
||||
networkTrafficElement.responseParts.push(response);
|
||||
}
|
||||
|
||||
if (this.requestId === response.id) {
|
||||
if (response.redirectURL) {
|
||||
return this.redirectURL = response.redirectURL;
|
||||
}
|
||||
|
||||
this.statusCode = response.status;
|
||||
return this._responseHeaders = response.headers;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject the poltergeist agent into the webpage
|
||||
* @return {Array}
|
||||
*/
|
||||
WebPage.prototype.injectAgent = function () {
|
||||
var extension, isAgentInjected, i, extensionsRefLength, extensionsRef, injectionResults;
|
||||
|
||||
isAgentInjected = this["native"]().evaluate(function () {
|
||||
return typeof window.__poltergeist;
|
||||
});
|
||||
|
||||
if (isAgentInjected === "undefined") {
|
||||
this["native"]().injectJs("" + phantom.libraryPath + "/agent.js");
|
||||
extensionsRef = WebPage.EXTENSIONS;
|
||||
injectionResults = [];
|
||||
for (i = 0, extensionsRefLength = extensionsRef.length; i < extensionsRefLength; i++) {
|
||||
extension = extensionsRef[i];
|
||||
injectionResults.push(this["native"]().injectJs(extension));
|
||||
}
|
||||
return injectionResults;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Injects a Javascript file extension into the
|
||||
* @param file
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.injectExtension = function (file) {
|
||||
//TODO: add error control, for example, check if file already in the extensions array, check if the file exists, etc.
|
||||
WebPage.EXTENSIONS.push(file);
|
||||
return this["native"]().injectJs(file);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the native phantomjs webpage object
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype["native"] = function () {
|
||||
if (this.closed) {
|
||||
throw new Poltergeist.NoSuchWindowError;
|
||||
}
|
||||
|
||||
return this._native;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the current page window name
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.windowName = function () {
|
||||
return this["native"]().windowName;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the keyCode of a given key as set in the phantomjs values
|
||||
* @param name
|
||||
* @return {number}
|
||||
*/
|
||||
WebPage.prototype.keyCode = function (name) {
|
||||
return this["native"]().event.key[name];
|
||||
};
|
||||
|
||||
/**
|
||||
* Waits for the page to reach a certain state
|
||||
* @param state
|
||||
* @param callback
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.waitState = function (state, callback) {
|
||||
var self = this;
|
||||
if (this.state === state) {
|
||||
return callback.call();
|
||||
} else {
|
||||
return setTimeout((function () {
|
||||
return self.waitState(state, callback);
|
||||
}), 100);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the browser header related to basic authentication protocol
|
||||
* @param user
|
||||
* @param password
|
||||
* @return {boolean}
|
||||
*/
|
||||
WebPage.prototype.setHttpAuth = function (user, password) {
|
||||
var allHeaders = this.getCustomHeaders();
|
||||
|
||||
if (user === false || password === false) {
|
||||
if (allHeaders.hasOwnProperty("Authorization")) {
|
||||
delete allHeaders["Authorization"];
|
||||
}
|
||||
this.setCustomHeaders(allHeaders);
|
||||
return true;
|
||||
}
|
||||
|
||||
var userName = user || "";
|
||||
var userPassword = password || "";
|
||||
|
||||
allHeaders["Authorization"] = "Basic " + btoa(userName + ":" + userPassword);
|
||||
this.setCustomHeaders(allHeaders);
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns all the network traffic associated to the rendering of this page
|
||||
* @return {{}}
|
||||
*/
|
||||
WebPage.prototype.networkTraffic = function () {
|
||||
return this._networkTraffic;
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears all the recorded network traffic related to the current page
|
||||
* @return {{}}
|
||||
*/
|
||||
WebPage.prototype.clearNetworkTraffic = function () {
|
||||
return this._networkTraffic = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the blocked urls that the page will not load
|
||||
* @return {Array}
|
||||
*/
|
||||
WebPage.prototype.blockedUrls = function () {
|
||||
return this._blockedUrls;
|
||||
};
|
||||
|
||||
/**
|
||||
* Clean all the urls that should not be loaded
|
||||
* @return {Array}
|
||||
*/
|
||||
WebPage.prototype.clearBlockedUrls = function () {
|
||||
return this._blockedUrls = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* This property stores the content of the web page's currently active frame
|
||||
* (which may or may not be the main frame), enclosed in an HTML/XML element.
|
||||
* @return {string}
|
||||
*/
|
||||
WebPage.prototype.content = function () {
|
||||
return this["native"]().frameContent;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the current active frame title
|
||||
* @return {string}
|
||||
*/
|
||||
WebPage.prototype.title = function () {
|
||||
return this["native"]().frameTitle;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns if possible the frame url of the frame given by name
|
||||
* @param frameName
|
||||
* @return {string}
|
||||
*/
|
||||
WebPage.prototype.frameUrl = function (frameName) {
|
||||
var query;
|
||||
|
||||
query = function (frameName) {
|
||||
var iframeReference;
|
||||
if ((iframeReference = document.querySelector("iframe[name='" + frameName + "']")) != null) {
|
||||
return iframeReference.src;
|
||||
}
|
||||
return void 0;
|
||||
};
|
||||
|
||||
return this.evaluate(query, frameName);
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove the errors caught on the page
|
||||
* @return {Array}
|
||||
*/
|
||||
WebPage.prototype.clearErrors = function () {
|
||||
return this.errors = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the response headers associated to this page
|
||||
* @return {{}}
|
||||
*/
|
||||
WebPage.prototype.responseHeaders = function () {
|
||||
var headers;
|
||||
headers = {};
|
||||
this._responseHeaders.forEach(function (item) {
|
||||
return headers[item.name] = item.value;
|
||||
});
|
||||
return headers;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get Cookies visible to the current URL (though, for setting, use of page.addCookie is preferred).
|
||||
* This array will be pre-populated by any existing Cookie data visible to this URL that is stored in the CookieJar, if any.
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.cookies = function () {
|
||||
return this["native"]().cookies;
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete any Cookies visible to the current URL with a 'name' property matching cookieName.
|
||||
* Returns true if successfully deleted, otherwise false.
|
||||
* @param name
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.deleteCookie = function (name) {
|
||||
return this["native"]().deleteCookie(name);
|
||||
};
|
||||
|
||||
/**
|
||||
* This property gets the size of the viewport for the layout process.
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.viewportSize = function () {
|
||||
return this["native"]().viewportSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* This property sets the size of the viewport for the layout process.
|
||||
* @param size
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.setViewportSize = function (size) {
|
||||
return this["native"]().viewportSize = size;
|
||||
};
|
||||
|
||||
/**
|
||||
* This property specifies the scaling factor for the page.render and page.renderBase64 functions.
|
||||
* @param zoomFactor
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.setZoomFactor = function (zoomFactor) {
|
||||
return this["native"]().zoomFactor = zoomFactor;
|
||||
};
|
||||
|
||||
/**
|
||||
* This property defines the size of the web page when rendered as a PDF.
|
||||
* See: http://phantomjs.org/api/webpage/property/paper-size.html
|
||||
* @param size
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.setPaperSize = function (size) {
|
||||
return this["native"]().paperSize = size;
|
||||
};
|
||||
|
||||
/**
|
||||
* This property gets the scroll position of the web page.
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.scrollPosition = function () {
|
||||
return this["native"]().scrollPosition;
|
||||
};
|
||||
|
||||
/**
|
||||
* This property defines the scroll position of the web page.
|
||||
* @param pos
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.setScrollPosition = function (pos) {
|
||||
return this["native"]().scrollPosition = pos;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This property defines the rectangular area of the web page to be rasterized when page.render is invoked.
|
||||
* If no clipping rectangle is set, page.render will process the entire web page.
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.clipRect = function () {
|
||||
return this["native"]().clipRect;
|
||||
};
|
||||
|
||||
/**
|
||||
* This property defines the rectangular area of the web page to be rasterized when page.render is invoked.
|
||||
* If no clipping rectangle is set, page.render will process the entire web page.
|
||||
* @param rect
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.setClipRect = function (rect) {
|
||||
return this["native"]().clipRect = rect;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the size of an element given by a selector and its position relative to the viewport.
|
||||
* @param selector
|
||||
* @return {Object}
|
||||
*/
|
||||
WebPage.prototype.elementBounds = function (selector) {
|
||||
return this["native"]().evaluate(function (selector) {
|
||||
return document.querySelector(selector).getBoundingClientRect();
|
||||
}, selector);
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines the user agent sent to server when the web page requests resources.
|
||||
* @param userAgent
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.setUserAgent = function (userAgent) {
|
||||
return this["native"]().settings.userAgent = userAgent;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the additional HTTP request headers that will be sent to the server for EVERY request.
|
||||
* @return {{}}
|
||||
*/
|
||||
WebPage.prototype.getCustomHeaders = function () {
|
||||
return this["native"]().customHeaders;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the additional HTTP request headers that will be sent to the server for EVERY request.
|
||||
* @param headers
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.setCustomHeaders = function (headers) {
|
||||
return this["native"]().customHeaders = headers;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a one time only request header, after being used it will be deleted
|
||||
* @param header
|
||||
* @return {Array}
|
||||
*/
|
||||
WebPage.prototype.addTempHeader = function (header) {
|
||||
var name, value, tempHeaderResult;
|
||||
tempHeaderResult = [];
|
||||
for (name in header) {
|
||||
if (header.hasOwnProperty(name)) {
|
||||
value = header[name];
|
||||
tempHeaderResult.push(this._tempHeaders[name] = value);
|
||||
}
|
||||
}
|
||||
return tempHeaderResult;
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove the temporary headers we have set via addTempHeader
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.removeTempHeaders = function () {
|
||||
var allHeaders, name, value, tempHeadersRef;
|
||||
allHeaders = this.getCustomHeaders();
|
||||
tempHeadersRef = this._tempHeaders;
|
||||
for (name in tempHeadersRef) {
|
||||
if (tempHeadersRef.hasOwnProperty(name)) {
|
||||
value = tempHeadersRef[name];
|
||||
delete allHeaders[name];
|
||||
}
|
||||
}
|
||||
|
||||
return this.setCustomHeaders(allHeaders);
|
||||
};
|
||||
|
||||
/**
|
||||
* If possible switch to the frame given by name
|
||||
* @param name
|
||||
* @return {boolean}
|
||||
*/
|
||||
WebPage.prototype.pushFrame = function (name) {
|
||||
if (this["native"]().switchToFrame(name)) {
|
||||
this.frames.push(name);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Switch to parent frame, use with caution:
|
||||
* popFrame assumes you are in frame, pop frame not being in a frame
|
||||
* leaves unexpected behaviour
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.popFrame = function () {
|
||||
//TODO: add some error control here, some way to check we are in a frame or not
|
||||
this.frames.pop();
|
||||
return this["native"]().switchToParentFrame();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the webpage dimensions
|
||||
* @return {{top: *, bottom: *, left: *, right: *, viewport: *, document: {height: number, width: number}}}
|
||||
*/
|
||||
WebPage.prototype.dimensions = function () {
|
||||
var scroll, viewport;
|
||||
scroll = this.scrollPosition();
|
||||
viewport = this.viewportSize();
|
||||
return {
|
||||
top: scroll.top,
|
||||
bottom: scroll.top + viewport.height,
|
||||
left: scroll.left,
|
||||
right: scroll.left + viewport.width,
|
||||
viewport: viewport,
|
||||
document: this.documentSize()
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns webpage dimensions that are valid
|
||||
* @return {{top: *, bottom: *, left: *, right: *, viewport: *, document: {height: number, width: number}}}
|
||||
*/
|
||||
WebPage.prototype.validatedDimensions = function () {
|
||||
var dimensions, documentDimensions;
|
||||
|
||||
dimensions = this.dimensions();
|
||||
documentDimensions = dimensions.document;
|
||||
|
||||
if (dimensions.right > documentDimensions.width) {
|
||||
dimensions.left = Math.max(0, dimensions.left - (dimensions.right - documentDimensions.width));
|
||||
dimensions.right = documentDimensions.width;
|
||||
}
|
||||
|
||||
if (dimensions.bottom > documentDimensions.height) {
|
||||
dimensions.top = Math.max(0, dimensions.top - (dimensions.bottom - documentDimensions.height));
|
||||
dimensions.bottom = documentDimensions.height;
|
||||
}
|
||||
|
||||
this.setScrollPosition({
|
||||
left: dimensions.left,
|
||||
top: dimensions.top
|
||||
});
|
||||
|
||||
return dimensions;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a Poltergeist.Node given by an id
|
||||
* @param id
|
||||
* @return {Poltergeist.Node}
|
||||
*/
|
||||
WebPage.prototype.get = function (id) {
|
||||
return new Poltergeist.Node(this, id);
|
||||
};
|
||||
|
||||
/**
|
||||
* Executes a phantomjs mouse event, for more info check: http://phantomjs.org/api/webpage/method/send-event.html
|
||||
* @param name
|
||||
* @param x
|
||||
* @param y
|
||||
* @param button
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.mouseEvent = function (name, x, y, button) {
|
||||
if (button == null) {
|
||||
button = 'left';
|
||||
}
|
||||
this.sendEvent('mousemove', x, y);
|
||||
return this.sendEvent(name, x, y, button);
|
||||
};
|
||||
|
||||
/**
|
||||
* Evaluates a javascript and returns the evaluation of such script
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.evaluate = function () {
|
||||
var args, fn;
|
||||
fn = arguments[0];
|
||||
args = [];
|
||||
|
||||
if (2 <= arguments.length) {
|
||||
args = __slice.call(arguments, 1);
|
||||
}
|
||||
|
||||
this.injectAgent();
|
||||
return JSON.parse(this.sanitize(this["native"]().evaluate("function() { return PoltergeistAgent.stringify(" + (this.stringifyCall(fn, args)) + ") }")));
|
||||
};
|
||||
|
||||
/**
|
||||
* Does some string sanitation prior parsing
|
||||
* @param potentialString
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.sanitize = function (potentialString) {
|
||||
if (typeof potentialString === "string") {
|
||||
return potentialString.replace("\n", "\\n").replace("\r", "\\r");
|
||||
}
|
||||
|
||||
return potentialString;
|
||||
};
|
||||
|
||||
/**
|
||||
* Executes a script into the current page scope
|
||||
* @param script
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.executeScript = function (script) {
|
||||
return this["native"]().evaluateJavaScript(script);
|
||||
};
|
||||
|
||||
/**
|
||||
* Executes a script via phantomjs evaluation
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.execute = function () {
|
||||
var args, fn;
|
||||
|
||||
fn = arguments[0];
|
||||
args = [];
|
||||
|
||||
if (2 <= arguments.length) {
|
||||
args = __slice.call(arguments, 1);
|
||||
}
|
||||
|
||||
return this["native"]().evaluate("function() { " + (this.stringifyCall(fn, args)) + " }");
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper methods to do script evaluation and execution
|
||||
* @param fn
|
||||
* @param args
|
||||
* @return {string}
|
||||
*/
|
||||
WebPage.prototype.stringifyCall = function (fn, args) {
|
||||
if (args.length === 0) {
|
||||
return "(" + (fn.toString()) + ")()";
|
||||
}
|
||||
|
||||
return "(" + (fn.toString()) + ").apply(this, JSON.parse(" + (JSON.stringify(JSON.stringify(args))) + "))";
|
||||
};
|
||||
|
||||
/**
|
||||
* Binds callbacks to their respective Native implementations
|
||||
* @param name
|
||||
* @return {Function}
|
||||
*/
|
||||
WebPage.prototype.bindCallback = function (name) {
|
||||
var self;
|
||||
self = this;
|
||||
|
||||
return this["native"]()[name] = function () {
|
||||
var result;
|
||||
if (self[name + 'Native'] != null) {
|
||||
result = self[name + 'Native'].apply(self, arguments);
|
||||
}
|
||||
if (result !== false && (self[name] != null)) {
|
||||
return self[name].apply(self, arguments);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Runs a command delegating to the PoltergeistAgent
|
||||
* @param name
|
||||
* @param args
|
||||
* @return {*}
|
||||
*/
|
||||
WebPage.prototype.runCommand = function (name, args) {
|
||||
var method, result, selector;
|
||||
|
||||
result = this.evaluate(function (name, args) {
|
||||
return window.__poltergeist.externalCall(name, args);
|
||||
}, name, args);
|
||||
|
||||
if (result !== null) {
|
||||
if (result.error != null) {
|
||||
switch (result.error.message) {
|
||||
case 'PoltergeistAgent.ObsoleteNode':
|
||||
throw new Poltergeist.ObsoleteNode;
|
||||
break;
|
||||
case 'PoltergeistAgent.InvalidSelector':
|
||||
method = args[0];
|
||||
selector = args[1];
|
||||
throw new Poltergeist.InvalidSelector(method, selector);
|
||||
break;
|
||||
default:
|
||||
throw new Poltergeist.BrowserError(result.error.message, result.error.stack);
|
||||
}
|
||||
} else {
|
||||
return result.value;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tells if we can go back or not
|
||||
* @return {boolean}
|
||||
*/
|
||||
WebPage.prototype.canGoBack = function () {
|
||||
return this["native"]().canGoBack;
|
||||
};
|
||||
|
||||
/**
|
||||
* Tells if we can go forward or not in the browser history
|
||||
* @return {boolean}
|
||||
*/
|
||||
WebPage.prototype.canGoForward = function () {
|
||||
return this["native"]().canGoForward;
|
||||
};
|
||||
|
||||
return WebPage;
|
||||
|
||||
}).call(this);
|
79
vendor/jcalderonzumba/gastonjs/src/Cookie.php
vendored
Normal file
79
vendor/jcalderonzumba/gastonjs/src/Cookie.php
vendored
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS;
|
||||
|
||||
/**
|
||||
* Class Cookie
|
||||
* @package Zumba\GastonJS
|
||||
*/
|
||||
class Cookie {
|
||||
/** @var array */
|
||||
protected $attributes;
|
||||
|
||||
/**
|
||||
* @param $attributes
|
||||
*/
|
||||
public function __construct($attributes) {
|
||||
$this->attributes = $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cookie name
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
return $this->attributes['name'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cookie value
|
||||
* @return string
|
||||
*/
|
||||
public function getValue() {
|
||||
return urldecode($this->attributes['value']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cookie domain
|
||||
* @return string
|
||||
*/
|
||||
public function getDomain() {
|
||||
return $this->attributes['domain'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path were the cookie is valid
|
||||
* @return string
|
||||
*/
|
||||
public function getPath() {
|
||||
return $this->attributes['path'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Is a secure cookie?
|
||||
* @return bool
|
||||
*/
|
||||
public function isSecure() {
|
||||
return isset($this->attributes['secure']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is http only cookie?
|
||||
* @return bool
|
||||
*/
|
||||
public function isHttpOnly() {
|
||||
return isset($this->attributes['httponly']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns cookie expiration time
|
||||
* @return mixed
|
||||
*/
|
||||
public function getExpirationTime() {
|
||||
//TODO: return a \DateTime object
|
||||
if (isset($this->attributes['expiry'])) {
|
||||
return $this->attributes['expiry'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
44
vendor/jcalderonzumba/gastonjs/src/Exception/BrowserError.php
vendored
Normal file
44
vendor/jcalderonzumba/gastonjs/src/Exception/BrowserError.php
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Exception;
|
||||
|
||||
|
||||
/**
|
||||
* Class BrowserError
|
||||
* @package Zumba\GastonJS\Exception
|
||||
*/
|
||||
class BrowserError extends ClientError {
|
||||
|
||||
/**
|
||||
* @param array $response
|
||||
*/
|
||||
public function __construct($response) {
|
||||
parent::__construct($response);
|
||||
$this->message = $this->message();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the browser error
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
return $this->response["error"]["name"];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return JSErrorItem
|
||||
*/
|
||||
public function javascriptError() {
|
||||
//TODO: this need to be check, i don't know yet what comes in response
|
||||
return new JSErrorItem($this->response["error"]["args"][0], $this->response["error"]["args"][1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns error message
|
||||
* TODO: check how to proper implement if we have exceptions
|
||||
* @return string
|
||||
*/
|
||||
public function message() {
|
||||
return "There was an error inside the PhantomJS portion of GastonJS.\nThis is probably a bug, so please report it:\n" . $this->javascriptError();
|
||||
}
|
||||
}
|
36
vendor/jcalderonzumba/gastonjs/src/Exception/ClientError.php
vendored
Normal file
36
vendor/jcalderonzumba/gastonjs/src/Exception/ClientError.php
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Exception;
|
||||
|
||||
/**
|
||||
* Class ClientError
|
||||
* @package Zumba\GastonJS\Exception
|
||||
*/
|
||||
class ClientError extends \Exception {
|
||||
|
||||
/** @var mixed */
|
||||
protected $response;
|
||||
|
||||
/**
|
||||
* @param mixed $response
|
||||
*/
|
||||
public function __construct($response) {
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResponse() {
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $response
|
||||
*/
|
||||
public function setResponse($response) {
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
|
||||
}
|
21
vendor/jcalderonzumba/gastonjs/src/Exception/DeadClient.php
vendored
Normal file
21
vendor/jcalderonzumba/gastonjs/src/Exception/DeadClient.php
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Exception;
|
||||
|
||||
|
||||
/**
|
||||
* Class DeadClient
|
||||
* @package Zumba\GastonJS\Exception
|
||||
*/
|
||||
class DeadClient extends \Exception {
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param \Exception $previous
|
||||
*/
|
||||
public function __construct($message = "", $code = 0, \Exception $previous = null) {
|
||||
$errorMsg = $message."\nPhantomjs browser server is not taking connections, most probably it has crashed\n";
|
||||
parent::__construct($errorMsg, $code, $previous);
|
||||
}
|
||||
}
|
26
vendor/jcalderonzumba/gastonjs/src/Exception/FrameNotFound.php
vendored
Normal file
26
vendor/jcalderonzumba/gastonjs/src/Exception/FrameNotFound.php
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Exception;
|
||||
|
||||
/**
|
||||
* Class FrameNotFound
|
||||
* @package Zumba\GastonJS\Exception
|
||||
*/
|
||||
class FrameNotFound extends ClientError {
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
//TODO: check stuff here
|
||||
return current(reset($this->response["args"]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function message() {
|
||||
//TODO: check the exception message stuff
|
||||
return "The frame " . $this->getName() . " was not not found";
|
||||
}
|
||||
}
|
32
vendor/jcalderonzumba/gastonjs/src/Exception/InvalidSelector.php
vendored
Normal file
32
vendor/jcalderonzumba/gastonjs/src/Exception/InvalidSelector.php
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Exception;
|
||||
|
||||
/**
|
||||
* Class InvalidSelector
|
||||
* @package Zumba\GastonJS\Exception
|
||||
*/
|
||||
class InvalidSelector extends ClientError {
|
||||
/**
|
||||
* Gets the method of selection
|
||||
* @return string
|
||||
*/
|
||||
public function getMethod() {
|
||||
return $this->response["error"]["args"][0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the selector related to the method
|
||||
* @return string
|
||||
*/
|
||||
public function getSelector() {
|
||||
return $this->response["error"]["args"][1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function message() {
|
||||
return "The browser raised a syntax error while trying to evaluate" . $this->getMethod() . " selector " . $this->getSelector();
|
||||
}
|
||||
}
|
31
vendor/jcalderonzumba/gastonjs/src/Exception/JSErrorItem.php
vendored
Normal file
31
vendor/jcalderonzumba/gastonjs/src/Exception/JSErrorItem.php
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Exception;
|
||||
|
||||
/**
|
||||
* Class JSErrorItem
|
||||
* @package Zumba\GastonJS\Exception
|
||||
*/
|
||||
class JSErrorItem {
|
||||
/** @var mixed */
|
||||
protected $message;
|
||||
/** @var mixed */
|
||||
protected $stack;
|
||||
|
||||
/**
|
||||
* @param $message
|
||||
* @param $stack
|
||||
*/
|
||||
public function __construct($message, $stack) {
|
||||
$this->message = $message;
|
||||
$this->stack = $stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* String representation of the class
|
||||
* @return string
|
||||
*/
|
||||
public function __toString() {
|
||||
return sprintf("%s\n%s", $this->message, $this->stack);
|
||||
}
|
||||
}
|
48
vendor/jcalderonzumba/gastonjs/src/Exception/JavascriptError.php
vendored
Normal file
48
vendor/jcalderonzumba/gastonjs/src/Exception/JavascriptError.php
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Exception;
|
||||
|
||||
|
||||
/**
|
||||
* Class JavascriptError
|
||||
* @package Zumba\GastonJS\Exception
|
||||
*/
|
||||
class JavascriptError extends ClientError {
|
||||
|
||||
/**
|
||||
* @param array $response
|
||||
*/
|
||||
public function __construct($response) {
|
||||
parent::__construct($response);
|
||||
$this->message = $this->message();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the javascript errors found during the use of the phantomjs
|
||||
* @return array
|
||||
*/
|
||||
public function javascriptErrors() {
|
||||
$jsErrors = array();
|
||||
$errors = $this->response["error"]["args"][0];
|
||||
foreach ($errors as $error) {
|
||||
$jsErrors[] = new JSErrorItem($error["message"], $error["stack"]);
|
||||
}
|
||||
return $jsErrors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the javascript errors found
|
||||
* @return string
|
||||
*/
|
||||
public function message() {
|
||||
$error = "One or more errors were raised in the Javascript code on the page.
|
||||
If you don't care about these errors, you can ignore them by
|
||||
setting js_errors: false in your Poltergeist configuration (see documentation for details).";
|
||||
//TODO: add javascript errors
|
||||
$jsErrors = $this->javascriptErrors();
|
||||
foreach($jsErrors as $jsError){
|
||||
$error = "$error\n$jsError";
|
||||
}
|
||||
return $error;
|
||||
}
|
||||
}
|
49
vendor/jcalderonzumba/gastonjs/src/Exception/MouseEventFailed.php
vendored
Normal file
49
vendor/jcalderonzumba/gastonjs/src/Exception/MouseEventFailed.php
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Exception;
|
||||
|
||||
/**
|
||||
* Class MouseEventFailed
|
||||
* @package Zumba\GastonJS\Exception
|
||||
*/
|
||||
class MouseEventFailed extends NodeError {
|
||||
|
||||
/**
|
||||
* Gets the name of the event
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
return $this->response["args"][0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Selector of the element to act with the mouse
|
||||
* @return string
|
||||
*/
|
||||
public function getSelector() {
|
||||
return $this->response["args"][1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the position where the click was done
|
||||
* @return array
|
||||
*/
|
||||
public function getPosition() {
|
||||
$position = array();
|
||||
$position[0] = $this->response["args"][1]['x'];
|
||||
$position[1] = $this->response["args"][2]['y'];
|
||||
return $position;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function message() {
|
||||
$name = $this->getName();
|
||||
$position = implode(",", $this->getPosition());
|
||||
return "Firing a $name at co-ordinates [$position] failed. Poltergeist detected
|
||||
another element with CSS selector '#{selector}' at this position.
|
||||
It may be overlapping the element you are trying to interact with.
|
||||
If you don't care about overlapping elements, try using node.trigger('$name').";
|
||||
}
|
||||
}
|
10
vendor/jcalderonzumba/gastonjs/src/Exception/NoSuchWindowError.php
vendored
Normal file
10
vendor/jcalderonzumba/gastonjs/src/Exception/NoSuchWindowError.php
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
namespace Zumba\GastonJS\Exception;
|
||||
|
||||
|
||||
/**
|
||||
* Class NoSuchWindowError
|
||||
* @package Zumba\GastonJS\Exception
|
||||
*/
|
||||
class NoSuchWindowError extends ClientError {
|
||||
}
|
20
vendor/jcalderonzumba/gastonjs/src/Exception/NodeError.php
vendored
Normal file
20
vendor/jcalderonzumba/gastonjs/src/Exception/NodeError.php
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Exception;
|
||||
|
||||
/**
|
||||
* Class NodeError
|
||||
* @package Zumba\GastonJS\Exception
|
||||
*/
|
||||
class NodeError extends ClientError {
|
||||
protected $node;
|
||||
|
||||
/**
|
||||
* @param mixed $node
|
||||
* @param mixed $response
|
||||
*/
|
||||
public function __construct($node, $response) {
|
||||
$this->node = $node;
|
||||
parent::__construct($response);
|
||||
}
|
||||
}
|
29
vendor/jcalderonzumba/gastonjs/src/Exception/ObsoleteNode.php
vendored
Normal file
29
vendor/jcalderonzumba/gastonjs/src/Exception/ObsoleteNode.php
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Exception;
|
||||
|
||||
/**
|
||||
* Class ObsoleteNode
|
||||
* @package Zumba\GastonJS\Exception
|
||||
*/
|
||||
class ObsoleteNode extends ClientError {
|
||||
|
||||
/**
|
||||
* @param array $response
|
||||
*/
|
||||
public function __construct($response) {
|
||||
parent::__construct($response);
|
||||
$this->message = $this->message();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function message() {
|
||||
return "The element you are trying to interact with is either not part of the DOM, or is
|
||||
not currently visible on the page (perhaps display: none is set).
|
||||
It's possible the element has been replaced by another element and you meant to interact with
|
||||
the new element. If so you need to do a new 'find' in order to get a reference to the
|
||||
new element.";
|
||||
}
|
||||
}
|
17
vendor/jcalderonzumba/gastonjs/src/Exception/StatusFailError.php
vendored
Normal file
17
vendor/jcalderonzumba/gastonjs/src/Exception/StatusFailError.php
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Exception;
|
||||
|
||||
|
||||
/**
|
||||
* Class StatusFailError
|
||||
* @package Zumba\GastonJS\Exception
|
||||
*/
|
||||
class StatusFailError extends ClientError {
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function message() {
|
||||
return "Request failed to reach server, check DNS and/or server status";
|
||||
}
|
||||
}
|
23
vendor/jcalderonzumba/gastonjs/src/Exception/TimeoutError.php
vendored
Normal file
23
vendor/jcalderonzumba/gastonjs/src/Exception/TimeoutError.php
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\Exception;
|
||||
|
||||
/**
|
||||
* Class TimeoutError
|
||||
* @package Zumba\GastonJS\Exception
|
||||
*/
|
||||
class TimeoutError extends \Exception {
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
*/
|
||||
public function __construct($message) {
|
||||
$errorMessage = "Timed out waiting for response to {$message}. It's possible that this happened
|
||||
because something took a very long time(for example a page load was slow).
|
||||
If so, setting the Poltergeist :timeout option to a higher value will help
|
||||
(see the docs for details). If increasing the timeout does not help, this is
|
||||
probably a bug in Poltergeist - please report it to the issue tracker.";
|
||||
parent::__construct($errorMessage);
|
||||
}
|
||||
|
||||
}
|
95
vendor/jcalderonzumba/gastonjs/src/NetworkTraffic/Request.php
vendored
Normal file
95
vendor/jcalderonzumba/gastonjs/src/NetworkTraffic/Request.php
vendored
Normal file
|
@ -0,0 +1,95 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\GastonJS\NetworkTraffic;
|
||||
|
||||
/**
|
||||
* Class Request
|
||||
* @package Zumba\GastonJS\NetworkTraffic
|
||||
*/
|
||||
class Request {
|
||||
/** @var array */
|
||||
protected $data;
|
||||
/** @var array */
|
||||
protected $responseParts;
|
||||
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param array $responseParts
|
||||
*/
|
||||
public function __construct($data, $responseParts = null) {
|
||||
$this->data = $data;
|
||||
$this->responseParts = $this->createResponseParts($responseParts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an array of Response objects from a given response array
|
||||
* @param $responseParts
|
||||
* @return array
|
||||
*/
|
||||
protected function createResponseParts($responseParts) {
|
||||
if ($responseParts === null) {
|
||||
return array();
|
||||
}
|
||||
$responses = array();
|
||||
foreach ($responseParts as $responsePart) {
|
||||
$responses[] = new Response($responsePart);
|
||||
}
|
||||
return $responses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getResponseParts() {
|
||||
return $this->responseParts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $responseParts
|
||||
*/
|
||||
public function setResponseParts($responseParts) {
|
||||
$this->responseParts = $responseParts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the url where the request is going to be made
|
||||
* @return string
|
||||
*/
|
||||
public function getUrl() {
|
||||
//TODO: add isset maybe?
|
||||
return $this->data['url'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request method
|
||||
* @return string
|
||||
*/
|
||||
public function getMethod() {
|
||||
return $this->data['method'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the request headers
|
||||
* @return array
|
||||
*/
|
||||
public function getHeaders() {
|
||||
//TODO: Check if the data is actually an array, else make it array and see implications
|
||||
return $this->data['headers'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if exists the request time
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getTime() {
|
||||
if (isset($this->data['time'])) {
|
||||
$requestTime = new \DateTime();
|
||||
//TODO: fix the microseconds to miliseconds
|
||||
$requestTime->createFromFormat("Y-m-dTH:i:s.uZ", $this->data["time"]);
|
||||
return $requestTime;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
97
vendor/jcalderonzumba/gastonjs/src/NetworkTraffic/Response.php
vendored
Normal file
97
vendor/jcalderonzumba/gastonjs/src/NetworkTraffic/Response.php
vendored
Normal file
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
namespace Zumba\GastonJS\NetworkTraffic;
|
||||
|
||||
/**
|
||||
* Class Response
|
||||
* @package Zumba\GastonJS\NetworkTraffic
|
||||
*/
|
||||
class Response {
|
||||
/** @var array */
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
*/
|
||||
public function __construct($data) {
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets Response url
|
||||
* @return string
|
||||
*/
|
||||
public function getUrl() {
|
||||
return $this->data['url'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the response status code
|
||||
* @return int
|
||||
*/
|
||||
public function getStatus() {
|
||||
return intval($this->data['status']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status text of the response
|
||||
* @return string
|
||||
*/
|
||||
public function getStatusText() {
|
||||
return $this->data['statusText'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the response headers
|
||||
* @return array
|
||||
*/
|
||||
public function getHeaders() {
|
||||
return $this->data['headers'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get redirect url if response is a redirect
|
||||
* @return string
|
||||
*/
|
||||
public function getRedirectUrl() {
|
||||
if (isset($this->data['redirectUrl']) && !empty($this->data['redirectUrl'])) {
|
||||
return $this->data['redirectUrl'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the response body
|
||||
* @return int
|
||||
*/
|
||||
public function getBodySize() {
|
||||
if (isset($this->data['bodySize'])) {
|
||||
return intval($this->data['bodySize']);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the content type of the response
|
||||
* @return string
|
||||
*/
|
||||
public function getContentType() {
|
||||
if (isset($this->data['contentType'])) {
|
||||
return $this->data['contentType'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if exists the response time
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getTime() {
|
||||
if (isset($this->data['time'])) {
|
||||
$requestTime = new \DateTime();
|
||||
//TODO: fix the microseconds to miliseconds
|
||||
$requestTime->createFromFormat("Y-m-dTH:i:s.uZ", $this->data["time"]);
|
||||
return $requestTime;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
25
vendor/jcalderonzumba/gastonjs/unit_tests.xml
vendored
Normal file
25
vendor/jcalderonzumba/gastonjs/unit_tests.xml
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit bootstrap="./tests/unit/bootstrap.php"
|
||||
backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="true"
|
||||
syntaxCheck="false">
|
||||
<testsuites>
|
||||
<testsuite>
|
||||
<directory>tests/unit</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">src</directory>
|
||||
<exclude>
|
||||
<directory suffix="Trait.php">src/</directory>
|
||||
</exclude>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
40
vendor/jcalderonzumba/mink-phantomjs-driver/.travis.yml
vendored
Normal file
40
vendor/jcalderonzumba/mink-phantomjs-driver/.travis.yml
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
language: php
|
||||
|
||||
php:
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- hhvm
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- php: 5.4
|
||||
env: COMPOSER_FLAGS='--prefer-lowest --prefer-stable' SYMFONY_DEPRECATIONS_HELPER=weak
|
||||
- php: 5.6
|
||||
env: DEPENDENCIES=dev
|
||||
allow_failures:
|
||||
- php: 7.0
|
||||
- php: hhvm
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache/files
|
||||
|
||||
before_install:
|
||||
- composer self-update
|
||||
- if [ "$DEPENDENCIES" = "dev" ]; then perl -pi -e 's/^}$/,"minimum-stability":"dev"}/' composer.json; fi;
|
||||
|
||||
install:
|
||||
- composer update $COMPOSER_FLAGS
|
||||
|
||||
before_script:
|
||||
- mkdir -p /tmp/jcalderonzumba/phantomjs
|
||||
|
||||
script:
|
||||
- bin/run-tests.sh
|
||||
|
||||
after_script:
|
||||
- ps axo pid,command | grep phantomjs | grep -v grep | awk '{print $1}' | xargs -I {} kill {}
|
||||
- ps axo pid,command | grep php | grep -v grep | awk '{print $1}' | xargs -I {} kill {}
|
7
vendor/jcalderonzumba/mink-phantomjs-driver/CHANGELOG-0.2.md
vendored
Normal file
7
vendor/jcalderonzumba/mink-phantomjs-driver/CHANGELOG-0.2.md
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
CHANGELOG for 0.2.x
|
||||
===================
|
||||
This changelog references the relevant changes (bug and security fixes) done in 0.2 minor versions.
|
||||
|
||||
* 0.2.3
|
||||
|
||||
* bug #1 set_url_blacklist was not working properly (thanks to reporter)
|
21
vendor/jcalderonzumba/mink-phantomjs-driver/LICENSE
vendored
Normal file
21
vendor/jcalderonzumba/mink-phantomjs-driver/LICENSE
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Juan Francisco Calderón Zumba
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
61
vendor/jcalderonzumba/mink-phantomjs-driver/README.md
vendored
Normal file
61
vendor/jcalderonzumba/mink-phantomjs-driver/README.md
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
Mink PhantomJS Driver
|
||||
===========================
|
||||
[](https://travis-ci.org/jcalderonzumba/MinkPhantomJSDriver)
|
||||
[](https://scrutinizer-ci.com/g/jcalderonzumba/MinkPhantomJSDriver/?branch=master)
|
||||
[](https://packagist.org/packages/jcalderonzumba/mink-phantomjs-driver)
|
||||
[](https://packagist.org/packages/jcalderonzumba/mink-phantomjs-driver)
|
||||
|
||||
Installation & Compatibility
|
||||
----------------------------
|
||||
You need a working installation of [PhantomJS](http://phantomjs.org/download.html)
|
||||
|
||||
This driver is tested using PhantomJS 1.9.8 but it should work with 1.9.X or latest 2.0.X versions
|
||||
|
||||
This driver supports **PHP 5.4 or greater**, there is NO support for PHP 5.3
|
||||
|
||||
Use [Composer](https://getcomposer.org/) to install all required PHP dependencies:
|
||||
|
||||
```bash
|
||||
$ composer require --dev behat/mink jcalderonzumba/mink-phantomjs-driver
|
||||
```
|
||||
|
||||
How to use
|
||||
-------------
|
||||
Extension configuration (for the moment NONE).
|
||||
```yml
|
||||
default:
|
||||
extensions:
|
||||
Zumba\PhantomJSExtension:
|
||||
```
|
||||
Driver specific configuration:
|
||||
```yml
|
||||
Behat\MinkExtension:
|
||||
phantomjs:
|
||||
phantom_server: "http://localhost:8510/api"
|
||||
template_cache: "/tmp/pjsdrivercache/phantomjs"
|
||||
```
|
||||
PhantomJS browser start:
|
||||
```bash
|
||||
phantomjs --ssl-protocol=any --ignore-ssl-errors=true vendor/jcalderonzumba/gastonjs/src/Client/main.js 8510 1024 768 2>&1 >> /tmp/gastonjs.log &
|
||||
```
|
||||
|
||||
FAQ
|
||||
---------
|
||||
|
||||
1. Is this a selenium based driver?:
|
||||
|
||||
**NO**, it has nothing to do with Selenium it's inspired on [Poltergeist](https://github.com/teampoltergeist/poltergeist)
|
||||
|
||||
2. What features does this driver implements?
|
||||
|
||||
**ALL** of the features defined in Mink DriverInterface. maximizeWindow is the only one not implemented since is a headless browser it does not make sense to implement it.
|
||||
|
||||
3. Do i need to modify my selenium based tests?
|
||||
|
||||
If you only use the standard behat driver defined methods then NO, you just have to change your default javascript driver.
|
||||
|
||||
|
||||
Copyright
|
||||
---------
|
||||
|
||||
Copyright (c) 2015 Juan Francisco Calderon Zumba <juanfcz@gmail.com>
|
40
vendor/jcalderonzumba/mink-phantomjs-driver/bin/run-tests.sh
vendored
Normal file
40
vendor/jcalderonzumba/mink-phantomjs-driver/bin/run-tests.sh
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
start_browser_api(){
|
||||
CURRENT_DIR=$(pwd)
|
||||
LOCAL_PHANTOMJS="${CURRENT_DIR}/bin/phantomjs"
|
||||
if [ -f ${LOCAL_PHANTOMJS} ]; then
|
||||
${LOCAL_PHANTOMJS} --ssl-protocol=any --ignore-ssl-errors=true vendor/jcalderonzumba/gastonjs/src/Client/main.js 8510 1024 768 2>&1 &
|
||||
else
|
||||
phantomjs --ssl-protocol=any --ignore-ssl-errors=true vendor/jcalderonzumba/gastonjs/src/Client/main.js 8510 1024 768 2>&1 >> /dev/null &
|
||||
fi
|
||||
sleep 2
|
||||
}
|
||||
|
||||
stop_services(){
|
||||
ps axo pid,command | grep phantomjs | grep -v grep | awk '{print $1}' | xargs -I {} kill {}
|
||||
ps axo pid,command | grep php | grep -v grep | grep -v phpstorm | awk '{print $1}' | xargs -I {} kill {}
|
||||
sleep 2
|
||||
}
|
||||
|
||||
star_local_browser(){
|
||||
CURRENT_DIR=$(pwd)
|
||||
cd ${CURRENT_DIR}/vendor/behat/mink/driver-testsuite/web-fixtures
|
||||
if [ "$TRAVIS" = true ]; then
|
||||
echo "Starting webserver fox fixtures...."
|
||||
~/.phpenv/versions/5.6/bin/php -S 127.0.0.1:6789 > /dev/null 2>&1 &
|
||||
else
|
||||
php -S 127.0.0.1:6789 2>&1 >> /dev/null &
|
||||
fi
|
||||
sleep 2
|
||||
}
|
||||
|
||||
mkdir -p /tmp/jcalderonzumba/phantomjs
|
||||
stop_services
|
||||
start_browser_api
|
||||
star_local_browser
|
||||
cd ${CURRENT_DIR}
|
||||
${CURRENT_DIR}/bin/phpunit --configuration integration_tests.xml
|
||||
stop_services
|
||||
start_browser_api
|
53
vendor/jcalderonzumba/mink-phantomjs-driver/composer.json
vendored
Normal file
53
vendor/jcalderonzumba/mink-phantomjs-driver/composer.json
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
{
|
||||
"name": "jcalderonzumba/mink-phantomjs-driver",
|
||||
"description": "PhantomJS driver for Mink framework",
|
||||
"keywords": [
|
||||
"phantomjs",
|
||||
"headless",
|
||||
"javascript",
|
||||
"ajax",
|
||||
"testing",
|
||||
"browser"
|
||||
],
|
||||
"homepage": "http://mink.behat.org/",
|
||||
"type": "mink-driver",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Juan Francisco Calderón Zumba",
|
||||
"email": "juanfcz@gmail.com",
|
||||
"homepage": "http://github.com/jcalderonzumba"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.4",
|
||||
"behat/mink": "~1.6",
|
||||
"twig/twig": "~1.8",
|
||||
"jcalderonzumba/gastonjs": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/process": "~2.3",
|
||||
"symfony/phpunit-bridge": "~2.7",
|
||||
"symfony/css-selector": "~2.1",
|
||||
"phpunit/phpunit": "~4.6",
|
||||
"silex/silex": "~1.2"
|
||||
},
|
||||
"config": {
|
||||
"bin-dir": "bin"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Zumba\\Mink\\Driver\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Behat\\Mink\\Tests\\Driver\\": "tests/integration"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.4.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
38
vendor/jcalderonzumba/mink-phantomjs-driver/integration_tests.xml
vendored
Normal file
38
vendor/jcalderonzumba/mink-phantomjs-driver/integration_tests.xml
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit colors="true" bootstrap="./tests/integration/bootstrap.php" stopOnFailure="true">
|
||||
<testsuites>
|
||||
<testsuite name="PhantomJS Driver test suite">
|
||||
<directory>tests/integration</directory>
|
||||
<file>vendor/behat/mink/driver-testsuite/tests/Basic/BasicAuthTest.php</file>
|
||||
<file>vendor/behat/mink/driver-testsuite/tests/Basic/ContentTest.php</file>
|
||||
<file>vendor/behat/mink/driver-testsuite/tests/Basic/CookieTest.php</file>
|
||||
<file>vendor/behat/mink/driver-testsuite/tests/Basic/ErrorHandlingTest.php</file>
|
||||
<file>vendor/behat/mink/driver-testsuite/tests/Basic/IFrameTest.php</file>
|
||||
<file>vendor/behat/mink/driver-testsuite/tests/Basic/ScreenshotTest.php</file>
|
||||
<file>vendor/behat/mink/driver-testsuite/tests/Basic/TraversingTest.php</file>
|
||||
<file>vendor/behat/mink/driver-testsuite/tests/Basic/VisibilityTest.php</file>
|
||||
<directory>vendor/behat/mink/driver-testsuite/tests/Form</directory>
|
||||
<directory>vendor/behat/mink/driver-testsuite/tests/Js</directory>
|
||||
<!-- The following have been disabled and their respective equals added to Custom driver tests -->
|
||||
<!--<directory>vendor/behat/mink/driver-testsuite/tests/Css</directory>-->
|
||||
<!--<file>vendor/behat/mink/driver-testsuite/tests/Basic/StatusCodeTest.php</file>-->
|
||||
<!--<file>vendor/behat/mink/driver-testsuite/tests/Basic/HeaderTest.php</file>-->
|
||||
<!--<file>vendor/behat/mink/driver-testsuite/tests/Basic/NavigationTest.php</file>-->
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<php>
|
||||
<var name="driver_config_factory" value="Behat\Mink\Tests\Driver\PhantomJSConfig::getInstance"/>
|
||||
<server name="WEB_FIXTURES_HOST" value="http://127.0.0.1:6789"/>
|
||||
<!-- where driver will connect to -->
|
||||
<server name="DRIVER_URL" value="http://127.0.0.1:8510/"/>
|
||||
<server name="TEMPLATE_CACHE_DIR" value="/tmp/jcalderonzumba/phantomjs"/>
|
||||
</php>
|
||||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory>./src/Behat/Mink/Driver</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
109
vendor/jcalderonzumba/mink-phantomjs-driver/src/BasePhantomJSDriver.php
vendored
Normal file
109
vendor/jcalderonzumba/mink-phantomjs-driver/src/BasePhantomJSDriver.php
vendored
Normal file
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\Mink\Driver;
|
||||
|
||||
use Behat\Mink\Driver\CoreDriver;
|
||||
use Behat\Mink\Exception\DriverException;
|
||||
use Behat\Mink\Session;
|
||||
use Zumba\GastonJS\Browser\Browser;
|
||||
|
||||
/**
|
||||
* Class BasePhantomJSDriver
|
||||
* @package Zumba\Mink\Driver
|
||||
*/
|
||||
class BasePhantomJSDriver extends CoreDriver {
|
||||
|
||||
/** @var Session */
|
||||
protected $session;
|
||||
/** @var Browser */
|
||||
protected $browser;
|
||||
/** @var string */
|
||||
protected $phantomHost;
|
||||
/** @var \Twig_Loader_Filesystem */
|
||||
protected $templateLoader;
|
||||
/** @var \Twig_Environment */
|
||||
protected $templateEnv;
|
||||
|
||||
/**
|
||||
* Instantiates the driver
|
||||
* @param string $phantomHost browser "api" oriented host
|
||||
* @param string $templateCache where we are going to store the templates cache
|
||||
*/
|
||||
public function __construct($phantomHost, $templateCache = null) {
|
||||
$this->phantomHost = $phantomHost;
|
||||
$this->browser = new Browser($phantomHost);
|
||||
$this->templateLoader = new \Twig_Loader_Filesystem(realpath(__DIR__ . '/Resources/Script'));
|
||||
$this->templateEnv = new \Twig_Environment($this->templateLoader, array('cache' => $this->templateCacheSetup($templateCache), 'strict_variables' => true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the cache template location for the scripts we are going to create with the driver
|
||||
* @param $templateCache
|
||||
* @return string
|
||||
* @throws DriverException
|
||||
*/
|
||||
protected function templateCacheSetup($templateCache) {
|
||||
$cacheDir = $templateCache;
|
||||
if ($templateCache === null) {
|
||||
$cacheDir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . "jcalderonzumba" . DIRECTORY_SEPARATOR . "phantomjs";
|
||||
if (!file_exists($cacheDir)) {
|
||||
mkdir($cacheDir, 0777, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!file_exists($cacheDir)) {
|
||||
throw new DriverException("Template cache $cacheDir directory does not exist");
|
||||
}
|
||||
return $cacheDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to find a node element given an xpath
|
||||
* @param string $xpath
|
||||
* @param int $max
|
||||
* @returns int
|
||||
* @throws DriverException
|
||||
*/
|
||||
protected function findElement($xpath, $max = 1) {
|
||||
$elements = $this->browser->find("xpath", $xpath);
|
||||
if (!isset($elements["page_id"]) || !isset($elements["ids"]) || count($elements["ids"]) !== $max) {
|
||||
throw new DriverException("Failed to get elements with given $xpath");
|
||||
}
|
||||
return $elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @param Session $session
|
||||
*/
|
||||
public function setSession(Session $session) {
|
||||
$this->session = $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Browser
|
||||
*/
|
||||
public function getBrowser() {
|
||||
return $this->browser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Twig_Environment
|
||||
*/
|
||||
public function getTemplateEnv() {
|
||||
return $this->templateEnv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a javascript script via twig template engine
|
||||
* @param $templateName
|
||||
* @param $viewData
|
||||
* @return string
|
||||
*/
|
||||
public function javascriptTemplateRender($templateName, $viewData) {
|
||||
/** @var $templateEngine \Twig_Environment */
|
||||
$templateEngine = $this->getTemplateEnv();
|
||||
return $templateEngine->render($templateName, $viewData);
|
||||
}
|
||||
|
||||
}
|
45
vendor/jcalderonzumba/mink-phantomjs-driver/src/CookieTrait.php
vendored
Normal file
45
vendor/jcalderonzumba/mink-phantomjs-driver/src/CookieTrait.php
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\Mink\Driver;
|
||||
|
||||
use Zumba\GastonJS\Cookie;
|
||||
|
||||
/**
|
||||
* Trait CookieTrait
|
||||
* @package Zumba\Mink\Driver
|
||||
*/
|
||||
trait CookieTrait {
|
||||
|
||||
/**
|
||||
* Sets a cookie on the browser, if null value then delete it
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
*/
|
||||
public function setCookie($name, $value = null) {
|
||||
if ($value === null) {
|
||||
$this->browser->removeCookie($name);
|
||||
}
|
||||
//TODO: set the cookie with domain, not with url, meaning www.aaa.com or .aaa.com
|
||||
if ($value !== null) {
|
||||
$urlData = parse_url($this->getCurrentUrl());
|
||||
$cookie = array("name" => $name, "value" => $value, "domain" => $urlData["host"]);
|
||||
$this->browser->setCookie($cookie);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a cookie by its name if exists, else it will return null
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
public function getCookie($name) {
|
||||
$cookies = $this->browser->cookies();
|
||||
foreach ($cookies as $cookie) {
|
||||
if ($cookie instanceof Cookie && strcmp($cookie->getName(), $name) === 0) {
|
||||
return $cookie->getValue();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
168
vendor/jcalderonzumba/mink-phantomjs-driver/src/FormManipulationTrait.php
vendored
Normal file
168
vendor/jcalderonzumba/mink-phantomjs-driver/src/FormManipulationTrait.php
vendored
Normal file
|
@ -0,0 +1,168 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\Mink\Driver;
|
||||
|
||||
use Behat\Mink\Exception\DriverException;
|
||||
|
||||
/**
|
||||
* Trait FormManipulationTrait
|
||||
* @package Zumba\Mink\Driver
|
||||
*/
|
||||
trait FormManipulationTrait {
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value of a given xpath element
|
||||
* @param string $xpath
|
||||
* @return string
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function getValue($xpath) {
|
||||
$this->findElement($xpath, 1);
|
||||
$javascript = $this->javascriptTemplateRender("get_value.js.twig", array("xpath" => $xpath));
|
||||
return $this->browser->evaluate($javascript);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $xpath
|
||||
* @param string $value
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function setValue($xpath, $value) {
|
||||
$this->findElement($xpath, 1);
|
||||
//This stuff is BECAUSE the way the driver works for setting values when being checkboxes, radios, etc.
|
||||
if (is_bool($value)) {
|
||||
$value = $this->boolToString($value);
|
||||
}
|
||||
|
||||
$javascript = $this->javascriptTemplateRender("set_value.js.twig", array("xpath" => $xpath, "value" => json_encode($value)));
|
||||
$this->browser->evaluate($javascript);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Submits a form given an xpath selector
|
||||
* @param string $xpath
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function submitForm($xpath) {
|
||||
$element = $this->findElement($xpath, 1);
|
||||
$tagName = $this->browser->tagName($element["page_id"], $element["ids"][0]);
|
||||
if (strcmp(strtolower($tagName), "form") !== 0) {
|
||||
throw new DriverException("Can not submit something that is not a form");
|
||||
}
|
||||
$this->browser->trigger($element["page_id"], $element["ids"][0], "submit");
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method needed for twig and javascript stuff
|
||||
* @param $boolValue
|
||||
* @return string
|
||||
*/
|
||||
protected function boolToString($boolValue) {
|
||||
if ($boolValue === true) {
|
||||
return "1";
|
||||
}
|
||||
return "0";
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects an option
|
||||
* @param string $xpath
|
||||
* @param string $value
|
||||
* @param bool $multiple
|
||||
* @return bool
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function selectOption($xpath, $value, $multiple = false) {
|
||||
$element = $this->findElement($xpath, 1);
|
||||
$tagName = strtolower($this->browser->tagName($element["page_id"], $element["ids"][0]));
|
||||
$attributes = $this->browser->attributes($element["page_id"], $element["ids"][0]);
|
||||
|
||||
if (!in_array($tagName, array("input", "select"))) {
|
||||
throw new DriverException(sprintf('Impossible to select an option on the element with XPath "%s" as it is not a select or radio input', $xpath));
|
||||
}
|
||||
|
||||
if ($tagName === "input" && $attributes["type"] != "radio") {
|
||||
throw new DriverException(sprintf('Impossible to select an option on the element with XPath "%s" as it is not a select or radio input', $xpath));
|
||||
}
|
||||
|
||||
return $this->browser->selectOption($element["page_id"], $element["ids"][0], $value, $multiple);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check control over an input element of radio or checkbox type
|
||||
* @param $xpath
|
||||
* @return bool
|
||||
* @throws DriverException
|
||||
*/
|
||||
protected function inputCheckableControl($xpath) {
|
||||
$element = $this->findElement($xpath, 1);
|
||||
$tagName = strtolower($this->browser->tagName($element["page_id"], $element["ids"][0]));
|
||||
$attributes = $this->browser->attributes($element["page_id"], $element["ids"][0]);
|
||||
if ($tagName != "input") {
|
||||
throw new DriverException("Can not check when the element is not of the input type");
|
||||
}
|
||||
if (!in_array($attributes["type"], array("checkbox", "radio"))) {
|
||||
throw new DriverException("Can not check when the element is not checkbox or radio");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* We click on the checkbox or radio when possible and needed
|
||||
* @param string $xpath
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function check($xpath) {
|
||||
$this->inputCheckableControl($xpath);
|
||||
$javascript = $this->javascriptTemplateRender("check_element.js.twig", array("xpath" => $xpath, "check" => "true"));
|
||||
$this->browser->evaluate($javascript);
|
||||
}
|
||||
|
||||
/**
|
||||
* We click on the checkbox or radio when possible and needed
|
||||
* @param string $xpath
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function uncheck($xpath) {
|
||||
$this->inputCheckableControl($xpath);
|
||||
$javascript = $this->javascriptTemplateRender("check_element.js.twig", array("xpath" => $xpath, "check" => "false"));
|
||||
$this->browser->evaluate($javascript);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the radio or checkbox is checked
|
||||
* @param string $xpath
|
||||
* @return bool
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function isChecked($xpath) {
|
||||
$this->findElement($xpath, 1);
|
||||
$javascript = $this->javascriptTemplateRender("is_checked.js.twig", array("xpath" => $xpath));
|
||||
$checked = $this->browser->evaluate($javascript);
|
||||
|
||||
if ($checked === null) {
|
||||
throw new DriverException("Can not check when the element is not checkbox or radio");
|
||||
}
|
||||
|
||||
return $checked;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the option is selected or not
|
||||
* @param string $xpath
|
||||
* @return bool
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function isSelected($xpath) {
|
||||
$elements = $this->findElement($xpath, 1);
|
||||
$javascript = $this->javascriptTemplateRender("is_selected.js.twig", array("xpath" => $xpath));
|
||||
$tagName = $this->browser->tagName($elements["page_id"], $elements["ids"][0]);
|
||||
if (strcmp(strtolower($tagName), "option") !== 0) {
|
||||
throw new DriverException("Can not assert on element that is not an option");
|
||||
}
|
||||
|
||||
return $this->browser->evaluate($javascript);
|
||||
}
|
||||
}
|
40
vendor/jcalderonzumba/mink-phantomjs-driver/src/HeadersTrait.php
vendored
Normal file
40
vendor/jcalderonzumba/mink-phantomjs-driver/src/HeadersTrait.php
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\Mink\Driver;
|
||||
|
||||
/**
|
||||
* Class HeadersTrait
|
||||
* @package Zumba\Mink\Driver
|
||||
*/
|
||||
trait HeadersTrait {
|
||||
|
||||
/**
|
||||
* Gets the current request response headers
|
||||
* Should be called only after a request, other calls are undefined behaviour
|
||||
* @return array
|
||||
*/
|
||||
public function getResponseHeaders() {
|
||||
return $this->browser->responseHeaders();
|
||||
}
|
||||
|
||||
/**
|
||||
* Current request status code response
|
||||
* @return int
|
||||
*/
|
||||
public function getStatusCode() {
|
||||
return $this->browser->getStatusCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* The name say its all
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
*/
|
||||
public function setRequestHeader($name, $value) {
|
||||
$header = array();
|
||||
$header[$name] = $value;
|
||||
//TODO: as a limitation of the driver it self, we will send permanent for the moment
|
||||
$this->browser->addHeader($header, true);
|
||||
}
|
||||
|
||||
}
|
49
vendor/jcalderonzumba/mink-phantomjs-driver/src/JavascriptTrait.php
vendored
Normal file
49
vendor/jcalderonzumba/mink-phantomjs-driver/src/JavascriptTrait.php
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\Mink\Driver;
|
||||
|
||||
use Behat\Mink\Exception\DriverException;
|
||||
|
||||
/**
|
||||
* Class JavascriptTrait
|
||||
* @package Zumba\Mink\Driver
|
||||
*/
|
||||
trait JavascriptTrait {
|
||||
|
||||
/**
|
||||
* Executes a script on the browser
|
||||
* @param string $script
|
||||
*/
|
||||
public function executeScript($script) {
|
||||
$this->browser->execute($script);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates a script and returns the result
|
||||
* @param string $script
|
||||
* @return mixed
|
||||
*/
|
||||
public function evaluateScript($script) {
|
||||
return $this->browser->evaluate($script);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits some time or until JS condition turns true.
|
||||
*
|
||||
* @param integer $timeout timeout in milliseconds
|
||||
* @param string $condition JS condition
|
||||
* @return boolean
|
||||
* @throws DriverException When the operation cannot be done
|
||||
*/
|
||||
public function wait($timeout, $condition) {
|
||||
$start = microtime(true);
|
||||
$end = $start + $timeout / 1000.0;
|
||||
do {
|
||||
$result = $this->browser->evaluate($condition);
|
||||
usleep(100000);
|
||||
} while (microtime(true) < $end && !$result);
|
||||
|
||||
return (bool)$result;
|
||||
}
|
||||
|
||||
}
|
95
vendor/jcalderonzumba/mink-phantomjs-driver/src/KeyboardTrait.php
vendored
Normal file
95
vendor/jcalderonzumba/mink-phantomjs-driver/src/KeyboardTrait.php
vendored
Normal file
|
@ -0,0 +1,95 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\Mink\Driver;
|
||||
|
||||
use Behat\Mink\Exception\DriverException;
|
||||
|
||||
/**
|
||||
* Class KeyboardTrait
|
||||
* @package Zumba\Mink\Driver
|
||||
*/
|
||||
trait KeyboardTrait {
|
||||
|
||||
/**
|
||||
* Does some normalization for the char we want to do keyboard events with.
|
||||
* @param $char
|
||||
* @throws DriverException
|
||||
* @return string
|
||||
*/
|
||||
protected function normalizeCharForKeyEvent($char) {
|
||||
if (!is_int($char) && !is_string($char)) {
|
||||
throw new DriverException("Unsupported key type, can only be integer or string");
|
||||
}
|
||||
|
||||
if (is_string($char) && strlen($char) !== 1) {
|
||||
throw new DriverException("Key can only have ONE character");
|
||||
}
|
||||
|
||||
$key = $char;
|
||||
if (is_int($char)) {
|
||||
$key = chr($char);
|
||||
}
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does some control and normalization for the key event modifier
|
||||
* @param $modifier
|
||||
* @return string
|
||||
* @throws DriverException
|
||||
*/
|
||||
protected function keyEventModifierControl($modifier) {
|
||||
if ($modifier === null) {
|
||||
$modifier = "none";
|
||||
}
|
||||
|
||||
if (!in_array($modifier, array("none", "alt", "ctrl", "shift", "meta"))) {
|
||||
throw new DriverException("Unsupported key modifier $modifier");
|
||||
}
|
||||
return $modifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a key-down event to the browser element
|
||||
* @param $xpath
|
||||
* @param $char
|
||||
* @param string $modifier
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function keyDown($xpath, $char, $modifier = null) {
|
||||
$element = $this->findElement($xpath, 1);
|
||||
$key = $this->normalizeCharForKeyEvent($char);
|
||||
$modifier = $this->keyEventModifierControl($modifier);
|
||||
return $this->browser->keyEvent($element["page_id"], $element["ids"][0], "keydown", $key, $modifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $xpath
|
||||
* @param string $char
|
||||
* @param string $modifier
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function keyPress($xpath, $char, $modifier = null) {
|
||||
$element = $this->findElement($xpath, 1);
|
||||
$key = $this->normalizeCharForKeyEvent($char);
|
||||
$modifier = $this->keyEventModifierControl($modifier);
|
||||
return $this->browser->keyEvent($element["page_id"], $element["ids"][0], "keypress", $key, $modifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pressed up specific keyboard key.
|
||||
*
|
||||
* @param string $xpath
|
||||
* @param string|integer $char could be either char ('b') or char-code (98)
|
||||
* @param string $modifier keyboard modifier (could be 'ctrl', 'alt', 'shift' or 'meta')
|
||||
*
|
||||
* @throws DriverException When the operation cannot be done
|
||||
*/
|
||||
public function keyUp($xpath, $char, $modifier = null) {
|
||||
$this->findElement($xpath, 1);
|
||||
$element = $this->findElement($xpath, 1);
|
||||
$key = $this->normalizeCharForKeyEvent($char);
|
||||
$modifier = $this->keyEventModifierControl($modifier);
|
||||
return $this->browser->keyEvent($element["page_id"], $element["ids"][0], "keyup", $key, $modifier);
|
||||
}
|
||||
}
|
57
vendor/jcalderonzumba/mink-phantomjs-driver/src/MouseTrait.php
vendored
Normal file
57
vendor/jcalderonzumba/mink-phantomjs-driver/src/MouseTrait.php
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\Mink\Driver;
|
||||
|
||||
use Behat\Mink\Exception\DriverException;
|
||||
|
||||
/**
|
||||
* Class MouseTrait
|
||||
* @package Zumba\Mink\Driver
|
||||
*/
|
||||
trait MouseTrait {
|
||||
|
||||
/**
|
||||
* Generates a mouseover event on the given element by xpath
|
||||
* @param string $xpath
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function mouseOver($xpath) {
|
||||
$element = $this->findElement($xpath, 1);
|
||||
$this->browser->hover($element["page_id"], $element["ids"][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clicks if possible on an element given by xpath
|
||||
* @param string $xpath
|
||||
* @return mixed
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function click($xpath) {
|
||||
$elements = $this->findElement($xpath, 1);
|
||||
$this->browser->click($elements["page_id"], $elements["ids"][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
/**
|
||||
* Double click on element found via xpath
|
||||
* @param string $xpath
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function doubleClick($xpath) {
|
||||
$elements = $this->findElement($xpath, 1);
|
||||
$this->browser->doubleClick($elements["page_id"], $elements["ids"][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Right click on element found via xpath
|
||||
* @param string $xpath
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function rightClick($xpath) {
|
||||
$elements = $this->findElement($xpath, 1);
|
||||
$this->browser->rightClick($elements["page_id"], $elements["ids"][0]);
|
||||
}
|
||||
|
||||
}
|
49
vendor/jcalderonzumba/mink-phantomjs-driver/src/NavigationTrait.php
vendored
Normal file
49
vendor/jcalderonzumba/mink-phantomjs-driver/src/NavigationTrait.php
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\Mink\Driver;
|
||||
|
||||
/**
|
||||
* Trait NavigationTrait
|
||||
* @package Zumba\Mink\Driver
|
||||
*/
|
||||
trait NavigationTrait {
|
||||
/**
|
||||
* Visits a given url
|
||||
* @param string $url
|
||||
*/
|
||||
public function visit($url) {
|
||||
$this->browser->visit($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current url if any
|
||||
* @return string
|
||||
*/
|
||||
public function getCurrentUrl() {
|
||||
return $this->browser->currentUrl();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reloads the page if possible
|
||||
*/
|
||||
public function reload() {
|
||||
$this->browser->reload();
|
||||
}
|
||||
|
||||
/**
|
||||
* Goes forward if possible
|
||||
*/
|
||||
public function forward() {
|
||||
$this->browser->goForward();
|
||||
}
|
||||
|
||||
/**
|
||||
* Goes back if possible
|
||||
*/
|
||||
public function back() {
|
||||
$this->browser->goBack();
|
||||
}
|
||||
|
||||
|
||||
}
|
72
vendor/jcalderonzumba/mink-phantomjs-driver/src/PageContentTrait.php
vendored
Normal file
72
vendor/jcalderonzumba/mink-phantomjs-driver/src/PageContentTrait.php
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\Mink\Driver;
|
||||
|
||||
use Behat\Mink\Exception\DriverException;
|
||||
|
||||
/**
|
||||
* Class PageContentTrait
|
||||
* @package Zumba\Mink\Driver
|
||||
*/
|
||||
trait PageContentTrait {
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getContent() {
|
||||
return $this->browser->getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given xpath, will try to get ALL the text, visible and not visible from such xpath
|
||||
* @param string $xpath
|
||||
* @return string
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function getText($xpath) {
|
||||
$elements = $this->findElement($xpath, 1);
|
||||
//allText works only with ONE element so it will be the first one and also returns new lines that we will remove
|
||||
$text = $this->browser->allText($elements["page_id"], $elements["ids"][0]);
|
||||
$text = trim(str_replace(array("\r", "\r\n", "\n"), ' ', $text));
|
||||
$text = preg_replace('/ {2,}/', ' ', $text);
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inner html of a given xpath
|
||||
* @param string $xpath
|
||||
* @return string
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function getHtml($xpath) {
|
||||
$elements = $this->findElement($xpath, 1);
|
||||
//allText works only with ONE element so it will be the first one
|
||||
return $this->browser->allHtml($elements["page_id"], $elements["ids"][0], "inner");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the outer html of a given xpath
|
||||
* @param string $xpath
|
||||
* @return string
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function getOuterHtml($xpath) {
|
||||
$elements = $this->findElement($xpath, 1);
|
||||
//allText works only with ONE element so it will be the first one
|
||||
return $this->browser->allHtml($elements["page_id"], $elements["ids"][0], "outer");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the binary representation of the current page we are in
|
||||
* @throws DriverException
|
||||
* @return string
|
||||
*/
|
||||
public function getScreenshot() {
|
||||
$options = array("full" => true, "selector" => null);
|
||||
$b64ScreenShot = $this->browser->renderBase64("JPEG", $options);
|
||||
if (($binaryScreenShot = base64_decode($b64ScreenShot, true)) === false) {
|
||||
throw new DriverException("There was a problem while doing the screenshot of the current page");
|
||||
}
|
||||
return $binaryScreenShot;
|
||||
}
|
||||
}
|
164
vendor/jcalderonzumba/mink-phantomjs-driver/src/PhantomJSDriver.php
vendored
Normal file
164
vendor/jcalderonzumba/mink-phantomjs-driver/src/PhantomJSDriver.php
vendored
Normal file
|
@ -0,0 +1,164 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\Mink\Driver;
|
||||
|
||||
use Behat\Mink\Element\NodeElement;
|
||||
use Behat\Mink\Exception\DriverException;
|
||||
|
||||
/**
|
||||
* Class PhantomJSDriver
|
||||
* @package Behat\Mink\Driver
|
||||
*/
|
||||
class PhantomJSDriver extends BasePhantomJSDriver {
|
||||
|
||||
use SessionTrait;
|
||||
use NavigationTrait;
|
||||
use CookieTrait;
|
||||
use HeadersTrait;
|
||||
use JavascriptTrait;
|
||||
use MouseTrait;
|
||||
use PageContentTrait;
|
||||
use KeyboardTrait;
|
||||
use FormManipulationTrait;
|
||||
use WindowTrait;
|
||||
|
||||
/**
|
||||
* Sets the basic auth user and password
|
||||
* @param string $user
|
||||
* @param string $password
|
||||
*/
|
||||
public function setBasicAuth($user, $password) {
|
||||
$this->browser->setHttpAuth($user, $password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the tag name of a given xpath
|
||||
* @param string $xpath
|
||||
* @return string
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function getTagName($xpath) {
|
||||
$elements = $this->findElement($xpath, 1);
|
||||
return $this->browser->tagName($elements["page_id"], $elements["ids"][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the attribute value of a given element and name
|
||||
* @param string $xpath
|
||||
* @param string $name
|
||||
* @return string
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function getAttribute($xpath, $name) {
|
||||
$elements = $this->findElement($xpath, 1);
|
||||
return $this->browser->attribute($elements["page_id"], $elements["ids"][0], $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if element given by xpath is visible or not
|
||||
* @param string $xpath
|
||||
* @return bool
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function isVisible($xpath) {
|
||||
$elements = $this->findElement($xpath, 1);
|
||||
return $this->browser->isVisible($elements["page_id"], $elements["ids"][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drags one element to another
|
||||
* @param string $sourceXpath
|
||||
* @param string $destinationXpath
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function dragTo($sourceXpath, $destinationXpath) {
|
||||
$sourceElement = $this->findElement($sourceXpath, 1);
|
||||
$destinationElement = $this->findElement($destinationXpath, 1);
|
||||
$this->browser->drag($sourceElement["page_id"], $sourceElement["ids"][0], $destinationElement["ids"][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload a file to the browser
|
||||
* @param string $xpath
|
||||
* @param string $path
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function attachFile($xpath, $path) {
|
||||
if (!file_exists($path)) {
|
||||
throw new DriverException("Wow there the file does not exist, you can not upload it");
|
||||
}
|
||||
|
||||
if (($realPath = realpath($path)) === false) {
|
||||
throw new DriverException("Wow there the file does not exist, you can not upload it");
|
||||
}
|
||||
|
||||
$element = $this->findElement($xpath, 1);
|
||||
$tagName = $this->getTagName($xpath);
|
||||
if ($tagName != "input") {
|
||||
throw new DriverException("The element is not an input element, you can not attach a file to it");
|
||||
}
|
||||
|
||||
$attributes = $this->getBrowser()->attributes($element["page_id"], $element["ids"][0]);
|
||||
if (!isset($attributes["type"]) || $attributes["type"] != "file") {
|
||||
throw new DriverException("The element is not an input file type element, you can not attach a file to it");
|
||||
}
|
||||
|
||||
$this->browser->selectFile($element["page_id"], $element["ids"][0], $realPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the browser control inside the IFRAME
|
||||
* You own the control, make sure to go back to the parent calling this method with null
|
||||
* @param string $name
|
||||
*/
|
||||
public function switchToIFrame($name = null) {
|
||||
//TODO: check response of the calls
|
||||
if ($name === null) {
|
||||
$this->browser->popFrame();
|
||||
return;
|
||||
} else {
|
||||
$this->browser->pushFrame($name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus on an element
|
||||
* @param string $xpath
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function focus($xpath) {
|
||||
$element = $this->findElement($xpath, 1);
|
||||
$this->browser->trigger($element["page_id"], $element["ids"][0], "focus");
|
||||
}
|
||||
|
||||
/**
|
||||
* Blur on element
|
||||
* @param string $xpath
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function blur($xpath) {
|
||||
$element = $this->findElement($xpath, 1);
|
||||
$this->browser->trigger($element["page_id"], $element["ids"][0], "blur");
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds elements with specified XPath query.
|
||||
* @param string $xpath
|
||||
* @return NodeElement[]
|
||||
* @throws DriverException When the operation cannot be done
|
||||
*/
|
||||
public function find($xpath) {
|
||||
$elements = $this->browser->find("xpath", $xpath);
|
||||
$nodeElements = array();
|
||||
|
||||
if (!isset($elements["ids"])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach ($elements["ids"] as $i => $elementId) {
|
||||
$nodeElements[] = new NodeElement(sprintf('(%s)[%d]', $xpath, $i + 1), $this->session);
|
||||
}
|
||||
return $nodeElements;
|
||||
}
|
||||
|
||||
}
|
35
vendor/jcalderonzumba/mink-phantomjs-driver/src/Resources/Script/check_element.js.twig
vendored
Normal file
35
vendor/jcalderonzumba/mink-phantomjs-driver/src/Resources/Script/check_element.js.twig
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
{% autoescape 'js' %}
|
||||
(function (xpath, check) {
|
||||
function getPolterNode(xpath) {
|
||||
var polterAgent = window.__poltergeist;
|
||||
var ids = polterAgent.find("xpath", xpath, document);
|
||||
return polterAgent.get(ids[0]);
|
||||
}
|
||||
|
||||
var pNode = getPolterNode(xpath);
|
||||
|
||||
if (check && pNode.element.checked) {
|
||||
//requested to check the element and is already check, do nothing.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!check && pNode.element.checked == false) {
|
||||
//move along nothing to be done
|
||||
return true;
|
||||
}
|
||||
|
||||
if (check && pNode.element.checked == false) {
|
||||
//we have to check the element, we will do so by triggering a click event so all change listeners are aware.
|
||||
pNode.trigger("click");
|
||||
pNode.element.checked = true;
|
||||
}
|
||||
|
||||
if (!check && pNode.element.checked) {
|
||||
//move along nothing to be done
|
||||
pNode.trigger("click");
|
||||
pNode.element.checked = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}('{{xpath}}', {{check}}));
|
||||
{% endautoescape %}
|
3
vendor/jcalderonzumba/mink-phantomjs-driver/src/Resources/Script/execute_script.js.twig
vendored
Normal file
3
vendor/jcalderonzumba/mink-phantomjs-driver/src/Resources/Script/execute_script.js.twig
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
{% autoescape false %}
|
||||
{{ script }};
|
||||
{% endautoescape %}
|
63
vendor/jcalderonzumba/mink-phantomjs-driver/src/Resources/Script/get_value.js.twig
vendored
Normal file
63
vendor/jcalderonzumba/mink-phantomjs-driver/src/Resources/Script/get_value.js.twig
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
{% autoescape 'js' %}
|
||||
(function (xpath) {
|
||||
function getElement(xpath) {
|
||||
var polterAgent = window.__poltergeist;
|
||||
var ids = polterAgent.find("xpath", xpath, document);
|
||||
var polterNode = polterAgent.get(ids[0]);
|
||||
return polterNode.element;
|
||||
}
|
||||
|
||||
function inputRadioGetValue(element){
|
||||
var value = null;
|
||||
var name = element.getAttribute('name');
|
||||
if (!name){
|
||||
return null;
|
||||
}
|
||||
var fields = window.document.getElementsByName(name);
|
||||
var i;
|
||||
var l = fields.length;
|
||||
for (i = 0; i < l; i++) {
|
||||
var field = fields.item(i);
|
||||
if (field.form === element.form && field.checked) {
|
||||
return field.value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
var node = getElement(xpath);
|
||||
var tagName = node.tagName.toLowerCase();
|
||||
var value = null;
|
||||
if (tagName == "input") {
|
||||
var type = node.type.toLowerCase();
|
||||
if (type == "checkbox") {
|
||||
value = node.checked ? node.value : null;
|
||||
} else if (type == "radio") {
|
||||
value = inputRadioGetValue(node);
|
||||
} else {
|
||||
value = node.value;
|
||||
}
|
||||
} else if (tagName == "textarea") {
|
||||
value = node.value;
|
||||
} else if (tagName == "select") {
|
||||
if (node.multiple) {
|
||||
value = [];
|
||||
for (var i = 0; i < node.options.length; i++) {
|
||||
if (node.options[i].selected) {
|
||||
value.push(node.options[i].value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var idx = node.selectedIndex;
|
||||
if (idx >= 0) {
|
||||
value = node.options.item(idx).value;
|
||||
} else {
|
||||
value = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
value = node.value;
|
||||
}
|
||||
return value;
|
||||
}('{{ xpath }}'));
|
||||
{% endautoescape %}
|
31
vendor/jcalderonzumba/mink-phantomjs-driver/src/Resources/Script/is_checked.js.twig
vendored
Normal file
31
vendor/jcalderonzumba/mink-phantomjs-driver/src/Resources/Script/is_checked.js.twig
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
{% autoescape 'js' %}
|
||||
(function (xpath) {
|
||||
function getElement(xpath, within) {
|
||||
var result;
|
||||
if (within === null || within === undefined) {
|
||||
within = document;
|
||||
}
|
||||
result = document.evaluate(xpath, within, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
||||
if (result.snapshotLength !== 1) {
|
||||
return null;
|
||||
}
|
||||
return result.snapshotItem(0);
|
||||
}
|
||||
|
||||
var node = getElement(xpath);
|
||||
|
||||
if (node === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if(node.tagName.toLowerCase() != "input"){
|
||||
return null;
|
||||
}
|
||||
|
||||
if(node.type.toLowerCase() != "checkbox" && node.type.toLowerCase() != "radio"){
|
||||
return null;
|
||||
}
|
||||
|
||||
return node.checked;
|
||||
}('{{ xpath }}'));
|
||||
{% endautoescape %}
|
16
vendor/jcalderonzumba/mink-phantomjs-driver/src/Resources/Script/is_selected.js.twig
vendored
Normal file
16
vendor/jcalderonzumba/mink-phantomjs-driver/src/Resources/Script/is_selected.js.twig
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
{% autoescape 'js' %}
|
||||
(function (xpath) {
|
||||
function getElement(xpath) {
|
||||
var polterAgent = window.__poltergeist;
|
||||
var ids = polterAgent.find("xpath", xpath, document);
|
||||
var polterNode = polterAgent.get(ids[0]);
|
||||
return polterNode.element;
|
||||
}
|
||||
|
||||
var node = getElement(xpath);
|
||||
if(typeof node.selected == "undefined"){
|
||||
return null;
|
||||
}
|
||||
return node.selected;
|
||||
}('{{xpath}}'));
|
||||
{% endautoescape %}
|
213
vendor/jcalderonzumba/mink-phantomjs-driver/src/Resources/Script/set_value.js.twig
vendored
Normal file
213
vendor/jcalderonzumba/mink-phantomjs-driver/src/Resources/Script/set_value.js.twig
vendored
Normal file
|
@ -0,0 +1,213 @@
|
|||
{% autoescape 'js' %}
|
||||
(function (xpath, value) {
|
||||
function getElement(xpath, within) {
|
||||
var result;
|
||||
if (within === null || within === undefined) {
|
||||
within = document;
|
||||
}
|
||||
result = document.evaluate(xpath, within, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
||||
if (result.snapshotLength !== 1) {
|
||||
return null;
|
||||
}
|
||||
return result.snapshotItem(0);
|
||||
}
|
||||
|
||||
function isInput(element) {
|
||||
if (element === null || element === undefined) {
|
||||
return false;
|
||||
}
|
||||
return (element.tagName.toLowerCase() == "input");
|
||||
}
|
||||
|
||||
function isTextArea(element) {
|
||||
if (element === null || element === undefined) {
|
||||
return false;
|
||||
}
|
||||
return (element.tagName.toLowerCase() == "textarea");
|
||||
}
|
||||
|
||||
function isSelect(element) {
|
||||
if (element === null || element === undefined) {
|
||||
return false;
|
||||
}
|
||||
return (element.tagName.toLowerCase() == "select");
|
||||
}
|
||||
|
||||
function deselectAllOptions(element) {
|
||||
var i, l = element.options.length;
|
||||
for (i = 0; i < l; i++) {
|
||||
element.options[i].selected = false;
|
||||
}
|
||||
}
|
||||
|
||||
function xpathStringLiteral(s) {
|
||||
if (s.indexOf('"') === -1)
|
||||
return '"' + s + '"';
|
||||
if (s.indexOf("'") === -1)
|
||||
return "'" + s + "'";
|
||||
return 'concat("' + s.replace(/"/g, '",\'"\',"') + '")';
|
||||
}
|
||||
|
||||
function clickOnElement(element) {
|
||||
// create a mouse click event
|
||||
var event = document.createEvent('MouseEvents');
|
||||
event.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
|
||||
|
||||
// send click to element
|
||||
element.dispatchEvent(event);
|
||||
|
||||
//After dispatching the event let's wait for 2 seconds at least...
|
||||
return setTimeout(function () {
|
||||
}, 2);
|
||||
}
|
||||
|
||||
function dispatchChange(element) {
|
||||
var tagName =element.tagName.toLowerCase();
|
||||
var elementType = element.getAttribute("type");
|
||||
if (tagName != "option" || (tagName == "input" && elementType == "radio")){
|
||||
return true;
|
||||
}
|
||||
//Force the change when element is option
|
||||
var event;
|
||||
event = document.createEvent('HTMLEvents');
|
||||
event.initEvent('change', true, false);
|
||||
element.dispatchEvent(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
function selectOptionOnElement(element, option, multiple) {
|
||||
var polterAgent = window.__poltergeist;
|
||||
var escapedOption = xpathStringLiteral(option);
|
||||
// The value of an option is the normalized version of its text when it has no value attribute
|
||||
var optionQuery = ".//option[@value = " + escapedOption + " or (not(@value) and normalize-space(.) = " + escapedOption + ")]";
|
||||
var ids = polterAgent.find("xpath", optionQuery, element);
|
||||
var polterNode = polterAgent.get(ids[0]);
|
||||
var optionElement = polterNode.element;
|
||||
|
||||
if (multiple || !element.multiple) {
|
||||
if (!optionElement.selected) {
|
||||
clickOnElement(optionElement);
|
||||
optionElement.selected = true;
|
||||
}
|
||||
return dispatchChange(optionElement);
|
||||
}
|
||||
|
||||
deselectAllOptions(element);
|
||||
clickOnElement(optionElement);
|
||||
optionElement.selected = true;
|
||||
return dispatchChange(optionElement);
|
||||
}
|
||||
|
||||
function selectSetValue(element, value) {
|
||||
var option;
|
||||
if ((Array.isArray && Array.isArray(value)) || (value instanceof Array)) {
|
||||
deselectAllOptions(element);
|
||||
for (option in value) {
|
||||
if (value.hasOwnProperty(option)) {
|
||||
selectOptionOnElement(element, value[option], true);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
selectOptionOnElement(element, value, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
function selectRadioValue(element, value) {
|
||||
if (element.value === value) {
|
||||
clickOnElement(element);
|
||||
element.checked=true;
|
||||
dispatchChange(element);
|
||||
return true;
|
||||
}
|
||||
|
||||
var formElements = element.form.elements;
|
||||
var name = element.getAttribute("name");
|
||||
var radioElement, i;
|
||||
|
||||
if (!name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (i = 0; i < formElements.length; i++) {
|
||||
radioElement = formElements[i];
|
||||
if (radioElement.tagName.toLowerCase() == 'input' && radioElement.type.toLowerCase() == 'radio' && radioElement.name === name) {
|
||||
if (value === radioElement.value) {
|
||||
clickOnElement(radioElement);
|
||||
radioElement.checked=true;
|
||||
dispatchChange(radioElement);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function inputSetValue(element, value, elementXpath) {
|
||||
var allowedTypes = ['submit', 'image', 'button', 'reset'];
|
||||
var elementType = element.type.toLowerCase();
|
||||
var textLikeInputType = ['file', 'text', 'password', 'url', 'email', 'search', 'number', 'tel', 'range', 'date', 'month', 'week', 'time', 'datetime', 'color', 'datetime-local'];
|
||||
|
||||
if (allowedTypes.indexOf(elementType) !== -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (elementType == "checkbox") {
|
||||
var booleanValue = false;
|
||||
if (value == "1" || value == 1) {
|
||||
booleanValue = true;
|
||||
} else if (value == "0" || value == 0) {
|
||||
booleanValue = false;
|
||||
}
|
||||
if ((element.checked && !booleanValue) || (!element.checked && booleanValue)) {
|
||||
clickOnElement(element);
|
||||
dispatchChange(element);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (elementType == "radio") {
|
||||
return selectRadioValue(element, value);
|
||||
}
|
||||
|
||||
if (textLikeInputType.indexOf(elementType) !== -1) {
|
||||
return textAreaSetValue(elementXpath, value);
|
||||
}
|
||||
|
||||
//No support for the moment for file stuff or other input types
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
function textAreaSetValue(elementXpath, value) {
|
||||
var polterAgent = window.__poltergeist;
|
||||
var ids = polterAgent.find("xpath", elementXpath, document);
|
||||
var polterNode = polterAgent.get(ids[0]);
|
||||
polterNode.set(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
var node = getElement(xpath);
|
||||
if (node === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isSelect(node)) {
|
||||
return selectSetValue(node, value);
|
||||
}
|
||||
|
||||
if (isInput(node)) {
|
||||
return inputSetValue(node, value, xpath);
|
||||
}
|
||||
|
||||
if (isTextArea(node)) {
|
||||
return textAreaSetValue(xpath, value);
|
||||
}
|
||||
|
||||
//for the moment everything else also to textArea stuff
|
||||
return textAreaSetValue(xpath, value);
|
||||
|
||||
}('{{xpath}}', JSON.parse('{{ value }}')));
|
||||
{% endautoescape %}
|
50
vendor/jcalderonzumba/mink-phantomjs-driver/src/SessionTrait.php
vendored
Normal file
50
vendor/jcalderonzumba/mink-phantomjs-driver/src/SessionTrait.php
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace Zumba\Mink\Driver;
|
||||
|
||||
/**
|
||||
* Trait SessionTrait
|
||||
* @package Zumba\Mink\Driver
|
||||
*/
|
||||
trait SessionTrait {
|
||||
|
||||
/** @var bool */
|
||||
protected $started;
|
||||
|
||||
/**
|
||||
* Starts a session to be used by the driver client
|
||||
*/
|
||||
public function start() {
|
||||
$this->started = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if the session is started or not
|
||||
* @return bool
|
||||
*/
|
||||
public function isStarted() {
|
||||
return $this->started;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the session completely, clean slate for the browser
|
||||
* @return bool
|
||||
*/
|
||||
public function stop() {
|
||||
//Since we are using a remote browser "API", stopping is just like resetting, say good bye to cookies
|
||||
//TODO: In the future we may want to control a start / stop of the remove browser
|
||||
return $this->reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the cookies in the browser, all of them
|
||||
* @return bool
|
||||
*/
|
||||
public function reset() {
|
||||
$this->getBrowser()->clearCookies();
|
||||
$this->getBrowser()->reset();
|
||||
$this->started = false;
|
||||
return true;
|
||||
}
|
||||
}
|
64
vendor/jcalderonzumba/mink-phantomjs-driver/src/WindowTrait.php
vendored
Normal file
64
vendor/jcalderonzumba/mink-phantomjs-driver/src/WindowTrait.php
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
namespace Zumba\Mink\Driver;
|
||||
|
||||
use Behat\Mink\Exception\DriverException;
|
||||
|
||||
/**
|
||||
* Class WindowTrait
|
||||
* @package Zumba\Mink\Driver
|
||||
*/
|
||||
trait WindowTrait {
|
||||
/**
|
||||
* Returns the current page window name
|
||||
* @return string
|
||||
*/
|
||||
public function getWindowName() {
|
||||
return $this->browser->windowName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the window handles currently present in phantomjs
|
||||
* @return array
|
||||
*/
|
||||
public function getWindowNames() {
|
||||
return $this->browser->windowHandles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches to window by name if possible
|
||||
* @param $name
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function switchToWindow($name = null) {
|
||||
$handles = $this->browser->windowHandles();
|
||||
if ($name === null) {
|
||||
//null means back to the main window
|
||||
return $this->browser->switchToWindow($handles[0]);
|
||||
}
|
||||
|
||||
$windowHandle = $this->browser->windowHandle($name);
|
||||
if (!empty($windowHandle)) {
|
||||
$this->browser->switchToWindow($windowHandle);
|
||||
} else {
|
||||
throw new DriverException("Could not find window handle by a given window name: $name");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizing a window with specified size
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* @param string $name
|
||||
* @throws DriverException
|
||||
*/
|
||||
public function resizeWindow($width, $height, $name = null) {
|
||||
if ($name !== null) {
|
||||
//TODO: add this on the phantomjs stuff
|
||||
throw new DriverException("Resizing other window than the main one is not supported yet");
|
||||
}
|
||||
$this->browser->resize($width, $height);
|
||||
}
|
||||
|
||||
}
|
Reference in a new issue