├── .envrc ├── .gitignore ├── phpspec.yml ├── .editorconfig ├── features ├── take-the-screenshot.feature ├── the-screen-size.feature ├── the-theme-should-be-activated.feature ├── not-logged-in.feature ├── the-wordpress-version-should-be.feature ├── hover-over-the-element.feature ├── wait-something.feature ├── should-be-logged-in.feature ├── http-response.feature ├── login-as-user-and-password.feature ├── bootstrap │ └── FeatureContext.php ├── login-as-the-role.feature └── plugins.feature ├── .travis.yml ├── spec ├── ServiceContainer │ └── WordPressExtensionSpec.php └── Context │ ├── WordPressContextSpec.php │ ├── Initializer │ └── WordPressInitializerSpec.php │ └── RawWordPressContextSpec.php ├── package.json ├── .github └── CONTRIBUTING.md ├── bin ├── run-behat.js └── run-phpspec.js ├── composer.json ├── behat.yml.dist ├── src ├── Context │ ├── Initializer │ │ └── WordPressInitializer.php │ ├── RawWordPressContext.php │ └── WordPressContext.php └── ServiceContainer │ └── WordPressExtension.php ├── LICENSE ├── README.md └── composer.lock /.envrc: -------------------------------------------------------------------------------- 1 | export WP_VERSION=latest 2 | export WP_THEME=twentyseventeen 3 | export WP_PATH=/tmp/wp-tests 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | /behat.yml 3 | /node_modules/ 4 | /npm-debug.log 5 | /vendor/ 6 | /wp-cli.yml 7 | /wp-cli-nightly.phar 8 | -------------------------------------------------------------------------------- /phpspec.yml: -------------------------------------------------------------------------------- 1 | suites: 2 | main_suite: 3 | namespace: VCCW\Behat\Mink\WordPressExtension 4 | psr4_prefix: VCCW\Behat\Mink\WordPressExtension 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.php] 12 | indent_style = tab 13 | indent_size = 4 14 | -------------------------------------------------------------------------------- /features/take-the-screenshot.feature: -------------------------------------------------------------------------------- 1 | Feature: Take the screenshot 2 | 3 | Scenario: Take the screenshot of the current page 4 | 5 | Given the screen size is 1440x900 6 | And I login as the "administrator" role 7 | 8 | When I am on "/wp-admin/" 9 | Then take a screenshot and save it to "/tmp/test-1.png" 10 | -------------------------------------------------------------------------------- /features/the-screen-size.feature: -------------------------------------------------------------------------------- 1 | Feature: The screen size 2 | 3 | Scenario: The screen size is 1440x900 4 | Given I login as the "administrator" role 5 | And I am on "/wp-admin/" 6 | 7 | When the screen size is 1440x900 8 | Then I should see "Dashboard" in the "#adminmenu" element 9 | 10 | When the screen size is 320x400 11 | Then I should not see "Dashboard" in the "#adminmenu" element 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - '7.1' 5 | - '5.6' 6 | 7 | env: 8 | matrix: 9 | - WP_VERSION=nightly WP_THEME=twentyseventeen 10 | - WP_VERSION=latest WP_THEME=twentyseventeen 11 | 12 | before_install: 13 | - nvm install node 14 | - nvm alias default node 15 | - node --version 16 | - composer install 17 | - npm install 18 | - npm run install-wp 19 | - npm run wp >/dev/null 2>&1 & 20 | 21 | script: 22 | - npm test 23 | -------------------------------------------------------------------------------- /spec/ServiceContainer/WordPressExtensionSpec.php: -------------------------------------------------------------------------------- 1 | shouldHaveType( 'Behat\Testwork\ServiceContainer\Extension' ); 12 | } 13 | 14 | function it_is_named_wp() 15 | { 16 | $this->getConfigKey()->shouldReturn('wp'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /features/the-theme-should-be-activated.feature: -------------------------------------------------------------------------------- 1 | Feature: Get current theme 2 | 3 | Scenario: Get current theme 4 | 5 | When I login as the "administrator" role 6 | And save env $WP_THEME as {WP_THEME} 7 | Then the "{WP_THEME}" theme should be activated 8 | 9 | @mink:goutte 10 | Scenario: Get current theme 11 | 12 | When I login as the "administrator" role 13 | And save env $WP_THEME as {WP_THEME} 14 | Then the "{WP_THEME}" theme should be activated 15 | -------------------------------------------------------------------------------- /features/not-logged-in.feature: -------------------------------------------------------------------------------- 1 | Feature: Logout from the WordPress 2 | 3 | Scenario: Logout 4 | 5 | Given I login as the "administrator" role 6 | 7 | When I logout 8 | Then I should see "You are now logged out." 9 | And I am not logged in 10 | 11 | @mink:goutte 12 | Scenario: Logout with goutte driver 13 | 14 | Given I login as the "administrator" role 15 | 16 | When I logout 17 | Then I should see "You are now logged out." 18 | And I am not logged in 19 | -------------------------------------------------------------------------------- /features/the-wordpress-version-should-be.feature: -------------------------------------------------------------------------------- 1 | Feature: WordPress version feature 2 | 3 | Scenario: WordPress version should be equal with $WP_VERSION 4 | 5 | When save env $WP_VERSION as {WP_VERSION} 6 | Then the WordPress version should be "{WP_VERSION}" 7 | 8 | @min:goutte 9 | Scenario: WordPress version should be equal with $WP_VERSION with goutte driver 10 | 11 | When save env $WP_VERSION as {WP_VERSION} 12 | Then the WordPress version should be "{WP_VERSION}" 13 | 14 | -------------------------------------------------------------------------------- /features/hover-over-the-element.feature: -------------------------------------------------------------------------------- 1 | Feature: Hover over the element 2 | 3 | Scenario: I hover over the specific element 4 | 5 | Given the screen size is 1440x900 6 | And I login as the "administrator" role 7 | 8 | When I am on "/wp-admin/" 9 | And I wait the "#wp-admin-bar-my-account" element be loaded 10 | And I hover over the "#wp-admin-bar-my-account" element 11 | And I wait for 3 seconds 12 | Then I should see "Edit My Profile" 13 | And I should see "Log Out" 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "install-wp": "curl https://raw.githubusercontent.com/vccw-team/install-wp/master/install-wp.sh | /usr/bin/env bash", 4 | "wp": "curl https://raw.githubusercontent.com/vccw-team/install-wp/master/run-wp.sh | /usr/bin/env bash", 5 | "phpspec": "/usr/bin/env node bin/run-phpspec.js", 6 | "behat": "/usr/bin/env node bin/run-behat.js", 7 | "test": "npm run phpspec && npm run behat" 8 | }, 9 | "devDependencies": { 10 | "phantomjs-prebuilt": "^2.1.13" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /features/wait-something.feature: -------------------------------------------------------------------------------- 1 | Feature: I wait something happen 2 | 3 | Scenario: I wait the specific element be loaded 4 | 5 | Given the screen size is 1440x900 6 | And I login as the "administrator" role 7 | 8 | When I am on "/" 9 | And I wait the "#wpadminbar" element be loaded 10 | Then I should see "Howdy," 11 | 12 | When I am on "/" 13 | And I wait for a second 14 | Then I should see "Welcome" 15 | 16 | When I am on "/" 17 | And I wait for 2 seconds 18 | Then I should see "Welcome" 19 | -------------------------------------------------------------------------------- /features/should-be-logged-in.feature: -------------------------------------------------------------------------------- 1 | Feature: I should be logged in or not 2 | 3 | Scenario: Login as the "administrator" role then logout 4 | 5 | Given the screen size is 1440x900 6 | 7 | When I login as the "administrator" role 8 | Then I should be logged in 9 | 10 | When I logout 11 | Then I should not be logged in 12 | 13 | @mink:goutte 14 | Scenario: Login as the "administrator" role then logout with goutte driver 15 | 16 | When I login as the "administrator" role 17 | Then I should be logged in 18 | 19 | When I logout 20 | Then I should not be logged in 21 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ## Automated Testing 4 | 5 | Clone this repository. 6 | 7 | ``` 8 | $ git clone git@github.com:vccw-team/wordpress-extension.git 9 | ``` 10 | 11 | Change into the directory. 12 | 13 | ``` 14 | $ cd wordpress-extension 15 | ``` 16 | 17 | Install dependencies. 18 | 19 | ``` 20 | $ npm install 21 | $ composer install 22 | ``` 23 | 24 | Start a WordPress server. 25 | 26 | ``` 27 | $ export WP_VERSION=latest 28 | $ export WP_THEME=twentysixteen 29 | $ npm run install-wp 30 | $ npm run wp 31 | ``` 32 | 33 | Run the test! 34 | 35 | ``` 36 | $ npm test 37 | ``` 38 | -------------------------------------------------------------------------------- /bin/run-behat.js: -------------------------------------------------------------------------------- 1 | const phantomjs = require( 'phantomjs-prebuilt' ) 2 | const spawn = require( 'child_process' ).spawn 3 | 4 | const argv = process.argv 5 | argv.shift() 6 | argv.shift() 7 | 8 | args = [ 9 | 'php', 10 | '-d', 11 | 'memory_limit=-1', 12 | 'vendor/bin/behat' 13 | ] 14 | 15 | phantomjs.run( 16 | '--webdriver=4444', 17 | '--ignore-ssl-errors=yes', 18 | '--cookies-file=/tmp/webdriver_cookie.txt' 19 | ).then( program => { 20 | const behat = spawn( '/usr/bin/env', args.concat( argv ), { stdio: "inherit" } ) 21 | behat.on( 'exit', ( code ) => { 22 | program.kill() 23 | process.exit( code ); 24 | } ) 25 | } ) 26 | -------------------------------------------------------------------------------- /features/http-response.feature: -------------------------------------------------------------------------------- 1 | Feature: HTTP response 2 | 3 | @mink:goutte 4 | Scenario: Check http status code 5 | 6 | When I am on "/" 7 | Then the HTTP status should be 200 8 | 9 | When I am on "/the-page-not-found" 10 | Then the HTTP status should be 404 11 | 12 | @mink:goutte 13 | Scenario: Check http response headers 14 | 15 | When I am on "/" 16 | Then the HTTP headers should be: 17 | | header | value | 18 | | Content-Type | text/html; charset=UTF-8 | 19 | | Connection | close | 20 | | Host | 127.0.0.1:8080 | 21 | -------------------------------------------------------------------------------- /bin/run-phpspec.js: -------------------------------------------------------------------------------- 1 | const phantomjs = require( 'phantomjs-prebuilt' ) 2 | const spawn = require( 'child_process' ).spawn 3 | 4 | const argv = process.argv 5 | argv.shift() 6 | argv.shift() 7 | 8 | args = [ 9 | 'php', 10 | '-d', 11 | 'memory_limit=-1', 12 | 'vendor/bin/phpspec', 13 | 'run' 14 | ] 15 | 16 | phantomjs.run( 17 | '--webdriver=4444', 18 | '--ignore-ssl-errors=yes', 19 | '--cookies-file=/tmp/webdriver_cookie.txt' 20 | ).then( program => { 21 | const behat = spawn( '/usr/bin/env', args.concat( argv ), { stdio: "inherit" } ) 22 | behat.on( 'exit', ( code ) => { 23 | program.kill() 24 | process.exit( code ); 25 | } ) 26 | } ) 27 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vccw-team/wordpress-extension", 3 | "description": "WordPress extension for the Behat", 4 | "license": "MIT", 5 | "authors": [ 6 | { 7 | "name": "Takayuki Miyauchi", 8 | "email": "miya0001@users.noreply.github.com" 9 | } 10 | ], 11 | "require": { 12 | "behat/behat": "~3.2", 13 | "behat/mink": "~1.7", 14 | "behat/mink-extension": "~2.2", 15 | "behat/mink-selenium2-driver": "~1.3.1", 16 | "behat/mink-goutte-driver": "^1.2" 17 | }, 18 | "require-dev": { 19 | "phpspec/phpspec": "^3.1" 20 | }, 21 | "autoload": { 22 | "psr-4": { 23 | "VCCW\\Behat\\Mink\\WordPressExtension\\": "src/" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /behat.yml.dist: -------------------------------------------------------------------------------- 1 | default: 2 | suites: 3 | default: 4 | paths: 5 | - %paths.base%/features 6 | contexts: 7 | - FeatureContext 8 | - VCCW\Behat\Mink\WordPressExtension\Context\WordPressContext 9 | - Behat\MinkExtension\Context\MinkContext 10 | extensions: 11 | VCCW\Behat\Mink\WordPressExtension: 12 | roles: 13 | administrator: 14 | username: admin 15 | password: admin 16 | editor: 17 | username: editor 18 | password: editor 19 | Behat\MinkExtension: 20 | base_url: http://127.0.0.1:8080 21 | default_session: default 22 | sessions: 23 | default: 24 | selenium2: 25 | wd_host: http://127.0.0.1:4444/wd/hub 26 | goutte: 27 | goutte: ~ 28 | -------------------------------------------------------------------------------- /features/login-as-user-and-password.feature: -------------------------------------------------------------------------------- 1 | Feature: I login as the specfic role 2 | 3 | Scenario: Login as user "admin" with password "admin" 4 | 5 | When I login as "admin" with password "admin" 6 | Then I should be logged in 7 | And I should see "Dashboard" 8 | 9 | Scenario: Login as user "admin" with incorrect password 10 | 11 | When I try to login as "admin" with password "1111" 12 | Then I should see "ERROR:" 13 | 14 | @mink:goutte 15 | Scenario: Login as user "admin" with password "admin" with goutte driver 16 | 17 | When I login as "admin" with password "admin" 18 | Then I should be logged in 19 | And I should see "Dashboard" 20 | 21 | @mink:goutte 22 | Scenario: Login as user "admin" with incorrect password with goutte driver 23 | 24 | When I try to login as "admin" with password "1111" 25 | Then I should see "ERROR:" 26 | -------------------------------------------------------------------------------- /src/Context/Initializer/WordPressInitializer.php: -------------------------------------------------------------------------------- 1 | parameters = $parameters; 21 | } 22 | 23 | /** 24 | * Initializes provided context. 25 | * 26 | * @param Context $context 27 | */ 28 | public function initializeContext( Context $context ) 29 | { 30 | if ( $context instanceof RawWordPressContext ) { 31 | $context->set_params( $this->parameters ); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /features/bootstrap/FeatureContext.php: -------------------------------------------------------------------------------- 1 | getTestResult()->getResultCode()) { 32 | $screenshot = $this->getSession()->getDriver()->getScreenshot(); 33 | file_put_contents( '/tmp/behat-'.time().".png", $screenshot ); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /features/login-as-the-role.feature: -------------------------------------------------------------------------------- 1 | Feature: I login as the specfic role 2 | 3 | Scenario: Login as the "administrator" role 4 | 5 | Given the screen size is 1440x900 6 | 7 | When I login as the "administrator" role 8 | Then I should see "Dashboard" 9 | 10 | When I am on "/wp-admin/plugins.php" 11 | Then I should see "Howdy, admin" 12 | Then I should see "Plugins" 13 | 14 | When I logout 15 | Then I should see "You are now logged out." 16 | 17 | Scenario: Login as the "editor" role 18 | 19 | Given the screen size is 1440x900 20 | 21 | When I login as the "editor" role 22 | Then I should see "Dashboard" 23 | 24 | When I am on "/wp-admin/plugins.php" 25 | Then I should see "Sorry, you are not allowed to access this page." 26 | 27 | @mink:goutte 28 | Scenario: Login as the "editor" role with goutte driver 29 | 30 | When I login as the "editor" role 31 | Then I should see "Dashboard" 32 | 33 | When I am on "/wp-admin/plugins.php" 34 | Then I should see "Sorry, you are not allowed to access this page." 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Takayuki Miyauchi 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /spec/Context/WordPressContextSpec.php: -------------------------------------------------------------------------------- 1 | shouldHaveType( 'VCCW\Behat\Mink\WordPressExtension\Context\RawWordPressContext' ); 18 | } 19 | 20 | public function it_should_check_status() 21 | { 22 | $this->init_mink( 'goutte' ); 23 | $session = $this->getSession(); 24 | 25 | $session->visit( 'http://127.0.0.1:8080/' ); 26 | $this->shouldThrow( new \Exception( 'The HTTP status is 200, but it should be 404' ) )->during( 27 | 'the_http_status_should_be', 28 | array( 404 ) 29 | ); 30 | } 31 | 32 | private function init_mink( $driver ) 33 | { 34 | $mink = new Mink( array( 35 | 'goutte' => new Session( new GoutteDriver( new GoutteClient() ) ), 36 | 'selenium2' => new Session( new Selenium2Driver() ), 37 | ) ); 38 | $mink->setDefaultSessionName( $driver ); 39 | $this->setMink( $mink ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /features/plugins.feature: -------------------------------------------------------------------------------- 1 | Feature: Get statuses of plugins 2 | 3 | Scenario: Tests for plugins 4 | 5 | When I login as the "administrator" role 6 | Then the plugins should be: 7 | | slug | status | 8 | | akismet | inactive | 9 | | wordpress-importer | active | 10 | And the "akismet" plugin should be installed 11 | And the "wordpress-importer" plugin should be activated 12 | And the "my-plugin" plugin should not be installed 13 | And the "akismet" plugin should not be activated 14 | And I activate the "hello-dolly" plugin 15 | And I deactivate the "hello-dolly" plugin 16 | 17 | @mink:goutte 18 | Scenario: Get plugins with goutte driver 19 | 20 | When I login as the "administrator" role 21 | Then the plugins should be: 22 | | slug | status | 23 | | hello-dolly | inactive | 24 | | wordpress-importer | active | 25 | And the "akismet" plugin should be installed 26 | And the "wordpress-importer" plugin should be activated 27 | And the "my-plugin" plugin should not be installed 28 | And the "akismet" plugin should not be activated 29 | And I activate the "hello-dolly" plugin 30 | And I deactivate the "hello-dolly" plugin 31 | -------------------------------------------------------------------------------- /spec/Context/Initializer/WordPressInitializerSpec.php: -------------------------------------------------------------------------------- 1 | beConstructedWith( $this->get_mock_params() ); 17 | } 18 | 19 | public function it_is_a_context_initializer_extension() 20 | { 21 | $this->shouldHaveType( 'Behat\Behat\Context\Initializer\ContextInitializer' ); 22 | } 23 | 24 | public function it_does_nothing_for_basic_contexts( Context $context ) 25 | { 26 | $this->initializeContext( $context ); 27 | } 28 | 29 | public function it_injects_mink_and_parameters_in_mink_aware_contexts( RawWordPressContext $context ) 30 | { 31 | $context->set_params( $this->get_mock_params() )->shouldBeCalled(); 32 | $this->initializeContext( $context ); 33 | } 34 | 35 | /** 36 | * The parameters for the mockup 37 | * 38 | * @return array The parameters for the initializer. 39 | */ 40 | private function get_mock_params() 41 | { 42 | return json_decode( '{ 43 | "roles": { 44 | "administrator": { 45 | "username": "admin", 46 | "password": "admin" 47 | }, 48 | "editor": { 49 | "username": "editor", 50 | "password": "xxxx" 51 | } 52 | }, 53 | "admin_url": "/wp-admin" 54 | }', true ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/ServiceContainer/WordPressExtension.php: -------------------------------------------------------------------------------- 1 | addDefaultsIfNotSet() 37 | ->children() 38 | ->arrayNode( 'roles' ) 39 | ->prototype('array') 40 | ->children() 41 | ->scalarNode('username')->end() 42 | ->scalarNode('password')->end() 43 | ->end() 44 | ->end() 45 | ->end() 46 | ->scalarNode( 'admin_url' ) 47 | ->defaultValue( '/wp-admin') 48 | ->end() 49 | ->end(); 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | public function load( ContainerBuilder $container, array $config ) 56 | { 57 | $definition = new Definition( 58 | 'VCCW\Behat\Mink\WordPressExtension\Context\Initializer\WordPressInitializer', 59 | array( 60 | $config, 61 | ) 62 | ); 63 | $definition->addTag( ContextExtension::INITIALIZER_TAG ); 64 | $container->setDefinition( 'wp.context_initializer', $definition ); 65 | } 66 | 67 | /** 68 | * {@inheritdoc} 69 | */ 70 | public function process( ContainerBuilder $container ) 71 | { 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /spec/Context/RawWordPressContextSpec.php: -------------------------------------------------------------------------------- 1 | shouldHaveType( 'VCCW\Behat\Mink\WordPressExtension\Context\RawWordPressContext' ); 18 | } 19 | 20 | public function it_can_set_and_get_parameters() 21 | { 22 | $params = json_decode( '{ 23 | "roles": { 24 | "administrator": { 25 | "username": "admin", 26 | "password": "admin" 27 | } 28 | }, 29 | "admin_url": "/wp-admin" 30 | }', true ); 31 | 32 | $this->set_params( $params ); 33 | $this->get_params()->shouldReturn( $params ); 34 | } 35 | 36 | public function it_can_replace_var() 37 | { 38 | // variable should be converted. 39 | $this->set_variables( 'FOO', 'hello' ); 40 | $this->replace_variables( '{FOO}' )->shouldReturn( 'hello' ); 41 | 42 | // $str is not variable 43 | $this->replace_variables( 'FOO' )->shouldReturn( 'FOO' ); 44 | 45 | // $str looks like variable, but it is undefined. 46 | $this->replace_variables( '{HELLO}' )->shouldReturn( '{HELLO}' ); 47 | } 48 | 49 | public function it_can_get_admin_url() 50 | { 51 | $params = json_decode( '{ 52 | "roles": { 53 | "administrator": { 54 | "username": "admin", 55 | "password": "admin" 56 | } 57 | }, 58 | "admin_url": "/wp-admin" 59 | }', true ); 60 | 61 | $this->set_params( $params ); 62 | $this->get_admin_url()->shouldReturn( '/wp-admin' ); 63 | } 64 | 65 | public function it_should_get_status() 66 | { 67 | $this->init_mink( 'goutte' ); 68 | $session = $this->getSession(); 69 | 70 | $session->visit( 'http://127.0.0.1:8080/' ); 71 | $this->get_http_status()->shouldReturn( 200 ); 72 | 73 | $session->visit( 'http://127.0.0.1:8080/the-page-not-found' ); 74 | $this->get_http_status()->shouldReturn( 404 ); 75 | } 76 | 77 | public function it_should_get_headers() 78 | { 79 | $this->init_mink( 'goutte' ); 80 | $session = $this->getSession(); 81 | 82 | $session->visit( 'http://127.0.0.1:8080/' ); 83 | $this->get_http_headers()->shouldHaveKeyWithValue( 84 | 'Content-Type', 85 | array( 'text/html; charset=UTF-8' ) 86 | ); 87 | 88 | $session->visit( 'http://127.0.0.1:8080/the-page-not-found' ); 89 | $this->get_http_headers()->shouldHaveKeyWithValue( 90 | 'Content-Type', 91 | array( 'text/html; charset=UTF-8' ) 92 | ); 93 | } 94 | 95 | public function it_can_login_with() 96 | { 97 | $this->init_mink( 'goutte' ); 98 | 99 | $this->login( 'admin', 'admin' )->shouldReturn( true ); 100 | $this->login( 'admin', 'xxxx' )->shouldReturn( false ); 101 | 102 | $this->init_mink( 'selenium2' ); 103 | 104 | $this->login( 'admin', 'admin' )->shouldReturn( true ); 105 | $this->login( 'admin', 'xxxx' )->shouldReturn( false ); 106 | } 107 | 108 | public function it_can_check_current_url_with() 109 | { 110 | $this->init_mink( 'goutte' ); 111 | $session = $this->getSession(); 112 | 113 | $session->visit( 'http://127.0.0.1:8080/i-am-here' ); 114 | 115 | $this->is_current_url( "/i-am-here" )->shouldReturn( true ); 116 | $this->is_current_url( "/i-am-not-here" )->shouldReturn( false ); 117 | 118 | $this->init_mink( 'selenium2' ); 119 | $session = $this->getSession(); 120 | 121 | $session->visit( 'http://127.0.0.1:8080/i-am-here' ); 122 | 123 | $this->is_current_url( "/i-am-here" )->shouldReturn( true ); 124 | $this->is_current_url( "/i-am-not-here" )->shouldReturn( false ); 125 | } 126 | 127 | public function it_can_logout() 128 | { 129 | $this->init_mink( 'goutte' ); 130 | 131 | $this->login( 'admin', 'admin' )->shouldReturn( true ); 132 | $this->is_logged_in()->shouldReturn( true ); 133 | $this->logout(); 134 | $this->is_logged_in()->shouldReturn( false ); 135 | 136 | $this->init_mink( 'selenium2' ); 137 | 138 | $this->login( 'admin', 'admin' )->shouldReturn( true ); 139 | $this->is_logged_in()->shouldReturn( true ); 140 | $this->logout(); 141 | $this->is_logged_in()->shouldReturn( false ); 142 | } 143 | 144 | private function init_mink( $driver ) 145 | { 146 | $mink = new Mink( array( 147 | 'goutte' => new Session( new GoutteDriver( new GoutteClient() ) ), 148 | 'selenium2' => new Session( new Selenium2Driver() ), 149 | ) ); 150 | $mink->setDefaultSessionName( $driver ); 151 | $this->setMink( $mink ); 152 | $this->setMinkParameter( 'base_url', 'http://127.0.0.1:8080' ); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WordPress Extension for the Behat/Mink 2 | 3 | [![Build Status](https://travis-ci.org/vccw-team/wordpress-mink-extension.svg?branch=master)](https://travis-ci.org/vccw-team/wordpress-mink-extension) 4 | [![Latest Stable Version](https://poser.pugx.org/vccw-team/wordpress-extension/v/stable)](https://packagist.org/packages/vccw-team/wordpress-extension) 5 | [![Total Downloads](https://poser.pugx.org/vccw-team/wordpress-extension/downloads)](https://packagist.org/packages/vccw-team/wordpress-extension) 6 | [![Latest Unstable Version](https://poser.pugx.org/vccw-team/wordpress-extension/v/unstable)](https://packagist.org/packages/vccw-team/wordpress-extension) 7 | [![License](https://poser.pugx.org/vccw-team/wordpress-extension/license)](https://packagist.org/packages/vccw-team/wordpress-extension) 8 | 9 | ## Requires 10 | 11 | * WordPress 4.6 or later 12 | * PHP 5.6 or later 13 | 14 | ## Getting Started 15 | 16 | ### Install dependencies 17 | 18 | The recomended way to install is by using Composer. 19 | 20 | ``` 21 | $ composer require vccw-team/wordpress-extension:@stable 22 | ``` 23 | 24 | ### Initialize Behat 25 | 26 | After that you will be able to initialize the project. 27 | 28 | ``` 29 | $ vendor/bin/behat --init 30 | ``` 31 | 32 | ### Configuration 33 | 34 | Place the `behat.yml` like following. 35 | 36 | ``` 37 | default: 38 | suites: 39 | default: 40 | paths: 41 | - %paths.base%/features 42 | contexts: 43 | - FeatureContext 44 | - VCCW\Behat\Mink\WordPressExtension\Context\WordPressContext 45 | - Behat\MinkExtension\Context\MinkContext 46 | extensions: 47 | VCCW\Behat\Mink\WordPressExtension: 48 | roles: 49 | administrator: 50 | username: admin 51 | password: admin 52 | editor: 53 | username: editor 54 | password: editor 55 | Behat\MinkExtension: 56 | base_url: http://127.0.0.1:8080 57 | default_session: default 58 | sessions: 59 | default: 60 | selenium2: 61 | wd_host: http://127.0.0.1:4444/wd/hub 62 | goutte: 63 | goutte: ~ 64 | 65 | ``` 66 | 67 | * Add user accounts of your WordPress site into `VCCW\Behat\Mink\WordPressExtension > roles`. 68 | * Update value of the `Behat\MinkExtension > base_url` to your hostname. 69 | * You can add multiple user like following. 70 | 71 | ``` 72 | extensions: 73 | VCCW\Behat\Mink\WordPressExtension: 74 | roles: 75 | administrator: 76 | username: admin 77 | password: admin 78 | editor: 79 | username: editor 80 | password: editor 81 | ``` 82 | 83 | See: 84 | https://github.com/vccw-team/wordpress-extension/blob/master/behat.yml.dist 85 | 86 | ### Write features 87 | 88 | You can write features with Gherkin language. 89 | 90 | https://github.com/cucumber/cucumber/wiki/Gherkin 91 | 92 | Example `*.feature` are in the following. 93 | 94 | https://github.com/vccw-team/wordpress-extension/tree/master/features 95 | 96 | #### Examples 97 | 98 | Login as the administrator role and I should see "Dashboard". 99 | 100 | ``` 101 | Feature: I login as the specfic role 102 | 103 | Scenario: Login as the "administrator" role 104 | 105 | When I login as the "administrator" role 106 | Then I should see "Welcome to WordPress!" 107 | ``` 108 | 109 | Selenium2 driver can't retrieve the HTTP response. 110 | So you have to use `@mink::goutte` tag like following in your `*.feature`. 111 | But goutte driver can't exec JavaScript. 112 | 113 | ``` 114 | Feature: HTTP response 115 | 116 | @mink:goutte 117 | Scenario: Check http status code 118 | 119 | When I am on "/" 120 | Then the HTTP status should be 200 121 | 122 | When I am on "/the-page-not-found" 123 | Then the HTTP status should be 404 124 | ``` 125 | 126 | Run to see contexts. 127 | 128 | ``` 129 | $ vendor/bin/behat -di --lang=en 130 | ``` 131 | 132 | ### Install headless browser 133 | 134 | Following is an exmaple for PhantomJS. 135 | 136 | ``` 137 | $ npm install phantomjs-prebuilt --save 138 | $ node_modules/.bin/phantomjs --webdriver=4444 --ignore-ssl-errors=yes --cookies-file=/tmp/webdriver_cookie.txt 139 | ``` 140 | 141 | ### Run tests 142 | 143 | ``` 144 | $ vendor/bin/behat 145 | ``` 146 | 147 | ### Running tests as npm-scripts 148 | 149 | Following is an example to run phantomjs and tests automatically. 150 | 151 | Save following as `bin/run-tests.js`. 152 | 153 | ``` 154 | const phantomjs = require( 'phantomjs-prebuilt' ) 155 | const spawn = require( 'child_process' ).spawn 156 | 157 | const argv = process.argv 158 | argv.shift() 159 | argv.shift() 160 | 161 | phantomjs.run( 162 | '--webdriver=4444', 163 | '--ignore-ssl-errors=yes', 164 | '--cookies-file=/tmp/webdriver_cookie.txt' 165 | ).then( program => { 166 | const behat = spawn( 'vendor/bin/behat', argv, { stdio: "inherit" } ) 167 | behat.on( 'exit', ( code ) => { 168 | program.kill() 169 | process.exit( code ); 170 | } ) 171 | } ) 172 | ``` 173 | 174 | Add it to `package.json`. 175 | 176 | ``` 177 | { 178 | "scripts": { 179 | "test": "/usr/bin/env node bin/run-tests.js" 180 | }, 181 | } 182 | ``` 183 | 184 | Then just run: 185 | 186 | ``` 187 | $ npm test 188 | ``` 189 | -------------------------------------------------------------------------------- /src/Context/RawWordPressContext.php: -------------------------------------------------------------------------------- 1 | parameters = $params; 25 | } 26 | 27 | /** 28 | * Get parameters 29 | * 30 | * @return array The parameter for this extension. 31 | */ 32 | public function get_params() 33 | { 34 | return $this->parameters; 35 | } 36 | 37 | /** 38 | * Set variables for the senario. 39 | * 40 | * @param string $key The parameter for this extension. 41 | */ 42 | public function set_variables( $key, $value ) 43 | { 44 | $this->variables[ $key ] = $value; 45 | } 46 | 47 | /** 48 | * Get variables for the senario. 49 | * 50 | * @param string $key The parameter for this extension. 51 | * @return array The value of the variable. 52 | */ 53 | public function get_variables( $key ) 54 | { 55 | if ( ! empty( $this->variables[ $key ] ) ) { 56 | return $this->variables[ $key ]; 57 | } else { 58 | return null; 59 | } 60 | } 61 | 62 | /** 63 | * Get http status code from the current page. 64 | * 65 | * @return int HTTP status code. 66 | */ 67 | public function get_http_status() 68 | { 69 | $session = $this->getSession(); 70 | return intval( $session->getStatusCode() ); 71 | } 72 | 73 | /** 74 | * Get http response headers from the current page. 75 | * 76 | * @return array HTTP response headers. 77 | */ 78 | public function get_http_headers() 79 | { 80 | $session = $this->getSession(); 81 | return $session->getResponseHeaders(); 82 | } 83 | 84 | /** 85 | * Get contents from $url. 86 | * 87 | * @param string $url The URL. 88 | * @return string The contents. 89 | */ 90 | public function get_contents( $url ) 91 | { 92 | $this->getSession()->visit( $url ); 93 | return $this->getSession()->getPage()->getText(); 94 | } 95 | 96 | /** 97 | * Log in into the WordPress. 98 | * 99 | * @param string $user The user name. 100 | * @param string $password The password. 101 | * @return bool 102 | * @throws \Exception If the page returns something wrong. 103 | */ 104 | public function login( $user, $password ) 105 | { 106 | $this->getSession()->visit( $this->locatePath( '/wp-login.php' ) ); 107 | $this->wait_the_element( "#loginform" ); 108 | 109 | $element = $this->getSession()->getPage(); 110 | $element->fillField( "user_login", $user ); 111 | $element->fillField( "user_pass", $password ); 112 | 113 | $submit = $element->findButton( "wp-submit" ); 114 | $submit->click(); 115 | 116 | for ( $i = 0; $i < $this->timeout; $i++ ) { 117 | // Check if keeping staying on login page till timeout. 118 | try { 119 | if ( $this->is_current_url( '/wp-login.php' ) ) { 120 | // Still in login page. 121 | if ( $this->getSession()->getPage()->find( 'css','#login_error' ) ) { 122 | // Find error dialog. Apparent Error. 123 | return false; 124 | } else { 125 | // @todo Should consider other situations? 126 | } 127 | } else { 128 | // Redirected. Guess logged in. 129 | return true; 130 | } 131 | } catch ( \Exception $e ) { 132 | // do nothing 133 | } 134 | 135 | sleep( 1 ); 136 | } 137 | 138 | throw new \Exception( 'Login timeout' ); 139 | } 140 | 141 | /** 142 | * Retrun true when I am at `$url`. 143 | * 144 | * @param string $url The URL where I should be. 145 | * @return bool Return true when I am at `$url`. 146 | * @throws \Exception If the page returns something wrong. 147 | */ 148 | public function is_current_url( $url ) 149 | { 150 | $current_url = $this->getSession()->getCurrentUrl(); 151 | 152 | if ( $url === substr( $current_url, 0 - strlen( $url ) ) ) { 153 | return true; 154 | } else { 155 | return false; 156 | } 157 | } 158 | 159 | /** 160 | * Log out from WordPress. 161 | * 162 | * @param none 163 | * @return bool 164 | * @throws \Exception If the page returns something wrong. 165 | */ 166 | public function logout() 167 | { 168 | if ( ! $this->is_logged_in() ) { 169 | return false; // user isn't login. 170 | } 171 | 172 | $page = $this->getSession()->getPage(); 173 | $logout = $page->find( "css", "#wp-admin-bar-logout a" ); 174 | 175 | if ( ! empty( $logout ) ) { 176 | $this->getSession()->visit( $this->locatePath( $logout->getAttribute( "href" ) ) ); 177 | 178 | for ( $i = 0; $i < $this->timeout; $i++ ) { 179 | try { 180 | $url = $this->getSession()->getCurrentUrl(); 181 | if ( strpos( $url, "loggedout=true" ) ) { 182 | return true; 183 | } 184 | } catch ( \Exception $e ) { 185 | // do nothing 186 | } 187 | 188 | sleep( 1 ); 189 | } 190 | 191 | throw new \Exception( 'Logout timeout' ); 192 | } 193 | } 194 | 195 | /** 196 | * Determine if the a user is already logged in. 197 | * 198 | * @return boolean 199 | * Returns TRUE if a user is logged in for this session. 200 | */ 201 | public function is_logged_in() 202 | { 203 | $page = $this->getSession()->getPage(); 204 | if ( $page->find( "css", ".logged-in" ) ) { 205 | return true; 206 | } elseif ( $page->find( "css", ".wp-admin" ) ) { 207 | return true; 208 | } 209 | 210 | return false; 211 | } 212 | 213 | /** 214 | * Wait the $selector to be loaded 215 | * 216 | * @param string $selector The CSS selector. 217 | * @return bool 218 | * @throws \Exception If the page returns something wrong. 219 | */ 220 | public function wait_the_element( $selector ) 221 | { 222 | $page = $this->getSession()->getPage(); 223 | 224 | for ( $i = 0; $i < $this->timeout; $i++ ) { 225 | try { 226 | if ( $page->find( 'css', $selector ) ) { 227 | sleep( 1 ); 228 | return true; 229 | } 230 | } catch ( \Exception $e ) { 231 | // do nothing 232 | } 233 | 234 | sleep( 1 ); 235 | } 236 | 237 | throw new \Exception( "No html element found for the selector ('$selector')" ); 238 | } 239 | 240 | /** 241 | * Check the plugin is activated. 242 | * 243 | * @param string $slug The slug of the plugin. 244 | * @return bool Return true if plugin is activated. 245 | * @throws \Exception 246 | */ 247 | public function is_plugin_activated( $slug ) 248 | { 249 | $element = $this->search_plugin( $slug ); 250 | if ( ! $element ) { 251 | throw new \Exception( sprintf( 252 | "The %s plugin is not installed.", 253 | $slug 254 | ) ); 255 | } 256 | $classes = preg_split( '/\s+/', trim( $element->getAttribute( "class" ) ) ); 257 | if ( in_array( 'active', $classes ) ) { 258 | return true; 259 | } else { 260 | return false; 261 | } 262 | } 263 | 264 | /** 265 | * Check the plugin is installed. 266 | * 267 | * @param string $slug The slug of the plugin. 268 | * @return bool Return true if plugin is installed. 269 | * @throws \Exception 270 | */ 271 | public function is_plugin_installed( $slug ) 272 | { 273 | $element = $this->search_plugin( $slug ); 274 | if ( count( $element ) ) { 275 | return true; 276 | } else { 277 | return false; 278 | } 279 | } 280 | 281 | /** 282 | * Activate the plugin. 283 | * 284 | * @param string $slug The slug of the plugin. 285 | * @throws \Exception 286 | */ 287 | public function activate_plugin( $slug ) 288 | { 289 | $element = $this->search_plugin( $slug ); 290 | if ( ! $element ) { 291 | throw new \Exception( sprintf( 292 | "The %s plugin is not installed.", 293 | $slug 294 | ) ); 295 | } 296 | $edit = $element->find( 'css', '.activate a' ); 297 | $edit->click(); 298 | sleep( 1 ); 299 | } 300 | 301 | /** 302 | * Deactivate the plugin. 303 | * 304 | * @param string $slug The slug of the plugin. 305 | * @throws \Exception 306 | */ 307 | public function deactivate_plugin( $slug ) 308 | { 309 | $element = $this->search_plugin( $slug ); 310 | if ( ! $element ) { 311 | throw new \Exception( sprintf( 312 | "The %s plugin is not installed.", 313 | $slug 314 | ) ); 315 | } 316 | $edit = $element->find( 'css', '.deactivate a' ); 317 | $edit->click(); 318 | sleep( 1 ); 319 | } 320 | 321 | /** 322 | * Search plugin in the plugins.php 323 | * 324 | * @param string $slug The slug of the plugin. 325 | * @return object An object of the dom element of plugin row. 326 | */ 327 | public function search_plugin( $slug ) 328 | { 329 | $session = $this->getSession(); 330 | $path = $this->get_admin_url() . '/plugins.php?s=' . urlencode( $slug ); 331 | $session->visit( $this->locatePath( $path ) ); 332 | return $session->getPage()->find( 'css', 'tr[data-slug="' . $slug . '"]' ); 333 | } 334 | 335 | /** 336 | * Get the current theme 337 | * 338 | * @return string The slug of the current theme. 339 | * @throws \Exception 340 | */ 341 | protected function get_current_theme() 342 | { 343 | if ( ! $this->is_logged_in() ) { 344 | throw new \Exception( "You are not logged in" ); 345 | } 346 | 347 | $this->getSession()->visit( $this->locatePath( $this->get_admin_url() . '/themes.php' ) ); 348 | $page = $this->getSession()->getPage(); 349 | $e = $page->find( 'css', ".theme.active" ); 350 | if ( $e ) { 351 | $classes = preg_split( "/\s+/", trim( $e->getAttribute( "aria-describedby" ) ) ); 352 | $theme = preg_replace( "/\-(name|action)$/", "", $classes[0] ); 353 | if ( $theme ) { 354 | return $theme; 355 | } 356 | } 357 | 358 | throw new \Exception( "Maybe you don't have permission to get the current theme." ); 359 | } 360 | 361 | /** 362 | * Get the WordPress version from meta. 363 | * 364 | * @return string WordPress version number. 365 | * @throws \Exception 366 | */ 367 | protected function get_wp_version() 368 | { 369 | $this->getSession()->visit( $this->locatePath( '/' ) ); 370 | $page = $this->getSession()->getPage(); 371 | $meta = $page->find( 'css', "meta[name=generator]" ); 372 | if ( $meta ) { 373 | $version = $meta->getAttribute( "content" ); 374 | if ( $version ) { 375 | return str_replace( "WordPress ", "", $version ); 376 | } 377 | } 378 | 379 | throw new \Exception( "No version number found" ); 380 | } 381 | 382 | /** 383 | * Replace with variables 384 | * 385 | * @param string $str The str or {VARIABLE} format text. 386 | * @return string The value of the variable. 387 | */ 388 | public function replace_variables( $str ) 389 | { 390 | if ( preg_match( "/^\{([A-Z0-9_]+)\}$/", $str, $matches ) ) { 391 | $key = $matches[1]; 392 | if ( $this->get_variables( $key ) ) { 393 | return $this->get_variables( $key ); 394 | } 395 | } 396 | return $str; 397 | } 398 | 399 | /** 400 | * Returns the admin_url from configuration 401 | * 402 | * @param none 403 | * @return string Admin url like `/wp-admin` 404 | */ 405 | public function get_admin_url() 406 | { 407 | $params = $this->get_params(); 408 | return $params['admin_url']; 409 | } 410 | } 411 | -------------------------------------------------------------------------------- /src/Context/WordPressContext.php: -------------------------------------------------------------------------------- 1 | [A-Z_]+) as \{(?P[A-Z_]+)\}$/ 22 | */ 23 | public function save_env_as_var( $env, $var ) 24 | { 25 | $this->set_variables( $var, getenv( $env ) ); 26 | } 27 | 28 | /** 29 | * Check http status code. 30 | * Example: the HTTP status should be 400 31 | * 32 | * @param string $expect The HTTP status code. 33 | * @throws \Exception 34 | * @then /^the HTTP status should be (?P[0-9]+)$/ 35 | */ 36 | public function the_http_status_should_be( $expect ) 37 | { 38 | $status = $this->get_http_status(); 39 | if ( intval( $expect ) !== $status ) { 40 | throw new \Exception(sprintf( 41 | 'The HTTP status is %1$s, but it should be %2$s', 42 | $status, 43 | $expect 44 | )); 45 | } 46 | } 47 | 48 | /** 49 | * Check HTTP response headers. 50 | * Example: 51 | * Then the HTTP headers should be: 52 | * | header | value | 53 | * | Content-Type | text/html; charset=UTF-8 | 54 | * | Connection | close | 55 | * | Host | 127.0.0.1:8080 | 56 | * 57 | * @then /^the HTTP headers should be:$/ 58 | * @param TableNode $table The TableNode object. 59 | * @throws \Exception 60 | */ 61 | public function the_http_headers_should_be( TableNode $table ) 62 | { 63 | $headers = $this->get_http_headers(); 64 | 65 | foreach ( $table->getHash() as $row ) { 66 | if ( ! empty( $headers[ $row['header'] ] ) ) { 67 | $value = $headers[ $row['header'] ][0]; 68 | if ( $row['value'] !== $value ) { 69 | throw new \Exception( sprintf( 70 | 'The value of "%1$s" header is "%1$s", but it should be "%3$s".', 71 | $row['header'], 72 | $value, 73 | $row['value'] 74 | ) ); 75 | } 76 | } else { 77 | throw new \Exception( sprintf( 78 | 'The value of "%1$s" header is empty, but it should be "%2$s".', 79 | $row['header'], 80 | $row['value'] 81 | ) ); 82 | } 83 | } 84 | } 85 | 86 | /** 87 | * Check status of plugins 88 | * Example: 89 | * Then the plugins should be: 90 | * | slug | status | 91 | * | akismet | inactive | 92 | * | hello-dolly | inactive | 93 | * | wordpress-importer | active | 94 | * 95 | * @then /^the plugins should be:$/ 96 | */ 97 | public function the_plugins_should_be( TableNode $table ) 98 | { 99 | foreach ( $table->getHash() as $row ) { 100 | $slug = $row['slug']; 101 | $expect = $row['status']; 102 | if ( ! $this->is_plugin_installed( $slug ) ) { 103 | throw new \Exception( sprintf( 104 | "The %s plugin is not installed.", 105 | $slug 106 | ) ); 107 | } 108 | if ( "active" === $expect && ! $this->is_plugin_activated( $slug ) ) { 109 | throw new \Exception( sprintf( 110 | "The %s plugin should be activated, but not activated.", 111 | $slug 112 | ) ); 113 | } elseif ( "inactive" === $expect && $this->is_plugin_activated( $slug ) ) { 114 | throw new \Exception( sprintf( 115 | "The %s plugin should not be activated, but activated.", 116 | $slug 117 | ) ); 118 | } elseif ( "active" !== $expect && "inactive" !== $expect ) { 119 | throw new \Exception( sprintf( 120 | "Incorrect status: %s", 121 | $expect 122 | ) ); 123 | } 124 | } 125 | } 126 | 127 | /** 128 | * Check status of plugins. 129 | * Example: Then "akismet" plugin should be activated 130 | * 131 | * @then /^the "(?P[^"]*)" plugin should be (?P(installed|activated))$/ 132 | */ 133 | public function the_plugin_should_be( $slug, $expect ) 134 | { 135 | if ( ! $this->is_plugin_installed( $slug ) ) { 136 | throw new \Exception( sprintf( 137 | "The %s plugin is not installed.", 138 | $slug 139 | ) ); 140 | } 141 | 142 | if ( "activated" === $expect && ! $this->is_plugin_activated( $slug ) ) { 143 | throw new \Exception( sprintf( 144 | "The %s plugin should be activated, but not activated.", 145 | $slug 146 | ) ); 147 | } 148 | } 149 | 150 | /** 151 | * Check status of plugins. 152 | * Example: Then "akismet" plugin should not be activated 153 | * 154 | * @then /^the "(?P[^"]*)" plugin should not be (?P(installed|activated))$/ 155 | */ 156 | public function the_plugin_should_not_be( $slug, $expect ) 157 | { 158 | if ( "installed" === $expect && $this->is_plugin_installed( $slug ) ) { 159 | throw new \Exception( sprintf( 160 | "The %s plugin should not be installed, but installed.", 161 | $slug 162 | ) ); 163 | } 164 | 165 | if ( "activated" === $expect && $this->is_plugin_activated( $slug ) ) { 166 | throw new \Exception( sprintf( 167 | "The %s plugin should not be activated, but activated.", 168 | $slug 169 | ) ); 170 | } 171 | } 172 | 173 | /** 174 | * Activate plugin 175 | * Example: When I activate the "hello-dolly" plugin 176 | * 177 | * @when /^I activate the "(?P[^"]*)" plugin$/ 178 | */ 179 | public function i_activate_the_plugin( $slug ) { 180 | if ( ! $this->is_plugin_installed( $slug ) ) { 181 | throw new \Exception( sprintf( 182 | "The %s plugin is not installed.", 183 | $slug 184 | ) ); 185 | } 186 | 187 | if ( $this->is_plugin_activated( $slug ) ) { 188 | $this->deactivate_plugin( $slug ); 189 | } 190 | 191 | $this->activate_plugin( $slug ); 192 | 193 | if ( ! $this->is_plugin_activated( $slug ) ) { 194 | throw new \Exception( sprintf( 195 | "The %s plugin should be activated, but not activated.", 196 | $slug 197 | ) ); 198 | } 199 | } 200 | 201 | /** 202 | * Deactivate plugin 203 | * Example: When I deactivate the "hello-dolly" plugin 204 | * 205 | * @then /^I deactivate the "(?P[^"]*)" plugin$/ 206 | */ 207 | public function i_deactivate_the_plugin( $slug ) { 208 | if ( ! $this->is_plugin_installed( $slug ) ) { 209 | throw new \Exception( sprintf( 210 | "The %s plugin is not installed.", 211 | $slug 212 | ) ); 213 | } 214 | 215 | if ( $this->is_plugin_activated( $slug ) ) { 216 | $this->deactivate_plugin( $slug ); 217 | } 218 | 219 | if ( $this->is_plugin_activated( $slug ) ) { 220 | throw new \Exception( sprintf( 221 | "The %s plugin should not be activated, but activated.", 222 | $slug 223 | ) ); 224 | } 225 | } 226 | 227 | /** 228 | * Check the theme is activated 229 | * Example: Given the "twentysixteen" theme should be activated 230 | * 231 | * @Then /^the "(?P[^"]*)" theme should be activated$/ 232 | * @throws \Exception 233 | */ 234 | public function theme_should_be_activated( $theme ) 235 | { 236 | $theme = $this->replace_variables( $theme ); 237 | $current_theme = $this->get_current_theme(); 238 | 239 | if ( $theme !== $current_theme ) { 240 | throw new \Exception( sprintf( 241 | "The current theme is %s, but it should be %s", 242 | $current_theme, 243 | $theme 244 | ) ); 245 | } 246 | } 247 | 248 | /** 249 | * Check WordPress version. 250 | * Example: Given the WordPress version should be "4.6" 251 | * 252 | * @Given /^the WordPress version should be "(?P[^"]*)"$/ 253 | */ 254 | public function wordpress_version_should_be( $version ) 255 | { 256 | $version = $this->replace_variables( $version ); 257 | $latest = ''; 258 | 259 | if ( "latest" === $version || "nightly" === $version ) { 260 | $api = $this->get_contents( "https://api.wordpress.org/core/version-check/1.7/" ); 261 | $versions = json_decode( $api ); 262 | $latest = $versions->offers[0]->current; 263 | } 264 | 265 | if ( "latest" === $version ) { 266 | $version = $latest; 267 | } 268 | 269 | $the_version = $this->get_wp_version(); 270 | if ( 0 === strpos( $the_version, $version ) ) { 271 | return true; 272 | } elseif ( "nightly" === $version && version_compare( $the_version, $latest, ">=" ) ) { 273 | return true; 274 | } else { 275 | throw new \Exception( sprintf( 276 | "The WordPress version number is %s, but it should be %s", 277 | $the_version, 278 | $version 279 | ) ); 280 | } 281 | } 282 | 283 | /** 284 | * Return exception if user is not logged-in. 285 | * Example: Then I should be logged in 286 | * 287 | * @Then I should be logged in 288 | */ 289 | public function i_should_be_logged_in() 290 | { 291 | if ( ! $this->is_logged_in() ) { 292 | throw new \Exception( "You are not logged in" ); 293 | } 294 | } 295 | 296 | /** 297 | * Return exception if user is logged-in. 298 | * Example: I should not be logged in 299 | * 300 | * @Then I should not be logged in 301 | */ 302 | public function i_should_not_be_logged_in() 303 | { 304 | if ( $this->is_logged_in() ) { 305 | throw new \Exception( "You are logged in" ); 306 | } 307 | } 308 | 309 | /** 310 | * Login with username and password. 311 | * When you failed to login, it will throw `Exception`. 312 | * Example: Given I login as "admin" width password "admin" 313 | * 314 | * @param string $username The user name. 315 | * @param string $password The password for the $username. 316 | * @Given /^I login as "(?P(?:[^"]|\\")*)" with password "(?P(?:[^"]|\\")*)"$/ 317 | * @throws \Exception 318 | */ 319 | public function login_as_user_password( $username, $password ) 320 | { 321 | $username = $this->replace_variables( $username ); 322 | $password = $this->replace_variables( $password ); 323 | 324 | $result = $this->login( $username, $password ); 325 | 326 | if ( ! $result ) { 327 | throw new \Exception( "Login failed." ); 328 | } 329 | } 330 | 331 | /** 332 | * Login with username and password. 333 | * Example: Given I login as "admin" width password "admin" 334 | * 335 | * @param string $username The user name. 336 | * @param string $password The password for the $username. 337 | * @Given /^I try to login as "(?P(?:[^"]|\\")*)" with password "(?P(?:[^"]|\\")*)"$/ 338 | */ 339 | public function try_to_login_as_user_password( $username, $password ) 340 | { 341 | $username = $this->replace_variables( $username ); 342 | $password = $this->replace_variables( $password ); 343 | 344 | $this->login( $username, $password ); 345 | } 346 | 347 | /** 348 | * Login as the role like "administrator", It should be defined in the `behat.yml`. 349 | * When you failed to login, it will throw `Exception`. 350 | * Example: Given I login as the "([^"]*)" role 351 | * 352 | * @param string $role The role that is defined in `behat.yml`. 353 | * @Given /^I login as the "(?P[a-zA-Z]*)" role$/ 354 | * @throws \Exception 355 | */ 356 | public function login_as_the_role( $role ) 357 | { 358 | $role = $this->replace_variables( $role ); 359 | 360 | $params = $this->get_params(); 361 | 362 | if ( empty( $params['roles'][ $role ] ) ) { 363 | throw new \InvalidArgumentException( sprintf( 364 | "Role '%s' is not defined in the `behat.yml`", $role 365 | ) ); 366 | } else { 367 | $result = $this->login( 368 | $params['roles'][ $role ]['username'], 369 | $params['roles'][ $role ]['password'] 370 | ); 371 | if ( ! $result ) { 372 | throw new \Exception( "Login failed." ); 373 | } 374 | } 375 | } 376 | 377 | /** 378 | * Login as the role like "administrator", It should be defined in the `behat.yml`. 379 | * Example: Given I login as the "([^"]*)" role 380 | * 381 | * @param string $role The role that is defined in `behat.yml`. 382 | * @Given /^I try to login as the "(?P[a-zA-Z]*)" role$/ 383 | */ 384 | public function try_to_login_as_the_role( $role ) 385 | { 386 | $role = $this->replace_variables( $role ); 387 | 388 | $params = $this->get_params(); 389 | 390 | if ( empty( $params['roles'][ $role ] ) ) { 391 | throw new \InvalidArgumentException( sprintf( 392 | "Role '%s' is not defined in the `behat.yml`", $role 393 | ) ); 394 | } else { 395 | $result = $this->login( 396 | $params['roles'][ $role ]['username'], 397 | $params['roles'][ $role ]['password'] 398 | ); 399 | } 400 | } 401 | 402 | /** 403 | * The mouseover over the specific element. 404 | * Example: I hover over the ".site-title a" element 405 | * 406 | * @param string $selector The CSS selector. 407 | * @When /^I hover over the "(?P[^"]*)" element$/ 408 | */ 409 | public function hover_over_the_element( $selector ) 410 | { 411 | $selector = $this->replace_variables( $selector ); 412 | 413 | $session = $this->getSession(); 414 | $element = $session->getPage()->find( 'css', $selector ); 415 | 416 | if ( null === $element ) { 417 | throw new \InvalidArgumentException( sprintf( 418 | 'Could not evaluate CSS selector: "%s"', $selector 419 | ) ); 420 | } 421 | 422 | $element->mouseOver(); 423 | } 424 | 425 | /** 426 | * Wait for specific seconds. 427 | * Example: 428 | * * When I wait for 5 seconds 429 | * * When I wait for a second 430 | * 431 | * @param int $second The seconds that wait for. 432 | * @Given /^I wait for (?P[0-9]+) seconds$/ 433 | * @Given /^I wait for a second$/ 434 | */ 435 | public function wait_for_second( $second = 1 ) 436 | { 437 | $second = $this->replace_variables( $second ); 438 | $this->getSession()->wait( $second * 1000 ); 439 | } 440 | 441 | /** 442 | * Wait the specific element will be loaded. 443 | * Example: I wait the "#wpadminbar" element be loaded 444 | * 445 | * @Given /^I wait the "(?P[^"]*)" element be loaded$/ 446 | */ 447 | public function wait_the_element_be_loaded( $selector ) 448 | { 449 | $selector = $this->replace_variables( $selector ); 450 | return $this->wait_the_element( $selector ); 451 | } 452 | 453 | /** 454 | * Change the screen size. 455 | * Example: Given the screen size is 1440x900 456 | * 457 | * @param int $width The screen width. 458 | * @param int $height The screen height. 459 | * @Given /^the screen size is (?P[0-9]+)x(?P[0-9]+)/ 460 | */ 461 | public function set_window_size( $width, $height ) 462 | { 463 | $width = $this->replace_variables( $width ); 464 | $height = $this->replace_variables( $height ); 465 | 466 | $this->getSession()->getDriver()->resizeWindow( $width, $height, 'current' ); 467 | } 468 | 469 | /** 470 | * Logout from the WordPress. 471 | * Example: When I logout 472 | * 473 | * @Given I logout 474 | * @Given I am not logged in 475 | */ 476 | public function i_logout() 477 | { 478 | $this->logout(); 479 | } 480 | 481 | /** 482 | * Take a screenshot of the current page and save it to the specific path. 483 | * Example: Then take a screenshot and save it to "./path/to/image.png" 484 | * 485 | * @param string $path The path to the screenshot will be saved 486 | * @Then /^take a screenshot and save it to "(.*)"/ 487 | * @throws \Exception 488 | */ 489 | public function take_a_screenshot( $path ) 490 | { 491 | $path = $this->replace_variables( $path ); 492 | 493 | $path = str_replace( "~", posix_getpwuid(posix_geteuid())['dir'], $path ); 494 | $image = $this->getSession()->getDriver()->getScreenshot(); 495 | $result = file_put_contents( $path, $image ); 496 | 497 | if ( ! $result ) { 498 | throw new \Exception( 'Cannot take a screenshot.' ); 499 | } 500 | } 501 | 502 | /** 503 | * @AfterStep 504 | */ 505 | public function after_step( afterStepScope $scope ) 506 | { 507 | // something to do 508 | } 509 | } 510 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "ef3cc2ccfadd9a720ad6091a80d2327a", 8 | "content-hash": "40519e4a8203b45b30b138165f2ba09f", 9 | "packages": [ 10 | { 11 | "name": "behat/behat", 12 | "version": "v3.3.0", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/Behat/Behat.git", 16 | "reference": "15a3a1857457eaa29cdf41564a5e421effb09526" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/Behat/Behat/zipball/15a3a1857457eaa29cdf41564a5e421effb09526", 21 | "reference": "15a3a1857457eaa29cdf41564a5e421effb09526", 22 | "shasum": "" 23 | }, 24 | "require": { 25 | "behat/gherkin": "^4.4.4", 26 | "behat/transliterator": "~1.0", 27 | "container-interop/container-interop": "^1.1", 28 | "ext-mbstring": "*", 29 | "php": ">=5.3.3", 30 | "symfony/class-loader": "~2.1||~3.0", 31 | "symfony/config": "~2.3||~3.0", 32 | "symfony/console": "~2.5||~3.0", 33 | "symfony/dependency-injection": "~2.1||~3.0", 34 | "symfony/event-dispatcher": "~2.1||~3.0", 35 | "symfony/translation": "~2.3||~3.0", 36 | "symfony/yaml": "~2.1||~3.0" 37 | }, 38 | "require-dev": { 39 | "herrera-io/box": "~1.6.1", 40 | "phpunit/phpunit": "~4.5", 41 | "symfony/process": "~2.5|~3.0" 42 | }, 43 | "suggest": { 44 | "behat/mink-extension": "for integration with Mink testing framework", 45 | "behat/symfony2-extension": "for integration with Symfony2 web framework", 46 | "behat/yii-extension": "for integration with Yii web framework" 47 | }, 48 | "bin": [ 49 | "bin/behat" 50 | ], 51 | "type": "library", 52 | "extra": { 53 | "branch-alias": { 54 | "dev-master": "3.2.x-dev" 55 | } 56 | }, 57 | "autoload": { 58 | "psr-0": { 59 | "Behat\\Behat": "src/", 60 | "Behat\\Testwork": "src/" 61 | } 62 | }, 63 | "notification-url": "https://packagist.org/downloads/", 64 | "license": [ 65 | "MIT" 66 | ], 67 | "authors": [ 68 | { 69 | "name": "Konstantin Kudryashov", 70 | "email": "ever.zet@gmail.com", 71 | "homepage": "http://everzet.com" 72 | } 73 | ], 74 | "description": "Scenario-oriented BDD framework for PHP 5.3", 75 | "homepage": "http://behat.org/", 76 | "keywords": [ 77 | "Agile", 78 | "BDD", 79 | "ScenarioBDD", 80 | "Scrum", 81 | "StoryBDD", 82 | "User story", 83 | "business", 84 | "development", 85 | "documentation", 86 | "examples", 87 | "symfony", 88 | "testing" 89 | ], 90 | "time": "2016-12-25 13:43:52" 91 | }, 92 | { 93 | "name": "behat/gherkin", 94 | "version": "v4.4.5", 95 | "source": { 96 | "type": "git", 97 | "url": "https://github.com/Behat/Gherkin.git", 98 | "reference": "5c14cff4f955b17d20d088dec1bde61c0539ec74" 99 | }, 100 | "dist": { 101 | "type": "zip", 102 | "url": "https://api.github.com/repos/Behat/Gherkin/zipball/5c14cff4f955b17d20d088dec1bde61c0539ec74", 103 | "reference": "5c14cff4f955b17d20d088dec1bde61c0539ec74", 104 | "shasum": "" 105 | }, 106 | "require": { 107 | "php": ">=5.3.1" 108 | }, 109 | "require-dev": { 110 | "phpunit/phpunit": "~4.5|~5", 111 | "symfony/phpunit-bridge": "~2.7|~3", 112 | "symfony/yaml": "~2.3|~3" 113 | }, 114 | "suggest": { 115 | "symfony/yaml": "If you want to parse features, represented in YAML files" 116 | }, 117 | "type": "library", 118 | "extra": { 119 | "branch-alias": { 120 | "dev-master": "4.4-dev" 121 | } 122 | }, 123 | "autoload": { 124 | "psr-0": { 125 | "Behat\\Gherkin": "src/" 126 | } 127 | }, 128 | "notification-url": "https://packagist.org/downloads/", 129 | "license": [ 130 | "MIT" 131 | ], 132 | "authors": [ 133 | { 134 | "name": "Konstantin Kudryashov", 135 | "email": "ever.zet@gmail.com", 136 | "homepage": "http://everzet.com" 137 | } 138 | ], 139 | "description": "Gherkin DSL parser for PHP 5.3", 140 | "homepage": "http://behat.org/", 141 | "keywords": [ 142 | "BDD", 143 | "Behat", 144 | "Cucumber", 145 | "DSL", 146 | "gherkin", 147 | "parser" 148 | ], 149 | "time": "2016-10-30 11:50:56" 150 | }, 151 | { 152 | "name": "behat/mink", 153 | "version": "v1.7.1", 154 | "source": { 155 | "type": "git", 156 | "url": "https://github.com/minkphp/Mink.git", 157 | "reference": "e6930b9c74693dff7f4e58577e1b1743399f3ff9" 158 | }, 159 | "dist": { 160 | "type": "zip", 161 | "url": "https://api.github.com/repos/minkphp/Mink/zipball/e6930b9c74693dff7f4e58577e1b1743399f3ff9", 162 | "reference": "e6930b9c74693dff7f4e58577e1b1743399f3ff9", 163 | "shasum": "" 164 | }, 165 | "require": { 166 | "php": ">=5.3.1", 167 | "symfony/css-selector": "~2.1|~3.0" 168 | }, 169 | "require-dev": { 170 | "symfony/phpunit-bridge": "~2.7|~3.0" 171 | }, 172 | "suggest": { 173 | "behat/mink-browserkit-driver": "extremely fast headless driver for Symfony\\Kernel-based apps (Sf2, Silex)", 174 | "behat/mink-goutte-driver": "fast headless driver for any app without JS emulation", 175 | "behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)", 176 | "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)" 177 | }, 178 | "type": "library", 179 | "extra": { 180 | "branch-alias": { 181 | "dev-master": "1.7.x-dev" 182 | } 183 | }, 184 | "autoload": { 185 | "psr-4": { 186 | "Behat\\Mink\\": "src/" 187 | } 188 | }, 189 | "notification-url": "https://packagist.org/downloads/", 190 | "license": [ 191 | "MIT" 192 | ], 193 | "authors": [ 194 | { 195 | "name": "Konstantin Kudryashov", 196 | "email": "ever.zet@gmail.com", 197 | "homepage": "http://everzet.com" 198 | } 199 | ], 200 | "description": "Browser controller/emulator abstraction for PHP", 201 | "homepage": "http://mink.behat.org/", 202 | "keywords": [ 203 | "browser", 204 | "testing", 205 | "web" 206 | ], 207 | "time": "2016-03-05 08:26:18" 208 | }, 209 | { 210 | "name": "behat/mink-browserkit-driver", 211 | "version": "v1.3.2", 212 | "source": { 213 | "type": "git", 214 | "url": "https://github.com/minkphp/MinkBrowserKitDriver.git", 215 | "reference": "10e67fb4a295efcd62ea0bf16025a85ea19534fb" 216 | }, 217 | "dist": { 218 | "type": "zip", 219 | "url": "https://api.github.com/repos/minkphp/MinkBrowserKitDriver/zipball/10e67fb4a295efcd62ea0bf16025a85ea19534fb", 220 | "reference": "10e67fb4a295efcd62ea0bf16025a85ea19534fb", 221 | "shasum": "" 222 | }, 223 | "require": { 224 | "behat/mink": "^1.7.1@dev", 225 | "php": ">=5.3.6", 226 | "symfony/browser-kit": "~2.3|~3.0", 227 | "symfony/dom-crawler": "~2.3|~3.0" 228 | }, 229 | "require-dev": { 230 | "silex/silex": "~1.2", 231 | "symfony/phpunit-bridge": "~2.7|~3.0" 232 | }, 233 | "type": "mink-driver", 234 | "extra": { 235 | "branch-alias": { 236 | "dev-master": "1.3.x-dev" 237 | } 238 | }, 239 | "autoload": { 240 | "psr-4": { 241 | "Behat\\Mink\\Driver\\": "src/" 242 | } 243 | }, 244 | "notification-url": "https://packagist.org/downloads/", 245 | "license": [ 246 | "MIT" 247 | ], 248 | "authors": [ 249 | { 250 | "name": "Konstantin Kudryashov", 251 | "email": "ever.zet@gmail.com", 252 | "homepage": "http://everzet.com" 253 | } 254 | ], 255 | "description": "Symfony2 BrowserKit driver for Mink framework", 256 | "homepage": "http://mink.behat.org/", 257 | "keywords": [ 258 | "Mink", 259 | "Symfony2", 260 | "browser", 261 | "testing" 262 | ], 263 | "time": "2016-03-05 08:59:47" 264 | }, 265 | { 266 | "name": "behat/mink-extension", 267 | "version": "v2.2", 268 | "source": { 269 | "type": "git", 270 | "url": "https://github.com/Behat/MinkExtension.git", 271 | "reference": "5b4bda64ff456104564317e212c823e45cad9d59" 272 | }, 273 | "dist": { 274 | "type": "zip", 275 | "url": "https://api.github.com/repos/Behat/MinkExtension/zipball/5b4bda64ff456104564317e212c823e45cad9d59", 276 | "reference": "5b4bda64ff456104564317e212c823e45cad9d59", 277 | "shasum": "" 278 | }, 279 | "require": { 280 | "behat/behat": "~3.0,>=3.0.5", 281 | "behat/mink": "~1.5", 282 | "php": ">=5.3.2", 283 | "symfony/config": "~2.2|~3.0" 284 | }, 285 | "require-dev": { 286 | "behat/mink-goutte-driver": "~1.1", 287 | "phpspec/phpspec": "~2.0" 288 | }, 289 | "type": "behat-extension", 290 | "extra": { 291 | "branch-alias": { 292 | "dev-master": "2.1.x-dev" 293 | } 294 | }, 295 | "autoload": { 296 | "psr-0": { 297 | "Behat\\MinkExtension": "src/" 298 | } 299 | }, 300 | "notification-url": "https://packagist.org/downloads/", 301 | "license": [ 302 | "MIT" 303 | ], 304 | "authors": [ 305 | { 306 | "name": "Christophe Coevoet", 307 | "email": "stof@notk.org" 308 | }, 309 | { 310 | "name": "Konstantin Kudryashov", 311 | "email": "ever.zet@gmail.com" 312 | } 313 | ], 314 | "description": "Mink extension for Behat", 315 | "homepage": "http://extensions.behat.org/mink", 316 | "keywords": [ 317 | "browser", 318 | "gui", 319 | "test", 320 | "web" 321 | ], 322 | "time": "2016-02-15 07:55:18" 323 | }, 324 | { 325 | "name": "behat/mink-goutte-driver", 326 | "version": "v1.2.1", 327 | "source": { 328 | "type": "git", 329 | "url": "https://github.com/minkphp/MinkGoutteDriver.git", 330 | "reference": "8b9ad6d2d95bc70b840d15323365f52fcdaea6ca" 331 | }, 332 | "dist": { 333 | "type": "zip", 334 | "url": "https://api.github.com/repos/minkphp/MinkGoutteDriver/zipball/8b9ad6d2d95bc70b840d15323365f52fcdaea6ca", 335 | "reference": "8b9ad6d2d95bc70b840d15323365f52fcdaea6ca", 336 | "shasum": "" 337 | }, 338 | "require": { 339 | "behat/mink": "~1.6@dev", 340 | "behat/mink-browserkit-driver": "~1.2@dev", 341 | "fabpot/goutte": "~1.0.4|~2.0|~3.1", 342 | "php": ">=5.3.1" 343 | }, 344 | "require-dev": { 345 | "symfony/phpunit-bridge": "~2.7|~3.0" 346 | }, 347 | "type": "mink-driver", 348 | "extra": { 349 | "branch-alias": { 350 | "dev-master": "1.2.x-dev" 351 | } 352 | }, 353 | "autoload": { 354 | "psr-4": { 355 | "Behat\\Mink\\Driver\\": "src/" 356 | } 357 | }, 358 | "notification-url": "https://packagist.org/downloads/", 359 | "license": [ 360 | "MIT" 361 | ], 362 | "authors": [ 363 | { 364 | "name": "Konstantin Kudryashov", 365 | "email": "ever.zet@gmail.com", 366 | "homepage": "http://everzet.com" 367 | } 368 | ], 369 | "description": "Goutte driver for Mink framework", 370 | "homepage": "http://mink.behat.org/", 371 | "keywords": [ 372 | "browser", 373 | "goutte", 374 | "headless", 375 | "testing" 376 | ], 377 | "time": "2016-03-05 09:04:22" 378 | }, 379 | { 380 | "name": "behat/mink-selenium2-driver", 381 | "version": "v1.3.1", 382 | "source": { 383 | "type": "git", 384 | "url": "https://github.com/minkphp/MinkSelenium2Driver.git", 385 | "reference": "473a9f3ebe0c134ee1e623ce8a9c852832020288" 386 | }, 387 | "dist": { 388 | "type": "zip", 389 | "url": "https://api.github.com/repos/minkphp/MinkSelenium2Driver/zipball/473a9f3ebe0c134ee1e623ce8a9c852832020288", 390 | "reference": "473a9f3ebe0c134ee1e623ce8a9c852832020288", 391 | "shasum": "" 392 | }, 393 | "require": { 394 | "behat/mink": "~1.7@dev", 395 | "instaclick/php-webdriver": "~1.1", 396 | "php": ">=5.3.1" 397 | }, 398 | "require-dev": { 399 | "symfony/phpunit-bridge": "~2.7" 400 | }, 401 | "type": "mink-driver", 402 | "extra": { 403 | "branch-alias": { 404 | "dev-master": "1.3.x-dev" 405 | } 406 | }, 407 | "autoload": { 408 | "psr-4": { 409 | "Behat\\Mink\\Driver\\": "src/" 410 | } 411 | }, 412 | "notification-url": "https://packagist.org/downloads/", 413 | "license": [ 414 | "MIT" 415 | ], 416 | "authors": [ 417 | { 418 | "name": "Konstantin Kudryashov", 419 | "email": "ever.zet@gmail.com", 420 | "homepage": "http://everzet.com" 421 | }, 422 | { 423 | "name": "Pete Otaqui", 424 | "email": "pete@otaqui.com", 425 | "homepage": "https://github.com/pete-otaqui" 426 | } 427 | ], 428 | "description": "Selenium2 (WebDriver) driver for Mink framework", 429 | "homepage": "http://mink.behat.org/", 430 | "keywords": [ 431 | "ajax", 432 | "browser", 433 | "javascript", 434 | "selenium", 435 | "testing", 436 | "webdriver" 437 | ], 438 | "time": "2016-03-05 09:10:18" 439 | }, 440 | { 441 | "name": "behat/transliterator", 442 | "version": "v1.1.0", 443 | "source": { 444 | "type": "git", 445 | "url": "https://github.com/Behat/Transliterator.git", 446 | "reference": "868e05be3a9f25ba6424c2dd4849567f50715003" 447 | }, 448 | "dist": { 449 | "type": "zip", 450 | "url": "https://api.github.com/repos/Behat/Transliterator/zipball/868e05be3a9f25ba6424c2dd4849567f50715003", 451 | "reference": "868e05be3a9f25ba6424c2dd4849567f50715003", 452 | "shasum": "" 453 | }, 454 | "require": { 455 | "php": ">=5.3.3" 456 | }, 457 | "type": "library", 458 | "extra": { 459 | "branch-alias": { 460 | "dev-master": "1.1-dev" 461 | } 462 | }, 463 | "autoload": { 464 | "psr-0": { 465 | "Behat\\Transliterator": "src/" 466 | } 467 | }, 468 | "notification-url": "https://packagist.org/downloads/", 469 | "license": [ 470 | "Artistic-1.0" 471 | ], 472 | "description": "String transliterator", 473 | "keywords": [ 474 | "i18n", 475 | "slug", 476 | "transliterator" 477 | ], 478 | "time": "2015-09-28 16:26:35" 479 | }, 480 | { 481 | "name": "container-interop/container-interop", 482 | "version": "1.1.0", 483 | "source": { 484 | "type": "git", 485 | "url": "https://github.com/container-interop/container-interop.git", 486 | "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e" 487 | }, 488 | "dist": { 489 | "type": "zip", 490 | "url": "https://api.github.com/repos/container-interop/container-interop/zipball/fc08354828f8fd3245f77a66b9e23a6bca48297e", 491 | "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e", 492 | "shasum": "" 493 | }, 494 | "type": "library", 495 | "autoload": { 496 | "psr-4": { 497 | "Interop\\Container\\": "src/Interop/Container/" 498 | } 499 | }, 500 | "notification-url": "https://packagist.org/downloads/", 501 | "license": [ 502 | "MIT" 503 | ], 504 | "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", 505 | "time": "2014-12-30 15:22:37" 506 | }, 507 | { 508 | "name": "fabpot/goutte", 509 | "version": "v3.2.0", 510 | "source": { 511 | "type": "git", 512 | "url": "https://github.com/FriendsOfPHP/Goutte.git", 513 | "reference": "8cc89de5e71daf84051859616891d3320d88a9e8" 514 | }, 515 | "dist": { 516 | "type": "zip", 517 | "url": "https://api.github.com/repos/FriendsOfPHP/Goutte/zipball/8cc89de5e71daf84051859616891d3320d88a9e8", 518 | "reference": "8cc89de5e71daf84051859616891d3320d88a9e8", 519 | "shasum": "" 520 | }, 521 | "require": { 522 | "guzzlehttp/guzzle": "^6.0", 523 | "php": ">=5.5.0", 524 | "symfony/browser-kit": "~2.1|~3.0", 525 | "symfony/css-selector": "~2.1|~3.0", 526 | "symfony/dom-crawler": "~2.1|~3.0" 527 | }, 528 | "type": "application", 529 | "extra": { 530 | "branch-alias": { 531 | "dev-master": "3.2-dev" 532 | } 533 | }, 534 | "autoload": { 535 | "psr-4": { 536 | "Goutte\\": "Goutte" 537 | } 538 | }, 539 | "notification-url": "https://packagist.org/downloads/", 540 | "license": [ 541 | "MIT" 542 | ], 543 | "authors": [ 544 | { 545 | "name": "Fabien Potencier", 546 | "email": "fabien@symfony.com" 547 | } 548 | ], 549 | "description": "A simple PHP Web Scraper", 550 | "homepage": "https://github.com/FriendsOfPHP/Goutte", 551 | "keywords": [ 552 | "scraper" 553 | ], 554 | "time": "2016-11-15 16:27:29" 555 | }, 556 | { 557 | "name": "guzzlehttp/guzzle", 558 | "version": "6.2.2", 559 | "source": { 560 | "type": "git", 561 | "url": "https://github.com/guzzle/guzzle.git", 562 | "reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60" 563 | }, 564 | "dist": { 565 | "type": "zip", 566 | "url": "https://api.github.com/repos/guzzle/guzzle/zipball/ebf29dee597f02f09f4d5bbecc68230ea9b08f60", 567 | "reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60", 568 | "shasum": "" 569 | }, 570 | "require": { 571 | "guzzlehttp/promises": "^1.0", 572 | "guzzlehttp/psr7": "^1.3.1", 573 | "php": ">=5.5" 574 | }, 575 | "require-dev": { 576 | "ext-curl": "*", 577 | "phpunit/phpunit": "^4.0", 578 | "psr/log": "^1.0" 579 | }, 580 | "type": "library", 581 | "extra": { 582 | "branch-alias": { 583 | "dev-master": "6.2-dev" 584 | } 585 | }, 586 | "autoload": { 587 | "files": [ 588 | "src/functions_include.php" 589 | ], 590 | "psr-4": { 591 | "GuzzleHttp\\": "src/" 592 | } 593 | }, 594 | "notification-url": "https://packagist.org/downloads/", 595 | "license": [ 596 | "MIT" 597 | ], 598 | "authors": [ 599 | { 600 | "name": "Michael Dowling", 601 | "email": "mtdowling@gmail.com", 602 | "homepage": "https://github.com/mtdowling" 603 | } 604 | ], 605 | "description": "Guzzle is a PHP HTTP client library", 606 | "homepage": "http://guzzlephp.org/", 607 | "keywords": [ 608 | "client", 609 | "curl", 610 | "framework", 611 | "http", 612 | "http client", 613 | "rest", 614 | "web service" 615 | ], 616 | "time": "2016-10-08 15:01:37" 617 | }, 618 | { 619 | "name": "guzzlehttp/promises", 620 | "version": "v1.3.1", 621 | "source": { 622 | "type": "git", 623 | "url": "https://github.com/guzzle/promises.git", 624 | "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" 625 | }, 626 | "dist": { 627 | "type": "zip", 628 | "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", 629 | "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", 630 | "shasum": "" 631 | }, 632 | "require": { 633 | "php": ">=5.5.0" 634 | }, 635 | "require-dev": { 636 | "phpunit/phpunit": "^4.0" 637 | }, 638 | "type": "library", 639 | "extra": { 640 | "branch-alias": { 641 | "dev-master": "1.4-dev" 642 | } 643 | }, 644 | "autoload": { 645 | "psr-4": { 646 | "GuzzleHttp\\Promise\\": "src/" 647 | }, 648 | "files": [ 649 | "src/functions_include.php" 650 | ] 651 | }, 652 | "notification-url": "https://packagist.org/downloads/", 653 | "license": [ 654 | "MIT" 655 | ], 656 | "authors": [ 657 | { 658 | "name": "Michael Dowling", 659 | "email": "mtdowling@gmail.com", 660 | "homepage": "https://github.com/mtdowling" 661 | } 662 | ], 663 | "description": "Guzzle promises library", 664 | "keywords": [ 665 | "promise" 666 | ], 667 | "time": "2016-12-20 10:07:11" 668 | }, 669 | { 670 | "name": "guzzlehttp/psr7", 671 | "version": "1.3.1", 672 | "source": { 673 | "type": "git", 674 | "url": "https://github.com/guzzle/psr7.git", 675 | "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b" 676 | }, 677 | "dist": { 678 | "type": "zip", 679 | "url": "https://api.github.com/repos/guzzle/psr7/zipball/5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", 680 | "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", 681 | "shasum": "" 682 | }, 683 | "require": { 684 | "php": ">=5.4.0", 685 | "psr/http-message": "~1.0" 686 | }, 687 | "provide": { 688 | "psr/http-message-implementation": "1.0" 689 | }, 690 | "require-dev": { 691 | "phpunit/phpunit": "~4.0" 692 | }, 693 | "type": "library", 694 | "extra": { 695 | "branch-alias": { 696 | "dev-master": "1.4-dev" 697 | } 698 | }, 699 | "autoload": { 700 | "psr-4": { 701 | "GuzzleHttp\\Psr7\\": "src/" 702 | }, 703 | "files": [ 704 | "src/functions_include.php" 705 | ] 706 | }, 707 | "notification-url": "https://packagist.org/downloads/", 708 | "license": [ 709 | "MIT" 710 | ], 711 | "authors": [ 712 | { 713 | "name": "Michael Dowling", 714 | "email": "mtdowling@gmail.com", 715 | "homepage": "https://github.com/mtdowling" 716 | } 717 | ], 718 | "description": "PSR-7 message implementation", 719 | "keywords": [ 720 | "http", 721 | "message", 722 | "stream", 723 | "uri" 724 | ], 725 | "time": "2016-06-24 23:00:38" 726 | }, 727 | { 728 | "name": "instaclick/php-webdriver", 729 | "version": "1.4.3", 730 | "source": { 731 | "type": "git", 732 | "url": "https://github.com/instaclick/php-webdriver.git", 733 | "reference": "0c20707dcf30a32728fd6bdeeab996c887fdb2fb" 734 | }, 735 | "dist": { 736 | "type": "zip", 737 | "url": "https://api.github.com/repos/instaclick/php-webdriver/zipball/0c20707dcf30a32728fd6bdeeab996c887fdb2fb", 738 | "reference": "0c20707dcf30a32728fd6bdeeab996c887fdb2fb", 739 | "shasum": "" 740 | }, 741 | "require": { 742 | "ext-curl": "*", 743 | "php": ">=5.3.2" 744 | }, 745 | "require-dev": { 746 | "satooshi/php-coveralls": "dev-master" 747 | }, 748 | "type": "library", 749 | "extra": { 750 | "branch-alias": { 751 | "dev-master": "1.4.x-dev" 752 | } 753 | }, 754 | "autoload": { 755 | "psr-0": { 756 | "WebDriver": "lib/" 757 | } 758 | }, 759 | "notification-url": "https://packagist.org/downloads/", 760 | "license": [ 761 | "Apache-2.0" 762 | ], 763 | "authors": [ 764 | { 765 | "name": "Justin Bishop", 766 | "email": "jubishop@gmail.com", 767 | "role": "Developer" 768 | }, 769 | { 770 | "name": "Anthon Pang", 771 | "email": "apang@softwaredevelopment.ca", 772 | "role": "Fork Maintainer" 773 | } 774 | ], 775 | "description": "PHP WebDriver for Selenium 2", 776 | "homepage": "http://instaclick.com/", 777 | "keywords": [ 778 | "browser", 779 | "selenium", 780 | "webdriver", 781 | "webtest" 782 | ], 783 | "time": "2015-06-15 20:19:33" 784 | }, 785 | { 786 | "name": "psr/http-message", 787 | "version": "1.0.1", 788 | "source": { 789 | "type": "git", 790 | "url": "https://github.com/php-fig/http-message.git", 791 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" 792 | }, 793 | "dist": { 794 | "type": "zip", 795 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", 796 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", 797 | "shasum": "" 798 | }, 799 | "require": { 800 | "php": ">=5.3.0" 801 | }, 802 | "type": "library", 803 | "extra": { 804 | "branch-alias": { 805 | "dev-master": "1.0.x-dev" 806 | } 807 | }, 808 | "autoload": { 809 | "psr-4": { 810 | "Psr\\Http\\Message\\": "src/" 811 | } 812 | }, 813 | "notification-url": "https://packagist.org/downloads/", 814 | "license": [ 815 | "MIT" 816 | ], 817 | "authors": [ 818 | { 819 | "name": "PHP-FIG", 820 | "homepage": "http://www.php-fig.org/" 821 | } 822 | ], 823 | "description": "Common interface for HTTP messages", 824 | "homepage": "https://github.com/php-fig/http-message", 825 | "keywords": [ 826 | "http", 827 | "http-message", 828 | "psr", 829 | "psr-7", 830 | "request", 831 | "response" 832 | ], 833 | "time": "2016-08-06 14:39:51" 834 | }, 835 | { 836 | "name": "psr/log", 837 | "version": "1.0.2", 838 | "source": { 839 | "type": "git", 840 | "url": "https://github.com/php-fig/log.git", 841 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" 842 | }, 843 | "dist": { 844 | "type": "zip", 845 | "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", 846 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", 847 | "shasum": "" 848 | }, 849 | "require": { 850 | "php": ">=5.3.0" 851 | }, 852 | "type": "library", 853 | "extra": { 854 | "branch-alias": { 855 | "dev-master": "1.0.x-dev" 856 | } 857 | }, 858 | "autoload": { 859 | "psr-4": { 860 | "Psr\\Log\\": "Psr/Log/" 861 | } 862 | }, 863 | "notification-url": "https://packagist.org/downloads/", 864 | "license": [ 865 | "MIT" 866 | ], 867 | "authors": [ 868 | { 869 | "name": "PHP-FIG", 870 | "homepage": "http://www.php-fig.org/" 871 | } 872 | ], 873 | "description": "Common interface for logging libraries", 874 | "homepage": "https://github.com/php-fig/log", 875 | "keywords": [ 876 | "log", 877 | "psr", 878 | "psr-3" 879 | ], 880 | "time": "2016-10-10 12:19:37" 881 | }, 882 | { 883 | "name": "symfony/browser-kit", 884 | "version": "v3.2.1", 885 | "source": { 886 | "type": "git", 887 | "url": "https://github.com/symfony/browser-kit.git", 888 | "reference": "34348c2691ce6254e8e008026f4c5e72c22bb318" 889 | }, 890 | "dist": { 891 | "type": "zip", 892 | "url": "https://api.github.com/repos/symfony/browser-kit/zipball/34348c2691ce6254e8e008026f4c5e72c22bb318", 893 | "reference": "34348c2691ce6254e8e008026f4c5e72c22bb318", 894 | "shasum": "" 895 | }, 896 | "require": { 897 | "php": ">=5.5.9", 898 | "symfony/dom-crawler": "~2.8|~3.0" 899 | }, 900 | "require-dev": { 901 | "symfony/css-selector": "~2.8|~3.0", 902 | "symfony/process": "~2.8|~3.0" 903 | }, 904 | "suggest": { 905 | "symfony/process": "" 906 | }, 907 | "type": "library", 908 | "extra": { 909 | "branch-alias": { 910 | "dev-master": "3.2-dev" 911 | } 912 | }, 913 | "autoload": { 914 | "psr-4": { 915 | "Symfony\\Component\\BrowserKit\\": "" 916 | }, 917 | "exclude-from-classmap": [ 918 | "/Tests/" 919 | ] 920 | }, 921 | "notification-url": "https://packagist.org/downloads/", 922 | "license": [ 923 | "MIT" 924 | ], 925 | "authors": [ 926 | { 927 | "name": "Fabien Potencier", 928 | "email": "fabien@symfony.com" 929 | }, 930 | { 931 | "name": "Symfony Community", 932 | "homepage": "https://symfony.com/contributors" 933 | } 934 | ], 935 | "description": "Symfony BrowserKit Component", 936 | "homepage": "https://symfony.com", 937 | "time": "2016-10-13 13:35:11" 938 | }, 939 | { 940 | "name": "symfony/class-loader", 941 | "version": "v3.2.1", 942 | "source": { 943 | "type": "git", 944 | "url": "https://github.com/symfony/class-loader.git", 945 | "reference": "87cd4e69435d98de01d0162c5f9c0ac017075c63" 946 | }, 947 | "dist": { 948 | "type": "zip", 949 | "url": "https://api.github.com/repos/symfony/class-loader/zipball/87cd4e69435d98de01d0162c5f9c0ac017075c63", 950 | "reference": "87cd4e69435d98de01d0162c5f9c0ac017075c63", 951 | "shasum": "" 952 | }, 953 | "require": { 954 | "php": ">=5.5.9" 955 | }, 956 | "require-dev": { 957 | "symfony/finder": "~2.8|~3.0", 958 | "symfony/polyfill-apcu": "~1.1" 959 | }, 960 | "suggest": { 961 | "symfony/polyfill-apcu": "For using ApcClassLoader on HHVM" 962 | }, 963 | "type": "library", 964 | "extra": { 965 | "branch-alias": { 966 | "dev-master": "3.2-dev" 967 | } 968 | }, 969 | "autoload": { 970 | "psr-4": { 971 | "Symfony\\Component\\ClassLoader\\": "" 972 | }, 973 | "exclude-from-classmap": [ 974 | "/Tests/" 975 | ] 976 | }, 977 | "notification-url": "https://packagist.org/downloads/", 978 | "license": [ 979 | "MIT" 980 | ], 981 | "authors": [ 982 | { 983 | "name": "Fabien Potencier", 984 | "email": "fabien@symfony.com" 985 | }, 986 | { 987 | "name": "Symfony Community", 988 | "homepage": "https://symfony.com/contributors" 989 | } 990 | ], 991 | "description": "Symfony ClassLoader Component", 992 | "homepage": "https://symfony.com", 993 | "time": "2016-11-29 08:26:13" 994 | }, 995 | { 996 | "name": "symfony/config", 997 | "version": "v3.2.1", 998 | "source": { 999 | "type": "git", 1000 | "url": "https://github.com/symfony/config.git", 1001 | "reference": "b4ec9f099599cfc5b7f4d07bb2e910781a2be5e4" 1002 | }, 1003 | "dist": { 1004 | "type": "zip", 1005 | "url": "https://api.github.com/repos/symfony/config/zipball/b4ec9f099599cfc5b7f4d07bb2e910781a2be5e4", 1006 | "reference": "b4ec9f099599cfc5b7f4d07bb2e910781a2be5e4", 1007 | "shasum": "" 1008 | }, 1009 | "require": { 1010 | "php": ">=5.5.9", 1011 | "symfony/filesystem": "~2.8|~3.0" 1012 | }, 1013 | "require-dev": { 1014 | "symfony/yaml": "~3.0" 1015 | }, 1016 | "suggest": { 1017 | "symfony/yaml": "To use the yaml reference dumper" 1018 | }, 1019 | "type": "library", 1020 | "extra": { 1021 | "branch-alias": { 1022 | "dev-master": "3.2-dev" 1023 | } 1024 | }, 1025 | "autoload": { 1026 | "psr-4": { 1027 | "Symfony\\Component\\Config\\": "" 1028 | }, 1029 | "exclude-from-classmap": [ 1030 | "/Tests/" 1031 | ] 1032 | }, 1033 | "notification-url": "https://packagist.org/downloads/", 1034 | "license": [ 1035 | "MIT" 1036 | ], 1037 | "authors": [ 1038 | { 1039 | "name": "Fabien Potencier", 1040 | "email": "fabien@symfony.com" 1041 | }, 1042 | { 1043 | "name": "Symfony Community", 1044 | "homepage": "https://symfony.com/contributors" 1045 | } 1046 | ], 1047 | "description": "Symfony Config Component", 1048 | "homepage": "https://symfony.com", 1049 | "time": "2016-12-09 07:45:17" 1050 | }, 1051 | { 1052 | "name": "symfony/console", 1053 | "version": "v3.2.1", 1054 | "source": { 1055 | "type": "git", 1056 | "url": "https://github.com/symfony/console.git", 1057 | "reference": "d12aa9ca20f4db83ec58410978dab6afcb9d6aaa" 1058 | }, 1059 | "dist": { 1060 | "type": "zip", 1061 | "url": "https://api.github.com/repos/symfony/console/zipball/d12aa9ca20f4db83ec58410978dab6afcb9d6aaa", 1062 | "reference": "d12aa9ca20f4db83ec58410978dab6afcb9d6aaa", 1063 | "shasum": "" 1064 | }, 1065 | "require": { 1066 | "php": ">=5.5.9", 1067 | "symfony/debug": "~2.8|~3.0", 1068 | "symfony/polyfill-mbstring": "~1.0" 1069 | }, 1070 | "require-dev": { 1071 | "psr/log": "~1.0", 1072 | "symfony/event-dispatcher": "~2.8|~3.0", 1073 | "symfony/filesystem": "~2.8|~3.0", 1074 | "symfony/process": "~2.8|~3.0" 1075 | }, 1076 | "suggest": { 1077 | "psr/log": "For using the console logger", 1078 | "symfony/event-dispatcher": "", 1079 | "symfony/filesystem": "", 1080 | "symfony/process": "" 1081 | }, 1082 | "type": "library", 1083 | "extra": { 1084 | "branch-alias": { 1085 | "dev-master": "3.2-dev" 1086 | } 1087 | }, 1088 | "autoload": { 1089 | "psr-4": { 1090 | "Symfony\\Component\\Console\\": "" 1091 | }, 1092 | "exclude-from-classmap": [ 1093 | "/Tests/" 1094 | ] 1095 | }, 1096 | "notification-url": "https://packagist.org/downloads/", 1097 | "license": [ 1098 | "MIT" 1099 | ], 1100 | "authors": [ 1101 | { 1102 | "name": "Fabien Potencier", 1103 | "email": "fabien@symfony.com" 1104 | }, 1105 | { 1106 | "name": "Symfony Community", 1107 | "homepage": "https://symfony.com/contributors" 1108 | } 1109 | ], 1110 | "description": "Symfony Console Component", 1111 | "homepage": "https://symfony.com", 1112 | "time": "2016-12-11 14:34:22" 1113 | }, 1114 | { 1115 | "name": "symfony/css-selector", 1116 | "version": "v3.2.1", 1117 | "source": { 1118 | "type": "git", 1119 | "url": "https://github.com/symfony/css-selector.git", 1120 | "reference": "e1241f275814827c411d922ba8e64cf2a00b2994" 1121 | }, 1122 | "dist": { 1123 | "type": "zip", 1124 | "url": "https://api.github.com/repos/symfony/css-selector/zipball/e1241f275814827c411d922ba8e64cf2a00b2994", 1125 | "reference": "e1241f275814827c411d922ba8e64cf2a00b2994", 1126 | "shasum": "" 1127 | }, 1128 | "require": { 1129 | "php": ">=5.5.9" 1130 | }, 1131 | "type": "library", 1132 | "extra": { 1133 | "branch-alias": { 1134 | "dev-master": "3.2-dev" 1135 | } 1136 | }, 1137 | "autoload": { 1138 | "psr-4": { 1139 | "Symfony\\Component\\CssSelector\\": "" 1140 | }, 1141 | "exclude-from-classmap": [ 1142 | "/Tests/" 1143 | ] 1144 | }, 1145 | "notification-url": "https://packagist.org/downloads/", 1146 | "license": [ 1147 | "MIT" 1148 | ], 1149 | "authors": [ 1150 | { 1151 | "name": "Jean-François Simon", 1152 | "email": "jeanfrancois.simon@sensiolabs.com" 1153 | }, 1154 | { 1155 | "name": "Fabien Potencier", 1156 | "email": "fabien@symfony.com" 1157 | }, 1158 | { 1159 | "name": "Symfony Community", 1160 | "homepage": "https://symfony.com/contributors" 1161 | } 1162 | ], 1163 | "description": "Symfony CssSelector Component", 1164 | "homepage": "https://symfony.com", 1165 | "time": "2016-11-03 08:11:03" 1166 | }, 1167 | { 1168 | "name": "symfony/debug", 1169 | "version": "v3.2.1", 1170 | "source": { 1171 | "type": "git", 1172 | "url": "https://github.com/symfony/debug.git", 1173 | "reference": "9f923e68d524a3095c5a2ae5fc7220c7cbc12231" 1174 | }, 1175 | "dist": { 1176 | "type": "zip", 1177 | "url": "https://api.github.com/repos/symfony/debug/zipball/9f923e68d524a3095c5a2ae5fc7220c7cbc12231", 1178 | "reference": "9f923e68d524a3095c5a2ae5fc7220c7cbc12231", 1179 | "shasum": "" 1180 | }, 1181 | "require": { 1182 | "php": ">=5.5.9", 1183 | "psr/log": "~1.0" 1184 | }, 1185 | "conflict": { 1186 | "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" 1187 | }, 1188 | "require-dev": { 1189 | "symfony/class-loader": "~2.8|~3.0", 1190 | "symfony/http-kernel": "~2.8|~3.0" 1191 | }, 1192 | "type": "library", 1193 | "extra": { 1194 | "branch-alias": { 1195 | "dev-master": "3.2-dev" 1196 | } 1197 | }, 1198 | "autoload": { 1199 | "psr-4": { 1200 | "Symfony\\Component\\Debug\\": "" 1201 | }, 1202 | "exclude-from-classmap": [ 1203 | "/Tests/" 1204 | ] 1205 | }, 1206 | "notification-url": "https://packagist.org/downloads/", 1207 | "license": [ 1208 | "MIT" 1209 | ], 1210 | "authors": [ 1211 | { 1212 | "name": "Fabien Potencier", 1213 | "email": "fabien@symfony.com" 1214 | }, 1215 | { 1216 | "name": "Symfony Community", 1217 | "homepage": "https://symfony.com/contributors" 1218 | } 1219 | ], 1220 | "description": "Symfony Debug Component", 1221 | "homepage": "https://symfony.com", 1222 | "time": "2016-11-16 22:18:16" 1223 | }, 1224 | { 1225 | "name": "symfony/dependency-injection", 1226 | "version": "v3.2.1", 1227 | "source": { 1228 | "type": "git", 1229 | "url": "https://github.com/symfony/dependency-injection.git", 1230 | "reference": "037054501c41007c93b6de1b5c7a7acb83523593" 1231 | }, 1232 | "dist": { 1233 | "type": "zip", 1234 | "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/037054501c41007c93b6de1b5c7a7acb83523593", 1235 | "reference": "037054501c41007c93b6de1b5c7a7acb83523593", 1236 | "shasum": "" 1237 | }, 1238 | "require": { 1239 | "php": ">=5.5.9" 1240 | }, 1241 | "conflict": { 1242 | "symfony/yaml": "<3.2" 1243 | }, 1244 | "require-dev": { 1245 | "symfony/config": "~2.8|~3.0", 1246 | "symfony/expression-language": "~2.8|~3.0", 1247 | "symfony/yaml": "~3.2" 1248 | }, 1249 | "suggest": { 1250 | "symfony/config": "", 1251 | "symfony/expression-language": "For using expressions in service container configuration", 1252 | "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", 1253 | "symfony/yaml": "" 1254 | }, 1255 | "type": "library", 1256 | "extra": { 1257 | "branch-alias": { 1258 | "dev-master": "3.2-dev" 1259 | } 1260 | }, 1261 | "autoload": { 1262 | "psr-4": { 1263 | "Symfony\\Component\\DependencyInjection\\": "" 1264 | }, 1265 | "exclude-from-classmap": [ 1266 | "/Tests/" 1267 | ] 1268 | }, 1269 | "notification-url": "https://packagist.org/downloads/", 1270 | "license": [ 1271 | "MIT" 1272 | ], 1273 | "authors": [ 1274 | { 1275 | "name": "Fabien Potencier", 1276 | "email": "fabien@symfony.com" 1277 | }, 1278 | { 1279 | "name": "Symfony Community", 1280 | "homepage": "https://symfony.com/contributors" 1281 | } 1282 | ], 1283 | "description": "Symfony DependencyInjection Component", 1284 | "homepage": "https://symfony.com", 1285 | "time": "2016-12-08 15:27:33" 1286 | }, 1287 | { 1288 | "name": "symfony/dom-crawler", 1289 | "version": "v3.2.1", 1290 | "source": { 1291 | "type": "git", 1292 | "url": "https://github.com/symfony/dom-crawler.git", 1293 | "reference": "1638c7534a8a2fa0bf9e979f9aacb6d7e8e9e24e" 1294 | }, 1295 | "dist": { 1296 | "type": "zip", 1297 | "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/1638c7534a8a2fa0bf9e979f9aacb6d7e8e9e24e", 1298 | "reference": "1638c7534a8a2fa0bf9e979f9aacb6d7e8e9e24e", 1299 | "shasum": "" 1300 | }, 1301 | "require": { 1302 | "php": ">=5.5.9", 1303 | "symfony/polyfill-mbstring": "~1.0" 1304 | }, 1305 | "require-dev": { 1306 | "symfony/css-selector": "~2.8|~3.0" 1307 | }, 1308 | "suggest": { 1309 | "symfony/css-selector": "" 1310 | }, 1311 | "type": "library", 1312 | "extra": { 1313 | "branch-alias": { 1314 | "dev-master": "3.2-dev" 1315 | } 1316 | }, 1317 | "autoload": { 1318 | "psr-4": { 1319 | "Symfony\\Component\\DomCrawler\\": "" 1320 | }, 1321 | "exclude-from-classmap": [ 1322 | "/Tests/" 1323 | ] 1324 | }, 1325 | "notification-url": "https://packagist.org/downloads/", 1326 | "license": [ 1327 | "MIT" 1328 | ], 1329 | "authors": [ 1330 | { 1331 | "name": "Fabien Potencier", 1332 | "email": "fabien@symfony.com" 1333 | }, 1334 | { 1335 | "name": "Symfony Community", 1336 | "homepage": "https://symfony.com/contributors" 1337 | } 1338 | ], 1339 | "description": "Symfony DomCrawler Component", 1340 | "homepage": "https://symfony.com", 1341 | "time": "2016-12-10 14:24:53" 1342 | }, 1343 | { 1344 | "name": "symfony/event-dispatcher", 1345 | "version": "v3.2.1", 1346 | "source": { 1347 | "type": "git", 1348 | "url": "https://github.com/symfony/event-dispatcher.git", 1349 | "reference": "e8f47a327c2f0fd5aa04fa60af2b693006ed7283" 1350 | }, 1351 | "dist": { 1352 | "type": "zip", 1353 | "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/e8f47a327c2f0fd5aa04fa60af2b693006ed7283", 1354 | "reference": "e8f47a327c2f0fd5aa04fa60af2b693006ed7283", 1355 | "shasum": "" 1356 | }, 1357 | "require": { 1358 | "php": ">=5.5.9" 1359 | }, 1360 | "require-dev": { 1361 | "psr/log": "~1.0", 1362 | "symfony/config": "~2.8|~3.0", 1363 | "symfony/dependency-injection": "~2.8|~3.0", 1364 | "symfony/expression-language": "~2.8|~3.0", 1365 | "symfony/stopwatch": "~2.8|~3.0" 1366 | }, 1367 | "suggest": { 1368 | "symfony/dependency-injection": "", 1369 | "symfony/http-kernel": "" 1370 | }, 1371 | "type": "library", 1372 | "extra": { 1373 | "branch-alias": { 1374 | "dev-master": "3.2-dev" 1375 | } 1376 | }, 1377 | "autoload": { 1378 | "psr-4": { 1379 | "Symfony\\Component\\EventDispatcher\\": "" 1380 | }, 1381 | "exclude-from-classmap": [ 1382 | "/Tests/" 1383 | ] 1384 | }, 1385 | "notification-url": "https://packagist.org/downloads/", 1386 | "license": [ 1387 | "MIT" 1388 | ], 1389 | "authors": [ 1390 | { 1391 | "name": "Fabien Potencier", 1392 | "email": "fabien@symfony.com" 1393 | }, 1394 | { 1395 | "name": "Symfony Community", 1396 | "homepage": "https://symfony.com/contributors" 1397 | } 1398 | ], 1399 | "description": "Symfony EventDispatcher Component", 1400 | "homepage": "https://symfony.com", 1401 | "time": "2016-10-13 06:29:04" 1402 | }, 1403 | { 1404 | "name": "symfony/filesystem", 1405 | "version": "v3.2.1", 1406 | "source": { 1407 | "type": "git", 1408 | "url": "https://github.com/symfony/filesystem.git", 1409 | "reference": "8d4cf7561a5b17e5eb7a02b80d0b8f014a3796d4" 1410 | }, 1411 | "dist": { 1412 | "type": "zip", 1413 | "url": "https://api.github.com/repos/symfony/filesystem/zipball/8d4cf7561a5b17e5eb7a02b80d0b8f014a3796d4", 1414 | "reference": "8d4cf7561a5b17e5eb7a02b80d0b8f014a3796d4", 1415 | "shasum": "" 1416 | }, 1417 | "require": { 1418 | "php": ">=5.5.9" 1419 | }, 1420 | "type": "library", 1421 | "extra": { 1422 | "branch-alias": { 1423 | "dev-master": "3.2-dev" 1424 | } 1425 | }, 1426 | "autoload": { 1427 | "psr-4": { 1428 | "Symfony\\Component\\Filesystem\\": "" 1429 | }, 1430 | "exclude-from-classmap": [ 1431 | "/Tests/" 1432 | ] 1433 | }, 1434 | "notification-url": "https://packagist.org/downloads/", 1435 | "license": [ 1436 | "MIT" 1437 | ], 1438 | "authors": [ 1439 | { 1440 | "name": "Fabien Potencier", 1441 | "email": "fabien@symfony.com" 1442 | }, 1443 | { 1444 | "name": "Symfony Community", 1445 | "homepage": "https://symfony.com/contributors" 1446 | } 1447 | ], 1448 | "description": "Symfony Filesystem Component", 1449 | "homepage": "https://symfony.com", 1450 | "time": "2016-11-24 00:46:43" 1451 | }, 1452 | { 1453 | "name": "symfony/polyfill-mbstring", 1454 | "version": "v1.3.0", 1455 | "source": { 1456 | "type": "git", 1457 | "url": "https://github.com/symfony/polyfill-mbstring.git", 1458 | "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4" 1459 | }, 1460 | "dist": { 1461 | "type": "zip", 1462 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4", 1463 | "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4", 1464 | "shasum": "" 1465 | }, 1466 | "require": { 1467 | "php": ">=5.3.3" 1468 | }, 1469 | "suggest": { 1470 | "ext-mbstring": "For best performance" 1471 | }, 1472 | "type": "library", 1473 | "extra": { 1474 | "branch-alias": { 1475 | "dev-master": "1.3-dev" 1476 | } 1477 | }, 1478 | "autoload": { 1479 | "psr-4": { 1480 | "Symfony\\Polyfill\\Mbstring\\": "" 1481 | }, 1482 | "files": [ 1483 | "bootstrap.php" 1484 | ] 1485 | }, 1486 | "notification-url": "https://packagist.org/downloads/", 1487 | "license": [ 1488 | "MIT" 1489 | ], 1490 | "authors": [ 1491 | { 1492 | "name": "Nicolas Grekas", 1493 | "email": "p@tchwork.com" 1494 | }, 1495 | { 1496 | "name": "Symfony Community", 1497 | "homepage": "https://symfony.com/contributors" 1498 | } 1499 | ], 1500 | "description": "Symfony polyfill for the Mbstring extension", 1501 | "homepage": "https://symfony.com", 1502 | "keywords": [ 1503 | "compatibility", 1504 | "mbstring", 1505 | "polyfill", 1506 | "portable", 1507 | "shim" 1508 | ], 1509 | "time": "2016-11-14 01:06:16" 1510 | }, 1511 | { 1512 | "name": "symfony/translation", 1513 | "version": "v3.2.1", 1514 | "source": { 1515 | "type": "git", 1516 | "url": "https://github.com/symfony/translation.git", 1517 | "reference": "5fd18eca88f4d187807a1eba083bc99feaa8635b" 1518 | }, 1519 | "dist": { 1520 | "type": "zip", 1521 | "url": "https://api.github.com/repos/symfony/translation/zipball/5fd18eca88f4d187807a1eba083bc99feaa8635b", 1522 | "reference": "5fd18eca88f4d187807a1eba083bc99feaa8635b", 1523 | "shasum": "" 1524 | }, 1525 | "require": { 1526 | "php": ">=5.5.9", 1527 | "symfony/polyfill-mbstring": "~1.0" 1528 | }, 1529 | "conflict": { 1530 | "symfony/config": "<2.8" 1531 | }, 1532 | "require-dev": { 1533 | "psr/log": "~1.0", 1534 | "symfony/config": "~2.8|~3.0", 1535 | "symfony/intl": "~2.8|~3.0", 1536 | "symfony/yaml": "~2.8|~3.0" 1537 | }, 1538 | "suggest": { 1539 | "psr/log": "To use logging capability in translator", 1540 | "symfony/config": "", 1541 | "symfony/yaml": "" 1542 | }, 1543 | "type": "library", 1544 | "extra": { 1545 | "branch-alias": { 1546 | "dev-master": "3.2-dev" 1547 | } 1548 | }, 1549 | "autoload": { 1550 | "psr-4": { 1551 | "Symfony\\Component\\Translation\\": "" 1552 | }, 1553 | "exclude-from-classmap": [ 1554 | "/Tests/" 1555 | ] 1556 | }, 1557 | "notification-url": "https://packagist.org/downloads/", 1558 | "license": [ 1559 | "MIT" 1560 | ], 1561 | "authors": [ 1562 | { 1563 | "name": "Fabien Potencier", 1564 | "email": "fabien@symfony.com" 1565 | }, 1566 | { 1567 | "name": "Symfony Community", 1568 | "homepage": "https://symfony.com/contributors" 1569 | } 1570 | ], 1571 | "description": "Symfony Translation Component", 1572 | "homepage": "https://symfony.com", 1573 | "time": "2016-11-30 14:40:17" 1574 | }, 1575 | { 1576 | "name": "symfony/yaml", 1577 | "version": "v3.2.1", 1578 | "source": { 1579 | "type": "git", 1580 | "url": "https://github.com/symfony/yaml.git", 1581 | "reference": "a7095af4b97a0955f85c8989106c249fa649011f" 1582 | }, 1583 | "dist": { 1584 | "type": "zip", 1585 | "url": "https://api.github.com/repos/symfony/yaml/zipball/a7095af4b97a0955f85c8989106c249fa649011f", 1586 | "reference": "a7095af4b97a0955f85c8989106c249fa649011f", 1587 | "shasum": "" 1588 | }, 1589 | "require": { 1590 | "php": ">=5.5.9" 1591 | }, 1592 | "require-dev": { 1593 | "symfony/console": "~2.8|~3.0" 1594 | }, 1595 | "suggest": { 1596 | "symfony/console": "For validating YAML files using the lint command" 1597 | }, 1598 | "type": "library", 1599 | "extra": { 1600 | "branch-alias": { 1601 | "dev-master": "3.2-dev" 1602 | } 1603 | }, 1604 | "autoload": { 1605 | "psr-4": { 1606 | "Symfony\\Component\\Yaml\\": "" 1607 | }, 1608 | "exclude-from-classmap": [ 1609 | "/Tests/" 1610 | ] 1611 | }, 1612 | "notification-url": "https://packagist.org/downloads/", 1613 | "license": [ 1614 | "MIT" 1615 | ], 1616 | "authors": [ 1617 | { 1618 | "name": "Fabien Potencier", 1619 | "email": "fabien@symfony.com" 1620 | }, 1621 | { 1622 | "name": "Symfony Community", 1623 | "homepage": "https://symfony.com/contributors" 1624 | } 1625 | ], 1626 | "description": "Symfony Yaml Component", 1627 | "homepage": "https://symfony.com", 1628 | "time": "2016-12-10 10:07:06" 1629 | } 1630 | ], 1631 | "packages-dev": [ 1632 | { 1633 | "name": "doctrine/instantiator", 1634 | "version": "1.0.5", 1635 | "source": { 1636 | "type": "git", 1637 | "url": "https://github.com/doctrine/instantiator.git", 1638 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" 1639 | }, 1640 | "dist": { 1641 | "type": "zip", 1642 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", 1643 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", 1644 | "shasum": "" 1645 | }, 1646 | "require": { 1647 | "php": ">=5.3,<8.0-DEV" 1648 | }, 1649 | "require-dev": { 1650 | "athletic/athletic": "~0.1.8", 1651 | "ext-pdo": "*", 1652 | "ext-phar": "*", 1653 | "phpunit/phpunit": "~4.0", 1654 | "squizlabs/php_codesniffer": "~2.0" 1655 | }, 1656 | "type": "library", 1657 | "extra": { 1658 | "branch-alias": { 1659 | "dev-master": "1.0.x-dev" 1660 | } 1661 | }, 1662 | "autoload": { 1663 | "psr-4": { 1664 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 1665 | } 1666 | }, 1667 | "notification-url": "https://packagist.org/downloads/", 1668 | "license": [ 1669 | "MIT" 1670 | ], 1671 | "authors": [ 1672 | { 1673 | "name": "Marco Pivetta", 1674 | "email": "ocramius@gmail.com", 1675 | "homepage": "http://ocramius.github.com/" 1676 | } 1677 | ], 1678 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 1679 | "homepage": "https://github.com/doctrine/instantiator", 1680 | "keywords": [ 1681 | "constructor", 1682 | "instantiate" 1683 | ], 1684 | "time": "2015-06-14 21:17:01" 1685 | }, 1686 | { 1687 | "name": "phpdocumentor/reflection-common", 1688 | "version": "1.0", 1689 | "source": { 1690 | "type": "git", 1691 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 1692 | "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" 1693 | }, 1694 | "dist": { 1695 | "type": "zip", 1696 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", 1697 | "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", 1698 | "shasum": "" 1699 | }, 1700 | "require": { 1701 | "php": ">=5.5" 1702 | }, 1703 | "require-dev": { 1704 | "phpunit/phpunit": "^4.6" 1705 | }, 1706 | "type": "library", 1707 | "extra": { 1708 | "branch-alias": { 1709 | "dev-master": "1.0.x-dev" 1710 | } 1711 | }, 1712 | "autoload": { 1713 | "psr-4": { 1714 | "phpDocumentor\\Reflection\\": [ 1715 | "src" 1716 | ] 1717 | } 1718 | }, 1719 | "notification-url": "https://packagist.org/downloads/", 1720 | "license": [ 1721 | "MIT" 1722 | ], 1723 | "authors": [ 1724 | { 1725 | "name": "Jaap van Otterdijk", 1726 | "email": "opensource@ijaap.nl" 1727 | } 1728 | ], 1729 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 1730 | "homepage": "http://www.phpdoc.org", 1731 | "keywords": [ 1732 | "FQSEN", 1733 | "phpDocumentor", 1734 | "phpdoc", 1735 | "reflection", 1736 | "static analysis" 1737 | ], 1738 | "time": "2015-12-27 11:43:31" 1739 | }, 1740 | { 1741 | "name": "phpdocumentor/reflection-docblock", 1742 | "version": "3.1.1", 1743 | "source": { 1744 | "type": "git", 1745 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 1746 | "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" 1747 | }, 1748 | "dist": { 1749 | "type": "zip", 1750 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", 1751 | "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", 1752 | "shasum": "" 1753 | }, 1754 | "require": { 1755 | "php": ">=5.5", 1756 | "phpdocumentor/reflection-common": "^1.0@dev", 1757 | "phpdocumentor/type-resolver": "^0.2.0", 1758 | "webmozart/assert": "^1.0" 1759 | }, 1760 | "require-dev": { 1761 | "mockery/mockery": "^0.9.4", 1762 | "phpunit/phpunit": "^4.4" 1763 | }, 1764 | "type": "library", 1765 | "autoload": { 1766 | "psr-4": { 1767 | "phpDocumentor\\Reflection\\": [ 1768 | "src/" 1769 | ] 1770 | } 1771 | }, 1772 | "notification-url": "https://packagist.org/downloads/", 1773 | "license": [ 1774 | "MIT" 1775 | ], 1776 | "authors": [ 1777 | { 1778 | "name": "Mike van Riel", 1779 | "email": "me@mikevanriel.com" 1780 | } 1781 | ], 1782 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 1783 | "time": "2016-09-30 07:12:33" 1784 | }, 1785 | { 1786 | "name": "phpdocumentor/type-resolver", 1787 | "version": "0.2.1", 1788 | "source": { 1789 | "type": "git", 1790 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 1791 | "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb" 1792 | }, 1793 | "dist": { 1794 | "type": "zip", 1795 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", 1796 | "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", 1797 | "shasum": "" 1798 | }, 1799 | "require": { 1800 | "php": ">=5.5", 1801 | "phpdocumentor/reflection-common": "^1.0" 1802 | }, 1803 | "require-dev": { 1804 | "mockery/mockery": "^0.9.4", 1805 | "phpunit/phpunit": "^5.2||^4.8.24" 1806 | }, 1807 | "type": "library", 1808 | "extra": { 1809 | "branch-alias": { 1810 | "dev-master": "1.0.x-dev" 1811 | } 1812 | }, 1813 | "autoload": { 1814 | "psr-4": { 1815 | "phpDocumentor\\Reflection\\": [ 1816 | "src/" 1817 | ] 1818 | } 1819 | }, 1820 | "notification-url": "https://packagist.org/downloads/", 1821 | "license": [ 1822 | "MIT" 1823 | ], 1824 | "authors": [ 1825 | { 1826 | "name": "Mike van Riel", 1827 | "email": "me@mikevanriel.com" 1828 | } 1829 | ], 1830 | "time": "2016-11-25 06:54:22" 1831 | }, 1832 | { 1833 | "name": "phpspec/php-diff", 1834 | "version": "v1.1.0", 1835 | "source": { 1836 | "type": "git", 1837 | "url": "https://github.com/phpspec/php-diff.git", 1838 | "reference": "0464787bfa7cd13576c5a1e318709768798bec6a" 1839 | }, 1840 | "dist": { 1841 | "type": "zip", 1842 | "url": "https://api.github.com/repos/phpspec/php-diff/zipball/0464787bfa7cd13576c5a1e318709768798bec6a", 1843 | "reference": "0464787bfa7cd13576c5a1e318709768798bec6a", 1844 | "shasum": "" 1845 | }, 1846 | "type": "library", 1847 | "extra": { 1848 | "branch-alias": { 1849 | "dev-master": "1.0.x-dev" 1850 | } 1851 | }, 1852 | "autoload": { 1853 | "psr-0": { 1854 | "Diff": "lib/" 1855 | } 1856 | }, 1857 | "notification-url": "https://packagist.org/downloads/", 1858 | "license": [ 1859 | "BSD-3-Clause" 1860 | ], 1861 | "authors": [ 1862 | { 1863 | "name": "Chris Boulton", 1864 | "homepage": "http://github.com/chrisboulton" 1865 | } 1866 | ], 1867 | "description": "A comprehensive library for generating differences between two hashable objects (strings or arrays).", 1868 | "time": "2016-04-07 12:29:16" 1869 | }, 1870 | { 1871 | "name": "phpspec/phpspec", 1872 | "version": "3.2.2", 1873 | "source": { 1874 | "type": "git", 1875 | "url": "https://github.com/phpspec/phpspec.git", 1876 | "reference": "019a113b657aed90a4aa8f5e39696800779b8b2c" 1877 | }, 1878 | "dist": { 1879 | "type": "zip", 1880 | "url": "https://api.github.com/repos/phpspec/phpspec/zipball/019a113b657aed90a4aa8f5e39696800779b8b2c", 1881 | "reference": "019a113b657aed90a4aa8f5e39696800779b8b2c", 1882 | "shasum": "" 1883 | }, 1884 | "require": { 1885 | "doctrine/instantiator": "^1.0.1", 1886 | "ext-tokenizer": "*", 1887 | "php": "^5.6 || ^7.0", 1888 | "phpspec/php-diff": "^1.0.0", 1889 | "phpspec/prophecy": "^1.5", 1890 | "sebastian/exporter": "^1.0 || ^2.0", 1891 | "symfony/console": "^2.7 || ^3.0", 1892 | "symfony/event-dispatcher": "^2.7 || ^3.0", 1893 | "symfony/finder": "^2.7 || ^3.0", 1894 | "symfony/process": "^2.7 || ^3.0", 1895 | "symfony/yaml": "^2.7 || ^3.0" 1896 | }, 1897 | "require-dev": { 1898 | "behat/behat": "^3.1", 1899 | "ciaranmcnulty/versionbasedtestskipper": "^0.2.1", 1900 | "phpunit/phpunit": "^5.4", 1901 | "symfony/filesystem": "^3.0" 1902 | }, 1903 | "suggest": { 1904 | "phpspec/nyan-formatters": "Adds Nyan formatters" 1905 | }, 1906 | "bin": [ 1907 | "bin/phpspec" 1908 | ], 1909 | "type": "library", 1910 | "extra": { 1911 | "branch-alias": { 1912 | "dev-master": "3.0.x-dev" 1913 | } 1914 | }, 1915 | "autoload": { 1916 | "psr-0": { 1917 | "PhpSpec": "src/" 1918 | } 1919 | }, 1920 | "notification-url": "https://packagist.org/downloads/", 1921 | "license": [ 1922 | "MIT" 1923 | ], 1924 | "authors": [ 1925 | { 1926 | "name": "Konstantin Kudryashov", 1927 | "email": "ever.zet@gmail.com", 1928 | "homepage": "http://everzet.com" 1929 | }, 1930 | { 1931 | "name": "Marcello Duarte", 1932 | "homepage": "http://marcelloduarte.net/" 1933 | }, 1934 | { 1935 | "name": "Ciaran McNulty", 1936 | "homepage": "https://ciaranmcnulty.com/" 1937 | } 1938 | ], 1939 | "description": "Specification-oriented BDD framework for PHP 5.6+", 1940 | "homepage": "http://phpspec.net/", 1941 | "keywords": [ 1942 | "BDD", 1943 | "SpecBDD", 1944 | "TDD", 1945 | "spec", 1946 | "specification", 1947 | "testing", 1948 | "tests" 1949 | ], 1950 | "time": "2016-12-05 13:46:47" 1951 | }, 1952 | { 1953 | "name": "phpspec/prophecy", 1954 | "version": "v1.6.2", 1955 | "source": { 1956 | "type": "git", 1957 | "url": "https://github.com/phpspec/prophecy.git", 1958 | "reference": "6c52c2722f8460122f96f86346600e1077ce22cb" 1959 | }, 1960 | "dist": { 1961 | "type": "zip", 1962 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", 1963 | "reference": "6c52c2722f8460122f96f86346600e1077ce22cb", 1964 | "shasum": "" 1965 | }, 1966 | "require": { 1967 | "doctrine/instantiator": "^1.0.2", 1968 | "php": "^5.3|^7.0", 1969 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", 1970 | "sebastian/comparator": "^1.1", 1971 | "sebastian/recursion-context": "^1.0|^2.0" 1972 | }, 1973 | "require-dev": { 1974 | "phpspec/phpspec": "^2.0", 1975 | "phpunit/phpunit": "^4.8 || ^5.6.5" 1976 | }, 1977 | "type": "library", 1978 | "extra": { 1979 | "branch-alias": { 1980 | "dev-master": "1.6.x-dev" 1981 | } 1982 | }, 1983 | "autoload": { 1984 | "psr-0": { 1985 | "Prophecy\\": "src/" 1986 | } 1987 | }, 1988 | "notification-url": "https://packagist.org/downloads/", 1989 | "license": [ 1990 | "MIT" 1991 | ], 1992 | "authors": [ 1993 | { 1994 | "name": "Konstantin Kudryashov", 1995 | "email": "ever.zet@gmail.com", 1996 | "homepage": "http://everzet.com" 1997 | }, 1998 | { 1999 | "name": "Marcello Duarte", 2000 | "email": "marcello.duarte@gmail.com" 2001 | } 2002 | ], 2003 | "description": "Highly opinionated mocking framework for PHP 5.3+", 2004 | "homepage": "https://github.com/phpspec/prophecy", 2005 | "keywords": [ 2006 | "Double", 2007 | "Dummy", 2008 | "fake", 2009 | "mock", 2010 | "spy", 2011 | "stub" 2012 | ], 2013 | "time": "2016-11-21 14:58:47" 2014 | }, 2015 | { 2016 | "name": "sebastian/comparator", 2017 | "version": "1.2.2", 2018 | "source": { 2019 | "type": "git", 2020 | "url": "https://github.com/sebastianbergmann/comparator.git", 2021 | "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f" 2022 | }, 2023 | "dist": { 2024 | "type": "zip", 2025 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/6a1ed12e8b2409076ab22e3897126211ff8b1f7f", 2026 | "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f", 2027 | "shasum": "" 2028 | }, 2029 | "require": { 2030 | "php": ">=5.3.3", 2031 | "sebastian/diff": "~1.2", 2032 | "sebastian/exporter": "~1.2 || ~2.0" 2033 | }, 2034 | "require-dev": { 2035 | "phpunit/phpunit": "~4.4" 2036 | }, 2037 | "type": "library", 2038 | "extra": { 2039 | "branch-alias": { 2040 | "dev-master": "1.2.x-dev" 2041 | } 2042 | }, 2043 | "autoload": { 2044 | "classmap": [ 2045 | "src/" 2046 | ] 2047 | }, 2048 | "notification-url": "https://packagist.org/downloads/", 2049 | "license": [ 2050 | "BSD-3-Clause" 2051 | ], 2052 | "authors": [ 2053 | { 2054 | "name": "Jeff Welch", 2055 | "email": "whatthejeff@gmail.com" 2056 | }, 2057 | { 2058 | "name": "Volker Dusch", 2059 | "email": "github@wallbash.com" 2060 | }, 2061 | { 2062 | "name": "Bernhard Schussek", 2063 | "email": "bschussek@2bepublished.at" 2064 | }, 2065 | { 2066 | "name": "Sebastian Bergmann", 2067 | "email": "sebastian@phpunit.de" 2068 | } 2069 | ], 2070 | "description": "Provides the functionality to compare PHP values for equality", 2071 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 2072 | "keywords": [ 2073 | "comparator", 2074 | "compare", 2075 | "equality" 2076 | ], 2077 | "time": "2016-11-19 09:18:40" 2078 | }, 2079 | { 2080 | "name": "sebastian/diff", 2081 | "version": "1.4.1", 2082 | "source": { 2083 | "type": "git", 2084 | "url": "https://github.com/sebastianbergmann/diff.git", 2085 | "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" 2086 | }, 2087 | "dist": { 2088 | "type": "zip", 2089 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", 2090 | "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", 2091 | "shasum": "" 2092 | }, 2093 | "require": { 2094 | "php": ">=5.3.3" 2095 | }, 2096 | "require-dev": { 2097 | "phpunit/phpunit": "~4.8" 2098 | }, 2099 | "type": "library", 2100 | "extra": { 2101 | "branch-alias": { 2102 | "dev-master": "1.4-dev" 2103 | } 2104 | }, 2105 | "autoload": { 2106 | "classmap": [ 2107 | "src/" 2108 | ] 2109 | }, 2110 | "notification-url": "https://packagist.org/downloads/", 2111 | "license": [ 2112 | "BSD-3-Clause" 2113 | ], 2114 | "authors": [ 2115 | { 2116 | "name": "Kore Nordmann", 2117 | "email": "mail@kore-nordmann.de" 2118 | }, 2119 | { 2120 | "name": "Sebastian Bergmann", 2121 | "email": "sebastian@phpunit.de" 2122 | } 2123 | ], 2124 | "description": "Diff implementation", 2125 | "homepage": "https://github.com/sebastianbergmann/diff", 2126 | "keywords": [ 2127 | "diff" 2128 | ], 2129 | "time": "2015-12-08 07:14:41" 2130 | }, 2131 | { 2132 | "name": "sebastian/exporter", 2133 | "version": "2.0.0", 2134 | "source": { 2135 | "type": "git", 2136 | "url": "https://github.com/sebastianbergmann/exporter.git", 2137 | "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" 2138 | }, 2139 | "dist": { 2140 | "type": "zip", 2141 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", 2142 | "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", 2143 | "shasum": "" 2144 | }, 2145 | "require": { 2146 | "php": ">=5.3.3", 2147 | "sebastian/recursion-context": "~2.0" 2148 | }, 2149 | "require-dev": { 2150 | "ext-mbstring": "*", 2151 | "phpunit/phpunit": "~4.4" 2152 | }, 2153 | "type": "library", 2154 | "extra": { 2155 | "branch-alias": { 2156 | "dev-master": "2.0.x-dev" 2157 | } 2158 | }, 2159 | "autoload": { 2160 | "classmap": [ 2161 | "src/" 2162 | ] 2163 | }, 2164 | "notification-url": "https://packagist.org/downloads/", 2165 | "license": [ 2166 | "BSD-3-Clause" 2167 | ], 2168 | "authors": [ 2169 | { 2170 | "name": "Jeff Welch", 2171 | "email": "whatthejeff@gmail.com" 2172 | }, 2173 | { 2174 | "name": "Volker Dusch", 2175 | "email": "github@wallbash.com" 2176 | }, 2177 | { 2178 | "name": "Bernhard Schussek", 2179 | "email": "bschussek@2bepublished.at" 2180 | }, 2181 | { 2182 | "name": "Sebastian Bergmann", 2183 | "email": "sebastian@phpunit.de" 2184 | }, 2185 | { 2186 | "name": "Adam Harvey", 2187 | "email": "aharvey@php.net" 2188 | } 2189 | ], 2190 | "description": "Provides the functionality to export PHP variables for visualization", 2191 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 2192 | "keywords": [ 2193 | "export", 2194 | "exporter" 2195 | ], 2196 | "time": "2016-11-19 08:54:04" 2197 | }, 2198 | { 2199 | "name": "sebastian/recursion-context", 2200 | "version": "2.0.0", 2201 | "source": { 2202 | "type": "git", 2203 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 2204 | "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" 2205 | }, 2206 | "dist": { 2207 | "type": "zip", 2208 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", 2209 | "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", 2210 | "shasum": "" 2211 | }, 2212 | "require": { 2213 | "php": ">=5.3.3" 2214 | }, 2215 | "require-dev": { 2216 | "phpunit/phpunit": "~4.4" 2217 | }, 2218 | "type": "library", 2219 | "extra": { 2220 | "branch-alias": { 2221 | "dev-master": "2.0.x-dev" 2222 | } 2223 | }, 2224 | "autoload": { 2225 | "classmap": [ 2226 | "src/" 2227 | ] 2228 | }, 2229 | "notification-url": "https://packagist.org/downloads/", 2230 | "license": [ 2231 | "BSD-3-Clause" 2232 | ], 2233 | "authors": [ 2234 | { 2235 | "name": "Jeff Welch", 2236 | "email": "whatthejeff@gmail.com" 2237 | }, 2238 | { 2239 | "name": "Sebastian Bergmann", 2240 | "email": "sebastian@phpunit.de" 2241 | }, 2242 | { 2243 | "name": "Adam Harvey", 2244 | "email": "aharvey@php.net" 2245 | } 2246 | ], 2247 | "description": "Provides functionality to recursively process PHP variables", 2248 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 2249 | "time": "2016-11-19 07:33:16" 2250 | }, 2251 | { 2252 | "name": "symfony/finder", 2253 | "version": "v3.2.1", 2254 | "source": { 2255 | "type": "git", 2256 | "url": "https://github.com/symfony/finder.git", 2257 | "reference": "a69cb5d455b4885ca376dc5bb3e1155cc8c08c4b" 2258 | }, 2259 | "dist": { 2260 | "type": "zip", 2261 | "url": "https://api.github.com/repos/symfony/finder/zipball/a69cb5d455b4885ca376dc5bb3e1155cc8c08c4b", 2262 | "reference": "a69cb5d455b4885ca376dc5bb3e1155cc8c08c4b", 2263 | "shasum": "" 2264 | }, 2265 | "require": { 2266 | "php": ">=5.5.9" 2267 | }, 2268 | "type": "library", 2269 | "extra": { 2270 | "branch-alias": { 2271 | "dev-master": "3.2-dev" 2272 | } 2273 | }, 2274 | "autoload": { 2275 | "psr-4": { 2276 | "Symfony\\Component\\Finder\\": "" 2277 | }, 2278 | "exclude-from-classmap": [ 2279 | "/Tests/" 2280 | ] 2281 | }, 2282 | "notification-url": "https://packagist.org/downloads/", 2283 | "license": [ 2284 | "MIT" 2285 | ], 2286 | "authors": [ 2287 | { 2288 | "name": "Fabien Potencier", 2289 | "email": "fabien@symfony.com" 2290 | }, 2291 | { 2292 | "name": "Symfony Community", 2293 | "homepage": "https://symfony.com/contributors" 2294 | } 2295 | ], 2296 | "description": "Symfony Finder Component", 2297 | "homepage": "https://symfony.com", 2298 | "time": "2016-12-13 09:39:43" 2299 | }, 2300 | { 2301 | "name": "symfony/process", 2302 | "version": "v3.2.1", 2303 | "source": { 2304 | "type": "git", 2305 | "url": "https://github.com/symfony/process.git", 2306 | "reference": "02ea84847aad71be7e32056408bb19f3a616cdd3" 2307 | }, 2308 | "dist": { 2309 | "type": "zip", 2310 | "url": "https://api.github.com/repos/symfony/process/zipball/02ea84847aad71be7e32056408bb19f3a616cdd3", 2311 | "reference": "02ea84847aad71be7e32056408bb19f3a616cdd3", 2312 | "shasum": "" 2313 | }, 2314 | "require": { 2315 | "php": ">=5.5.9" 2316 | }, 2317 | "type": "library", 2318 | "extra": { 2319 | "branch-alias": { 2320 | "dev-master": "3.2-dev" 2321 | } 2322 | }, 2323 | "autoload": { 2324 | "psr-4": { 2325 | "Symfony\\Component\\Process\\": "" 2326 | }, 2327 | "exclude-from-classmap": [ 2328 | "/Tests/" 2329 | ] 2330 | }, 2331 | "notification-url": "https://packagist.org/downloads/", 2332 | "license": [ 2333 | "MIT" 2334 | ], 2335 | "authors": [ 2336 | { 2337 | "name": "Fabien Potencier", 2338 | "email": "fabien@symfony.com" 2339 | }, 2340 | { 2341 | "name": "Symfony Community", 2342 | "homepage": "https://symfony.com/contributors" 2343 | } 2344 | ], 2345 | "description": "Symfony Process Component", 2346 | "homepage": "https://symfony.com", 2347 | "time": "2016-11-24 10:40:28" 2348 | }, 2349 | { 2350 | "name": "webmozart/assert", 2351 | "version": "1.2.0", 2352 | "source": { 2353 | "type": "git", 2354 | "url": "https://github.com/webmozart/assert.git", 2355 | "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" 2356 | }, 2357 | "dist": { 2358 | "type": "zip", 2359 | "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", 2360 | "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", 2361 | "shasum": "" 2362 | }, 2363 | "require": { 2364 | "php": "^5.3.3 || ^7.0" 2365 | }, 2366 | "require-dev": { 2367 | "phpunit/phpunit": "^4.6", 2368 | "sebastian/version": "^1.0.1" 2369 | }, 2370 | "type": "library", 2371 | "extra": { 2372 | "branch-alias": { 2373 | "dev-master": "1.3-dev" 2374 | } 2375 | }, 2376 | "autoload": { 2377 | "psr-4": { 2378 | "Webmozart\\Assert\\": "src/" 2379 | } 2380 | }, 2381 | "notification-url": "https://packagist.org/downloads/", 2382 | "license": [ 2383 | "MIT" 2384 | ], 2385 | "authors": [ 2386 | { 2387 | "name": "Bernhard Schussek", 2388 | "email": "bschussek@gmail.com" 2389 | } 2390 | ], 2391 | "description": "Assertions to validate method input/output with nice error messages.", 2392 | "keywords": [ 2393 | "assert", 2394 | "check", 2395 | "validate" 2396 | ], 2397 | "time": "2016-11-23 20:04:58" 2398 | } 2399 | ], 2400 | "aliases": [], 2401 | "minimum-stability": "stable", 2402 | "stability-flags": [], 2403 | "prefer-stable": false, 2404 | "prefer-lowest": false, 2405 | "platform": [], 2406 | "platform-dev": [] 2407 | } 2408 | --------------------------------------------------------------------------------