├── .circleci ├── auto-update.sh ├── behat-test.sh ├── config.yml ├── deploy-updates.sh ├── lighthouse-performance-test.sh ├── set-framework.sh ├── set-up-globals.sh ├── sites-to-update.sh └── visual-regression-test.sh ├── .gitignore ├── LICENSE ├── README.md ├── backstop.template.json ├── backstop_data └── casper_scripts │ ├── onBefore.js │ └── onReady.js ├── composer.json ├── composer.lock ├── devrel-gutes.backstop-config.js ├── review-signal-pantheon-elite-test-site.backstop-config.js ├── review-signal-pantheon-personal-test-site.backstop-config.js ├── review-signal-pantheon-professional-test-site.backstop-config.js ├── sites-to-auto-update.json ├── solr-power-demo.backstop.json ├── tests └── behat │ ├── behat-pantheon.yml │ ├── wp-microsite │ └── features │ │ └── admin-login.feature │ └── wp-quicksilver-demo │ └── features │ └── admin-login.feature └── wp-new-relic-demo.backstop-config.js /.circleci/auto-update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo -e "\nKicking off an update check for ${SITE_NAME} with UUID ${SITE_UUID}..." 3 | 4 | # login to Terminus 5 | echo -e "\nLogging into Terminus..." 6 | terminus auth:login --machine-token=${TERMINUS_MACHINE_TOKEN} > /dev/null 2>&1 7 | 8 | # Bail on errors 9 | set +ex 10 | 11 | IS_FROZEN="$(terminus site:info ${SITE_UUID} --field=frozen)" 12 | 13 | if [[ ${IS_FROZEN} == "1" ]] 14 | then 15 | echo -e "Update check stopped! The site ${SITE_NAME} is frozen. Either unfreeze the site or consider removing it from the sites to check.\n" 16 | exit 0 17 | fi 18 | 19 | # Helper to see if a multidev exists 20 | TERMINUS_DOES_MULTIDEV_EXIST() 21 | { 22 | # Return 1 if on master since dev always exists 23 | if [[ ${CIRCLE_BRANCH} == "master" ]] 24 | then 25 | return 0; 26 | fi 27 | 28 | # Stash list of Pantheon multidev environments 29 | PANTHEON_MULTIDEV_LIST="$(terminus multidev:list -n ${SITE_NAME} --format=list --field=Name)" 30 | 31 | while read -r CURRENT_MULTIDEV; do 32 | if [[ "${CURRENT_MULTIDEV}" == "$1" ]] 33 | then 34 | return 0; 35 | fi 36 | done <<< "$PANTHEON_MULTIDEV_LIST" 37 | 38 | return 1; 39 | } 40 | 41 | if [[ "$RECREATE_MULTIDEV" == "0" ]] 42 | then 43 | echo -e "\nSkipping deletion and recreation of multidev for ${SITE_NAME}..." 44 | else 45 | # delete the multidev environment if it exists 46 | echo -e "\nDeleting the ${MULTIDEV} multidev environment for ${SITE_NAME}..." 47 | terminus multidev:delete $SITE_UUID.$MULTIDEV --delete-branch --yes 48 | fi 49 | 50 | # Create the multidev environment 51 | echo -e "\nCreating the ${MULTIDEV} multidev environment for ${SITE_NAME}..." 52 | terminus multidev:create $SITE_NAME.live $MULTIDEV 53 | # check for upstream updates 54 | echo -e "\nChecking for upstream updates on the ${MULTIDEV} multidev for ${SITE_NAME}..." 55 | # the output goes to stderr, not stdout 56 | UPSTREAM_UPDATES="$(terminus upstream:updates:list ${SITE_UUID}.${MULTIDEV} --format=list 2>&1)" 57 | 58 | UPDATES_APPLIED=false 59 | 60 | if [[ ${UPSTREAM_UPDATES} == *"no available updates"* ]] 61 | then 62 | # no upstream updates available 63 | echo -e "\nNo upstream updates found on the ${MULTIDEV} multidev for ${SITE_NAME}..." 64 | else 65 | # making sure the multidev is in git mode 66 | echo -e "\nSetting the ${MULTIDEV} multidev to git mode" 67 | terminus connection:set $SITE_UUID.$MULTIDEV git 68 | 69 | # apply WordPress upstream updates 70 | echo -e "\nApplying upstream updates on the ${MULTIDEV} multidev for ${SITE_NAME}..." 71 | terminus upstream:updates:apply $SITE_UUID.$MULTIDEV --yes --updatedb --accept-upstream 72 | UPDATES_APPLIED=true 73 | 74 | if [[ ${CMS_FRAMEWORK} == "wordpress" ]] 75 | then 76 | terminus -n wp $SITE_UUID.$MULTIDEV -- core update-db 77 | fi 78 | 79 | if [[ ${CMS_FRAMEWORK} == "drupal" ]] 80 | then 81 | terminus -n drush $SITE_UUID.$MULTIDEV -- updatedb 82 | fi 83 | 84 | fi 85 | 86 | # making sure the multidev is in SFTP mode 87 | echo -e "\nSetting the ${MULTIDEV} multidev to SFTP mode for ${SITE_NAME}..." 88 | terminus connection:set $SITE_UUID.$MULTIDEV sftp 89 | 90 | # Wake pantheon SSH 91 | terminus -n wp $SITE_UUID.$MULTIDEV -- cli version 92 | 93 | echo -e "\nChecking for ${CMS_CONTRIB} updates on the ${MULTIDEV} multidev for ${SITE_NAME}..." 94 | 95 | # check for WordPress plugin updates 96 | if [[ ${CMS_FRAMEWORK} == "wordpress" ]] 97 | then 98 | 99 | PLUGIN_UPDATES=$(terminus -n wp ${SITE_UUID}.${MULTIDEV} -- plugin list --update=available --format=count) 100 | 101 | echo $PLUGIN_UPDATES 102 | 103 | if [[ "$PLUGIN_UPDATES" == "0" ]] 104 | then 105 | # no WordPress plugin or Drupal module updates found 106 | echo -e "\nNo ${CMS_CONTRIB} updates found on the ${MULTIDEV} multidev for $SITE_NAME..." 107 | else 108 | # update WordPress plugins or Drupal modules 109 | echo -e "\nUpdating ${CMS_CONTRIB}s on the ${MULTIDEV} multidev for $SITE_NAME..." 110 | terminus -n wp $SITE_UUID.$MULTIDEV -- plugin update --all 111 | 112 | # wake the site environment before committing code 113 | echo -e "\nWaking the ${MULTIDEV} multidev..." 114 | terminus env:wake $SITE_UUID.$MULTIDEV 115 | 116 | # committing updated WordPress plugins or Drupal modules 117 | echo -e "\nCommitting ${CMS_CONTRIB} updates on the ${MULTIDEV} multidev for $SITE_NAME..." 118 | terminus env:commit $SITE_UUID.$MULTIDEV --force --message="update ${CMS_CONTRIB}" 119 | UPDATES_APPLIED=true 120 | fi 121 | fi 122 | 123 | # check for Drupal module updates 124 | if [[ ${CMS_FRAMEWORK} == "drupal" ]] 125 | then 126 | 127 | PLUGIN_UPDATES=$(terminus drush ${SITE_UUID}.${MULTIDEV} -- pm-updatestatus --format=list --check-disabled | grep -v ok) 128 | 129 | echo $PLUGIN_UPDATES 130 | 131 | if [[ "$PLUGIN_UPDATES" == "" ]] 132 | then 133 | # no WordPress plugin or Drupal module updates found 134 | echo -e "\nNo ${CMS_CONTRIB} updates found on the ${MULTIDEV} multidev for $SITE_NAME..." 135 | else 136 | # update WordPress plugins or Drupal modules 137 | echo -e "\nUpdating ${CMS_CONTRIB}s on the ${MULTIDEV} multidev for $SITE_NAME..." 138 | terminus -n drush $SITE_UUID.$MULTIDEV -- pm-updatecode --no-core --yes 139 | 140 | # wake the site environment before committing code 141 | echo -e "\nWaking the ${MULTIDEV} multidev..." 142 | terminus env:wake $SITE_UUID.$MULTIDEV 143 | 144 | # committing updated WordPress plugins or Drupal modules 145 | echo -e "\nCommitting ${CMS_CONTRIB} updates on the ${MULTIDEV} multidev for $SITE_NAME..." 146 | terminus env:commit $SITE_UUID.$MULTIDEV --force --message="update ${CMS_CONTRIB}" 147 | UPDATES_APPLIED=true 148 | fi 149 | fi 150 | 151 | # check for WordPress theme updates 152 | if [[ ${CMS_FRAMEWORK} == "wordpress" ]] 153 | then 154 | echo -e "\nChecking for ${CMS_NAME} theme updates on the ${MULTIDEV} multidev for ${SITE_NAME}..." 155 | THEME_UPDATES=$(terminus -n wp ${SITE_UUID}.${MULTIDEV} -- theme list --update=available --format=count) 156 | echo $THEME_UPDATES 157 | 158 | if [[ "$THEME_UPDATES" == "0" ]] 159 | then 160 | # no WordPress theme updates found 161 | echo -e "\nNo WordPress theme updates found on the ${MULTIDEV} multidev for $SITE_NAME..." 162 | else 163 | # update WordPress themes 164 | echo -e "\nUpdating WordPress themes on the ${MULTIDEV} multidev for $SITE_NAME..." 165 | terminus -n wp $SITE_UUID.$MULTIDEV -- theme update --all 166 | 167 | # wake the site environment before committing code 168 | echo -e "\nWaking the ${MULTIDEV} multidev..." 169 | terminus env:wake $SITE_UUID.$MULTIDEV 170 | 171 | # committing updated WordPress themes 172 | echo -e "\nCommitting WordPress theme updates on the ${MULTIDEV} multidev for $SITE_NAME..." 173 | terminus env:commit $SITE_UUID.$MULTIDEV --force --message="update WordPress themes" 174 | UPDATES_APPLIED=true 175 | fi 176 | fi 177 | 178 | if [[ "${UPDATES_APPLIED}" = false ]] 179 | then 180 | # no updates applied 181 | echo -e "\nNo updates to apply for $SITE_NAME..." 182 | #SLACK_MESSAGE="Circle CI update check #${CIRCLE_BUILD_NUM} by ${CIRCLE_PROJECT_USERNAME} on site ${SITE_NAME}. No updates to apply, nothing deployed." 183 | #echo -e "\nSending a message to the ${SLACK_CHANNEL} Slack channel" 184 | #curl -X POST --data "payload={\"channel\": \"${SLACK_CHANNEL}\", \"username\": \"${SLACK_USERNAME}\", \"text\": \"${SLACK_MESSAGE}\"}" $SLACK_HOOK_URL 185 | else 186 | # Run visual regression tests 187 | echo -e "\nUpdates applied, starting the visual regression testing job via API for $SITE_NAME..." 188 | curl --user ${CIRCLE_TOKEN}: \ 189 | --data build_parameters[CIRCLE_JOB]=visual_regression_test \ 190 | --data build_parameters[SITE_NAME]=$SITE_NAME \ 191 | --data build_parameters[SITE_UUID]=$SITE_UUID \ 192 | --data build_parameters[CREATE_BACKUPS]=$CREATE_BACKUPS \ 193 | --data build_parameters[RECREATE_MULTIDEV]=$RECREATE_MULTIDEV \ 194 | --data build_parameters[LIVE_URL]=$LIVE_URL \ 195 | --data revision=$CIRCLE_SHA1 \ 196 | https://circleci.com/api/v1.1/project/github/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/tree/$CIRCLE_BRANCH >/dev/null 197 | fi 198 | -------------------------------------------------------------------------------- /.circleci/behat-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [[ (${CIRCLE_BRANCH} != "master" && -z ${CIRCLE_PULL_REQUEST+x}) || (${CIRCLE_BRANCH} == "master" && -n ${CIRCLE_PULL_REQUEST+x}) ]]; 3 | then 4 | echo -e "CircleCI will only run Behat tests on Pantheon if on the master branch or creating a pull requests.\n" 5 | exit 0; 6 | fi 7 | 8 | # Bail if required environment varaibles are missing 9 | if [ -z "$SITE_NAME" ] || [ -z "$MULTIDEV" ] 10 | then 11 | echo 'No test site specified. Set SITE_NAME and MULTIDEV.' 12 | exit 1 13 | fi 14 | 15 | if [ -z "$CMS_ADMIN_USERNAME" ] || [ -z "$CMS_ADMIN_PASSWORD" ] 16 | then 17 | echo "No CMS credentials specified. Set CMS_ADMIN_USERNAME and CMS_ADMIN_PASSWORD." 18 | exit 1 19 | fi 20 | 21 | echo "::::::::::::::::::::::::::::::::::::::::::::::::" 22 | echo "Behat test site: $SITE_NAME.$MULTIDEV" 23 | echo "::::::::::::::::::::::::::::::::::::::::::::::::" 24 | echo 25 | 26 | # login to Terminus 27 | echo -e "\nLogging into Terminus..." 28 | terminus auth:login --machine-token=${TERMINUS_MACHINE_TOKEN} > /dev/null 2>&1 29 | 30 | # Bail on errors 31 | set +ex 32 | 33 | export WORKING_DIR=$(pwd) 34 | 35 | # Check for tests to run 36 | if [ ! -d $WORKING_DIR/tests/behat/$SITE_NAME ]; then 37 | echo -e "\n Behat test directory $WORKING_DIR/tests/behat/$SITE_NAME not found" 38 | exit 1 39 | fi 40 | 41 | # Create a backup before running Behat tests 42 | if [[ "$RECREATE_MULTIDEV" == "0" ]] 43 | then 44 | echo -e "\n Reacreation of multidev was skipped so making a backup before running Behat tests" 45 | terminus -n backup:create $SITE_NAME.$MULTIDEV 46 | fi 47 | 48 | # Clear site cache 49 | terminus -n env:clear-cache $SITE_NAME.$MULTIDEV 50 | 51 | # Check if the WordPress admin user exists 52 | WORDPRESS_ADMIN_USER_LIST="$(terminus -n wp $SITE_NAME.$MULTIDEV -- user list --field=user_login --role=administrator)" 53 | 54 | while read -r USER; do 55 | if [[ "${USER}" == "$CMS_ADMIN_USERNAME" ]]; then 56 | terminus -n wp $SITE_NAME.$MULTIDEV -- user delete $CMS_ADMIN_USERNAME --yes 57 | fi 58 | done <<< "$WORDPRESS_ADMIN_USER_LIST" 59 | 60 | { 61 | terminus -n wp $SITE_NAME.$MULTIDEV -- user create $CMS_ADMIN_USERNAME no-reply@getpantheon.com --user_pass=$CMS_ADMIN_PASSWORD --role=administrator 62 | } &> /dev/null 63 | 64 | # Set Behat variables from environment variables 65 | export BEHAT_PARAMS='{"extensions":{"Behat\\MinkExtension":{"base_url":"https://'$MULTIDEV'-'$SITE_NAME'.pantheonsite.io"},"PaulGibbs\\WordpressBehatExtension":{"site_url":"https://'$MULTIDEV'-'$SITE_NAME'.pantheonsite.io","users":{"admin":{"username":"'$CMS_ADMIN_USERNAME'","password":"'$CMS_ADMIN_PASSWORD'"}},"wpcli":{"binary":"terminus -n wp '$SITE_NAME'.'$MULTIDEV' --"}}}}' 66 | 67 | # Wake the multidev environment before running tests 68 | terminus -n env:wake $SITE_NAME.$MULTIDEV 69 | 70 | # Ping wp-cli to start ssh with the app server 71 | terminus -n wp $SITE_NAME.$MULTIDEV -- cli version 72 | 73 | # Install Composer dependencies 74 | composer install --no-ansi --no-interaction --optimize-autoloader --no-progress 75 | 76 | # Run the Behat tests 77 | cd $WORKING_DIR/tests/behat/$SITE_NAME 78 | 79 | # Stash the Behat results 80 | echo -e "\n Running Behat..." 81 | BEHAT_RESULTS=$($WORKING_DIR/vendor/bin/behat --config=$WORKING_DIR/tests/behat/behat-pantheon.yml --strict "$@" || echo 'true' ) 82 | 83 | # Output 84 | echo "$BEHAT_RESULTS" 85 | 86 | # Change back into working directory 87 | cd $WORKING_DIR 88 | 89 | # Restore the backup made before testing 90 | if [[ "$RECREATE_MULTIDEV" == "0" ]] 91 | then 92 | echo -e "\n Reacreation of multidev was skipped so restoring the backup made before running Behat tests" 93 | terminus -n backup:restore $SITE_NAME.$MULTIDEV --element=database --yes 94 | fi 95 | 96 | if [[ ${BEHAT_RESULTS} == *"Failed scenarios"* ]] 97 | then 98 | # Behat failed 99 | SLACK_MESSAGE="Behat tests failed for $SITE_NAME! Halting deployment. Please check the logs for more details." 100 | SLACK_ATTACHEMENTS="\"attachments\": [{\"fallback\": \"View the Behat log in CircleCI\",\"color\": \"${RED_HEX}\",\"actions\": [{\"type\": \"button\",\"text\": \"Behat test logs\",\"url\":\"${CIRCLE_BUILD_URL}\"}]}]" 101 | else 102 | SLACK_MESSAGE="Behat tests passed for $SITE_NAME! Proceeding with deployment." 103 | SLACK_ATTACHEMENTS="\"attachments\": [{\"fallback\": \"View the Behat log in CircleCI\",\"color\": \"${GREEN_HEX}\",\"actions\": [{\"type\": \"button\",\"text\": \"Behat test logs\",\"url\":\"${CIRCLE_BUILD_URL}\"}]}]" 104 | fi 105 | 106 | echo -e "\n$SLACK_MESSAGE" 107 | 108 | # Post the report back to Slack 109 | echo -e "\nSending a message to the ${SLACK_CHANNEL} Slack channel" 110 | curl -X POST --data "payload={\"channel\": \"${SLACK_CHANNEL}\",${SLACK_ATTACHEMENTS}, \"username\": \"${SLACK_USERNAME}\", \"text\": \"${SLACK_MESSAGE}\"}" $SLACK_HOOK_URL 111 | 112 | if [[ ${BEHAT_RESULTS} == *"Failed scenarios"* ]] 113 | then 114 | # Behat failed 115 | exit 1 116 | fi 117 | 118 | 119 | # Deploy updates 120 | echo -e "\nStarting the deploy job via API for $SITE_NAME..." 121 | curl --user ${CIRCLE_TOKEN}: \ 122 | --data build_parameters[CIRCLE_JOB]=deploy_updates \ 123 | --data build_parameters[SITE_NAME]=$SITE_NAME \ 124 | --data build_parameters[VISUAL_REGRESSION_HTML_REPORT_URL]=$VISUAL_REGRESSION_HTML_REPORT_URL \ 125 | --data build_parameters[LIGHTHOUSE_SCORE]=$LIGHTHOUSE_SCORE \ 126 | --data build_parameters[LIGHTHOUSE_HTML_REPORT_URL]=$LIGHTHOUSE_HTML_REPORT_URL \ 127 | --data build_parameters[LIGHTHOUSE_PRODUCTION_SCORE]=$LIGHTHOUSE_PRODUCTION_SCORE \ 128 | --data build_parameters[LIGHTHOUSE_PRODUCTION_HTML_REPORT_URL]=$LIGHTHOUSE_PRODUCTION_HTML_REPORT_URL \ 129 | --data build_parameters[LIGHTHOUSE_ACCEPTABLE_THRESHOLD]=$LIGHTHOUSE_ACCEPTABLE_THRESHOLD \ 130 | --data build_parameters[BEHAT_LOG_URL]=$CIRCLE_BUILD_URL \ 131 | --data build_parameters[SITE_UUID]=$SITE_UUID \ 132 | --data build_parameters[CREATE_BACKUPS]=$CREATE_BACKUPS \ 133 | --data build_parameters[RECREATE_MULTIDEV]=$RECREATE_MULTIDEV \ 134 | --data build_parameters[LIVE_URL]=$LIVE_URL \ 135 | --data revision=$CIRCLE_SHA1 \ 136 | https://circleci.com/api/v1.1/project/github/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/tree/$CIRCLE_BRANCH >/dev/null 137 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs 2 | defaults: &defaults 3 | docker: 4 | - image: ataylorme/docker-php-advanced-wordpress-on-pantheon:latest 5 | working_directory: ~/pantheon-auto-updates 6 | environment: 7 | #========================================================================= 8 | # In addition to the environment variables defined in this file, also 9 | # add the following variables in the Circle CI UI. 10 | # 11 | # See: https://circleci.com/docs/2.0/environment-variables/ 12 | # 13 | # TERMINUS_SITE: Name of the Pantheon site to run tests on, e.g. my_site 14 | # TERMINUS_TOKEN: The Pantheon machine token 15 | # GITHUB_TOKEN: The GitHub personal access token 16 | # GIT_EMAIL: The email address to use when making commits 17 | # 18 | # TEST_SITE_NAME: The name of the test site to provide when installing. 19 | # ADMIN_PASSWORD: The admin password to use when installing. 20 | # ADMIN_EMAIL: The email address to give the admin when installing. 21 | #========================================================================= 22 | TZ: "/usr/share/zoneinfo/America/Los_Angeles" 23 | 24 | # The variables below usually do not need to be modified. 25 | 26 | #====================================================================================================================================== 27 | # Circle CI 2.0 does not yet expand environment variables so they have to be manually EXPORTed 28 | # Once environment variables can be expanded the variables below can be uncommented and the EXPORTs in set-up-globals.sh can be removed 29 | # See: https://discuss.circleci.com/t/unclear-how-to-work-with-user-variables-circleci-provided-env-variables/12810/11 30 | # See: https://discuss.circleci.com/t/environment-variable-expansion-in-working-directory/11322 31 | # See: https://discuss.circleci.com/t/circle-2-0-global-environment-variables/8681 32 | #====================================================================================================================================== 33 | # See set-up-globals.sh for more environment variables 34 | 35 | TERM: dumb 36 | 37 | version: 2 38 | jobs: 39 | build: 40 | <<: *defaults 41 | steps: 42 | - checkout 43 | 44 | - run: 45 | name: declare environment variables 46 | command: ./.circleci/set-up-globals.sh 47 | 48 | - run: 49 | name: fire off updates on multiple sites 50 | command: ./.circleci/sites-to-update.sh 51 | 52 | check_for_updates: 53 | <<: *defaults 54 | steps: 55 | - checkout 56 | 57 | - run: 58 | name: declare environment variables 59 | command: ./.circleci/set-up-globals.sh 60 | 61 | - run: 62 | name: declare framework 63 | command: ./.circleci/set-framework.sh 64 | 65 | - run: 66 | name: check for updates 67 | command: ./.circleci/auto-update.sh 68 | no_output_timeout: 30m 69 | 70 | visual_regression_test: 71 | <<: *defaults 72 | docker: 73 | - image: ataylorme/docker-node-advanced-wordpress-on-pantheon:backstop-js 74 | steps: 75 | - checkout 76 | 77 | - run: 78 | name: declare environment variables 79 | command: ./.circleci/set-up-globals.sh 80 | 81 | - run: 82 | name: run visual regression tests 83 | command: ./.circleci/visual-regression-test.sh 84 | no_output_timeout: 30m 85 | 86 | - store_artifacts: 87 | path: /tmp/artifacts 88 | destination: artifacts 89 | 90 | lighthouse_performance_test: 91 | <<: *defaults 92 | docker: 93 | - image: ataylorme/docker-node-advanced-wordpress-on-pantheon:lighthouse 94 | steps: 95 | - checkout 96 | 97 | - run: 98 | name: declare environment variables 99 | command: ./.circleci/set-up-globals.sh 100 | 101 | - run: 102 | name: run lighthouse tests 103 | command: ./.circleci/lighthouse-performance-test.sh 104 | no_output_timeout: 30m 105 | 106 | - store_artifacts: 107 | path: /tmp/artifacts 108 | destination: artifacts 109 | 110 | behat_test: 111 | <<: *defaults 112 | steps: 113 | - checkout 114 | 115 | - restore_cache: 116 | keys: 117 | - composer-cache 118 | 119 | - run: 120 | name: declare environment variables 121 | command: ./.circleci/set-up-globals.sh 122 | 123 | - run: 124 | name: declare framework 125 | command: ./.circleci/set-framework.sh 126 | 127 | - run: 128 | name: run behat tests 129 | command: ./.circleci/behat-test.sh 130 | no_output_timeout: 30m 131 | 132 | - save_cache: 133 | key: composer-cache 134 | paths: 135 | - $HOME/.composer/cache 136 | 137 | deploy_updates: 138 | <<: *defaults 139 | steps: 140 | - checkout 141 | 142 | - run: 143 | name: declare environment variables 144 | command: ./.circleci/set-up-globals.sh 145 | 146 | - run: 147 | name: declare framework 148 | command: ./.circleci/set-framework.sh 149 | 150 | - run: 151 | name: deploy updates 152 | command: ./.circleci/deploy-updates.sh 153 | no_output_timeout: 30m 154 | 155 | workflows: 156 | version: 2 157 | commit-workflow: 158 | jobs: 159 | - build 160 | # Remove the commented code below to run the build job on a daily cron 161 | # update_and_test: 162 | # triggers: 163 | # - schedule: 164 | # cron: "5 4 * * *" 165 | # filters: 166 | # branches: 167 | # only: 168 | # - master 169 | # jobs: 170 | # - build 171 | -------------------------------------------------------------------------------- /.circleci/deploy-updates.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo -e "\Deploying updates for $SITE_NAME with UUID $SITE_UUID..." 3 | 4 | # login to Terminus 5 | echo -e "\nLogging into Terminus..." 6 | terminus auth:login --machine-token=${TERMINUS_MACHINE_TOKEN} > /dev/null 2>&1 7 | 8 | # Bail on errors 9 | set +ex 10 | 11 | # enable git mode on dev 12 | echo -e "\nEnabling git mode on the dev environment for $SITE_NAME..." 13 | terminus connection:set $SITE_UUID.dev git 14 | 15 | # merge the multidev back to dev 16 | echo -e "\nMerging the ${MULTIDEV} multidev back into the dev environment (master) for $SITE_NAME..." 17 | terminus multidev:merge-to-dev $SITE_UUID.$MULTIDEV 18 | 19 | # update database on dev 20 | echo -e "\nUpdating the ${CMS_NAME} database on the dev environment for $SITE_NAME..." 21 | if [[ ${CMS_FRAMEWORK} == "wordpress" ]] 22 | then 23 | terminus -n wp $SITE_UUID.dev -- core update-db 24 | fi 25 | 26 | if [[ ${CMS_FRAMEWORK} == "drupal" ]] 27 | then 28 | terminus -n drush $SITE_UUID.dev -- updatedb 29 | fi 30 | 31 | # deploy to test 32 | echo -e "\nDeploying the updates from dev to test for $SITE_NAME..." 33 | terminus env:deploy $SITE_UUID.test --sync-content --cc --note="Auto deploy of ${CMS_NAME} updates" 34 | 35 | # update database on test 36 | echo -e "\nUpdating the ${CMS_NAME} database on the test environment..." 37 | if [[ ${CMS_FRAMEWORK} == "wordpress" ]] 38 | then 39 | terminus -n wp $SITE_UUID.test -- core update-db 40 | fi 41 | 42 | if [[ ${CMS_FRAMEWORK} == "drupal" ]] 43 | then 44 | terminus -n drush $SITE_UUID.test -- updatedb 45 | fi 46 | 47 | # backup the live site 48 | if [[ "$CREATE_BACKUPS" == "0" ]] 49 | then 50 | echo -e "\nSkipping backup of the live environment for $SITE_NAME..." 51 | else 52 | echo -e "\nBacking up the live environment for $SITE_NAME..." 53 | terminus backup:create $SITE_UUID.live --element=all --keep-for=30 54 | fi 55 | 56 | # deploy to live 57 | echo -e "\nDeploying the updates from test to live for $SITE_NAME..." 58 | terminus env:deploy $SITE_UUID.live --cc --note="Auto deploy of ${CMS_NAME} updates" 59 | 60 | # update database on live 61 | echo -e "\nUpdating the {$CMS_NAME} database on the live environment for $SITE_NAME..." 62 | if [[ ${CMS_FRAMEWORK} == "wordpress" ]] 63 | then 64 | terminus -n wp $SITE_UUID.live -- core update-db 65 | fi 66 | 67 | if [[ ${CMS_FRAMEWORK} == "drupal" ]] 68 | then 69 | terminus -n drush $SITE_UUID.live -- updatedb 70 | fi 71 | 72 | echo -e "\nTests passed! ${CMS_NAME} updates deployed to live for $SITE_NAME..." 73 | SLACK_MESSAGE="Circle CI update check #${CIRCLE_BUILD_NUM} by ${CIRCLE_PROJECT_USERNAME} on ${SITE_NAME}. Automated tests passed! ${CMS_NAME} updates deployed to production. View the reports below:" 74 | 75 | SLACK_MESSAGE="Automated tests passed for $SITE_NAME! Updates deployed to production. View the test reports below:" 76 | 77 | if [ -z $BEHAT_LOG_URL ]; 78 | then 79 | SLACK_ATTACHEMENTS="\"attachments\": [{\"fallback\": \"View the test results in CircleCI artifacts\",\"color\": \"${GREEN_HEX}\",\"actions\": [{\"type\": \"button\",\"text\": \"Lighthouse Report for ${MULTIDEV} (${LIGHTHOUSE_SCORE})\",\"url\":\"${LIGHTHOUSE_HTML_REPORT_URL}\"},{\"type\": \"button\",\"text\": \"Lighthouse Report for Live (${LIGHTHOUSE_PRODUCTION_SCORE})\",\"url\":\"${LIGHTHOUSE_PRODUCTION_HTML_REPORT_URL}\"},{\"type\": \"button\",\"text\": \"BackstopJS Visual Regression Report\",\"url\":\"${VISUAL_REGRESSION_HTML_REPORT_URL}\"},{\"type\": \"button\",\"text\": \"View Site\",\"url\":\"${LIVE_URL}\"},{\"type\": \"button\",\"text\": \"Pantheon dashboard\",\"url\":\"https://dashboard.pantheon.io/sites/${SITE_UUID}#live\"}]}]" 80 | else 81 | SLACK_ATTACHEMENTS="\"attachments\": [{\"fallback\": \"View the test results in CircleCI artifacts\",\"color\": \"${GREEN_HEX}\",\"actions\": [{\"type\": \"button\",\"text\": \"Lighthouse Report for ${MULTIDEV} (${LIGHTHOUSE_SCORE})\",\"url\":\"${LIGHTHOUSE_HTML_REPORT_URL}\"},{\"type\": \"button\",\"text\": \"Lighthouse Report for Live (${LIGHTHOUSE_PRODUCTION_SCORE})\",\"url\":\"${LIGHTHOUSE_PRODUCTION_HTML_REPORT_URL}\"},{\"type\": \"button\",\"text\": \"BackstopJS Visual Regression Report\",\"url\":\"${VISUAL_REGRESSION_HTML_REPORT_URL}\"},{\"type\": \"button\",\"text\": \"Behat test log\",\"url\":\"${BEHAT_LOG_URL}\"},{\"type\": \"button\",\"text\": \"View Site\",\"url\":\"${LIVE_URL}\"},{\"type\": \"button\",\"text\": \"Pantheon dashboard\",\"url\":\"https://dashboard.pantheon.io/sites/${SITE_UUID}#live\"}]}]" 82 | fi 83 | 84 | # Post the report back to Slack 85 | echo -e "\nSending a message to the ${SLACK_CHANNEL} Slack channel" 86 | curl -X POST --data "payload={\"channel\": \"${SLACK_CHANNEL}\",${SLACK_ATTACHEMENTS}, \"username\": \"${SLACK_USERNAME}\", \"text\": \"${SLACK_MESSAGE}\"}" $SLACK_HOOK_URL 87 | -------------------------------------------------------------------------------- /.circleci/lighthouse-performance-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Bail on errors 4 | set +ex 5 | 6 | # Variables 7 | BUILD_DIR=$(pwd) 8 | GITHUB_API_URL="https://api.github.com/repos/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME" 9 | 10 | # Check if we are NOT on the master branch and this is a PR 11 | if [[ ${CIRCLE_BRANCH} != "master" && -z ${CIRCLE_PULL_REQUEST+x} ]]; 12 | then 13 | echo -e "\Lighthouse performance test will only run if not on the master branch when making a pull request" 14 | exit 0 15 | fi 16 | 17 | # Make artifacts directory 18 | CIRCLE_ARTIFACTS='artifacts' 19 | CIRCLE_ARTIFACTS_DIR='/tmp/artifacts' 20 | mkdir -p $CIRCLE_ARTIFACTS_DIR 21 | 22 | # Set Lighthouse results directory, branch and url 23 | LIGHTHOUSE_BRANCH=$MULTIDEV 24 | LIGHTHOUSE_URL=$MULTIDEV_URL 25 | LIGHTHOUSE_RESULTS_DIR="lighthouse_results/$LIGHTHOUSE_BRANCH" 26 | LIGHTHOUSE_REPORT_NAME="$LIGHTHOUSE_RESULTS_DIR/lighthouse.json" 27 | LIGHTHOUSE_JSON_REPORT="$LIGHTHOUSE_RESULTS_DIR/lighthouse.report.json" 28 | LIGHTHOUSE_HTML_REPORT="$LIGHTHOUSE_RESULTS_DIR/lighthouse.report.html" 29 | LIGHTHOUSE_RESULTS_JSON="$LIGHTHOUSE_RESULTS_DIR/lighthouse.results.json" 30 | 31 | # Delete the Lighthouse results directory so we don't keep old results around 32 | if [ -d "$LIGHTHOUSE_RESULTS_DIR" ]; then 33 | rm -rf $LIGHTHOUSE_RESULTS_DIR 34 | fi 35 | 36 | # Create the Lighthouse results directory if it doesn't exist or has been deleted 37 | mkdir -p $LIGHTHOUSE_RESULTS_DIR 38 | 39 | # Create the Lighthouse results directory for master if needed 40 | if [ ! -d "lighthouse_results/master" ]; then 41 | mkdir -p "lighthouse_results/master" 42 | fi 43 | 44 | # Stash Circle Artifacts URL 45 | CIRCLE_ARTIFACTS_URL="$CIRCLE_BUILD_URL/artifacts/$CIRCLE_NODE_INDEX/$CIRCLE_ARTIFACTS" 46 | 47 | # Ping the Pantheon environment to wake it from sleep and prime the cache 48 | echo -e "\nPinging the ${LIGHTHOUSE_BRANCH} environment to wake it from sleep..." 49 | curl -s -I "$LIGHTHOUSE_URL" >/dev/null 50 | 51 | # Run the Lighthouse test 52 | lighthouse --perf --save-artifacts --output json --output html --output-path ${LIGHTHOUSE_REPORT_NAME} --chrome-flags="--headless --disable-gpu --no-sandbox" ${LIGHTHOUSE_URL} 53 | 54 | # Check for HTML report file 55 | if [ ! -f $LIGHTHOUSE_HTML_REPORT ]; then 56 | echo -e "\nLighthouse HTML report file $LIGHTHOUSE_HTML_REPORT not found!" 57 | exit 1 58 | fi 59 | 60 | # Check for JSON report file 61 | if [ ! -f $LIGHTHOUSE_JSON_REPORT ]; then 62 | echo -e "\nLighthouse JSON report file $LIGHTHOUSE_JSON_REPORT not found!" 63 | exit 1 64 | fi 65 | 66 | # Create tailored results JSON file 67 | cat $LIGHTHOUSE_JSON_REPORT | jq '. | { "total-score": .score, "speed-index": .audits["speed-index-metric"]["score"], "first-meaningful-paint": .audits["first-meaningful-paint"]["score"], "estimated-input-latency": .audits["estimated-input-latency"]["score"], "time-to-first-byte": .audits["time-to-first-byte"]["rawValue"], "first-interactive": .audits["first-interactive"]["score"], "consistently-interactive": .audits["consistently-interactive"]["score"], "critical-request-chains": .audits["critical-request-chains"]["displayValue"], "redirects": .audits["redirects"]["score"], "bootup-time": .audits["bootup-time"]["rawValue"], "uses-long-cache-ttl": .audits["uses-long-cache-ttl"]["score"], "total-byte-weight": .audits["total-byte-weight"]["score"], "offscreen-images": .audits["offscreen-images"]["score"], "uses-webp-images": .audits["uses-webp-images"]["score"], "uses-optimized-images": .audits["uses-optimized-images"]["score"], "uses-request-compression": .audits["uses-request-compression"]["score"], "uses-responsive-images": .audits["uses-responsive-images"]["score"], "dom-size": .audits["dom-size"]["score"], "script-blocking-first-paint": .audits["script-blocking-first-paint"]["score"] }' > $LIGHTHOUSE_RESULTS_JSON 68 | 69 | LIGHTHOUSE_SCORE=$(cat $LIGHTHOUSE_RESULTS_JSON | jq '.["total-score"] | floor | tonumber') 70 | LIGHTHOUSE_HTML_REPORT_URL="$CIRCLE_ARTIFACTS_URL/$LIGHTHOUSE_HTML_REPORT" 71 | 72 | # Rsync files to CIRCLE_ARTIFACTS_DIR 73 | echo -e "\nRsyncing lighthouse_results files to $CIRCLE_ARTIFACTS_DIR..." 74 | rsync -rlvz lighthouse_results $CIRCLE_ARTIFACTS_DIR 75 | 76 | LIGHTHOUSE_PRODUCTION_RESULTS_DIR="lighthouse_results/master" 77 | LIGHTHOUSE_PRODUCTION_REPORT_NAME="$LIGHTHOUSE_PRODUCTION_RESULTS_DIR/lighthouse.json" 78 | LIGHTHOUSE_PRODUCTION_JSON_REPORT="$LIGHTHOUSE_PRODUCTION_RESULTS_DIR/lighthouse.report.json" 79 | LIGHTHOUSE_PRODUCTION_HTML_REPORT="$LIGHTHOUSE_PRODUCTION_RESULTS_DIR/lighthouse.report.html" 80 | LIGHTHOUSE_PRODUCTION_RESULTS_JSON="$LIGHTHOUSE_PRODUCTION_RESULTS_DIR/lighthouse.results.json" 81 | 82 | # Ping the live environment to wake it from sleep and prime the cache 83 | echo -e "\nPinging the live environment to wake it from sleep..." 84 | curl -s -I "$LIVE_URL" >/dev/null 85 | 86 | # Run Lighthouse on the live environment 87 | echo -e "\nRunning Lighthouse on the live environment" 88 | lighthouse --perf --save-artifacts --output json --output html --output-path "$LIGHTHOUSE_PRODUCTION_REPORT_NAME" --chrome-flags="--headless --disable-gpu --no-sandbox" ${LIVE_URL} 89 | 90 | # Create tailored results JSON file 91 | cat $LIGHTHOUSE_PRODUCTION_JSON_REPORT | jq '. | { "total-score": .score, "speed-index": .audits["speed-index-metric"]["score"], "first-meaningful-paint": .audits["first-meaningful-paint"]["score"], "estimated-input-latency": .audits["estimated-input-latency"]["score"], "time-to-first-byte": .audits["time-to-first-byte"]["rawValue"], "first-interactive": .audits["first-interactive"]["score"], "consistently-interactive": .audits["consistently-interactive"]["score"], "critical-request-chains": .audits["critical-request-chains"]["displayValue"], "redirects": .audits["redirects"]["score"], "bootup-time": .audits["bootup-time"]["rawValue"], "uses-long-cache-ttl": .audits["uses-long-cache-ttl"]["score"], "total-byte-weight": .audits["total-byte-weight"]["score"], "offscreen-images": .audits["offscreen-images"]["score"], "uses-webp-images": .audits["uses-webp-images"]["score"], "uses-optimized-images": .audits["uses-optimized-images"]["score"], "uses-request-compression": .audits["uses-request-compression"]["score"], "uses-responsive-images": .audits["uses-responsive-images"]["score"], "dom-size": .audits["dom-size"]["score"], "script-blocking-first-paint": .audits["script-blocking-first-paint"]["score"] }' > $LIGHTHOUSE_PRODUCTION_RESULTS_JSON 92 | 93 | LIGHTHOUSE_PRODUCTION_SCORE=$(cat $LIGHTHOUSE_PRODUCTION_RESULTS_JSON | jq '.["total-score"] | floor | tonumber') 94 | 95 | # Rsync files to CIRCLE_ARTIFACTS_DIR again now that we have master results 96 | echo -e "\nRsyncing lighthouse_results files to $CIRCLE_ARTIFACTS_DIR..." 97 | rsync -rlvz lighthouse_results $CIRCLE_ARTIFACTS_DIR 98 | 99 | echo -e "\nMaster score of $LIGHTHOUSE_PRODUCTION_SCORE recorded" 100 | 101 | LIGHTHOUSE_PRODUCTION_HTML_REPORT_URL="$CIRCLE_ARTIFACTS_URL/$LIGHTHOUSE_PRODUCTION_HTML_REPORT" 102 | 103 | # Level of tolerance for score decline 104 | LIGHTHOUSE_ACCEPTABLE_THRESHOLD=5 105 | LIGHTHOUSE_ACCEPTABLE_SCORE=$((LIGHTHOUSE_PRODUCTION_SCORE-LIGHTHOUSE_ACCEPTABLE_THRESHOLD)) 106 | 107 | if [ $LIGHTHOUSE_SCORE -lt $LIGHTHOUSE_ACCEPTABLE_SCORE ]; then 108 | # Lighthouse test failed! The score is less than the acceptable score 109 | echo -e "\nAuto update Lighthouse test failed for $SITE_NAME! The score of $LIGHTHOUSE_SCORE is less than the acceptable score of $LIGHTHOUSE_ACCEPTABLE_SCORE. Deployment halted, please manually review the $MULTIDEV environment." 110 | SLACK_MESSAGE="Auto update Lighthouse test failed for $SITE_NAME! The score of \`$LIGHTHOUSE_SCORE\` is less than the acceptable score of \`$LIGHTHOUSE_ACCEPTABLE_SCORE\`. **Deployment halted, please manually review <$MULTIDEV_URL|the $MULTIDEV environment>.** View the reports below:" 111 | 112 | SLACK_ATTACHEMENTS="\"attachments\": [{\"fallback\": \"View the Lighthouse reports in CircleCI artifacts\",\"color\": \"${RED_HEX}\",\"actions\": [{\"type\": \"button\",\"text\": \"${MULTIDEV} (${LIGHTHOUSE_SCORE})\",\"url\":\"${LIGHTHOUSE_HTML_REPORT_URL}\"},{\"type\": \"button\",\"text\": \"Live (${LIGHTHOUSE_PRODUCTION_SCORE})\",\"url\":\"${LIGHTHOUSE_PRODUCTION_HTML_REPORT_URL}\"}]}]" 113 | 114 | # Post the report back to Slack 115 | echo -e "\nSending a message to the ${SLACK_CHANNEL} Slack channel" 116 | curl -X POST --data "payload={\"channel\": \"${SLACK_CHANNEL}\",${SLACK_ATTACHEMENTS}, \"username\": \"${SLACK_USERNAME}\", \"text\": \"${SLACK_MESSAGE}\"}" $SLACK_HOOK_URL 117 | 118 | exit 1 119 | else 120 | # Lighthouse test passed! The score isn't less than the acceptable score 121 | echo -e "\nAuto update Lighthouse test passed for $SITE_NAME! The score of $LIGHTHOUSE_SCORE isn't less than the acceptable score of $LIGHTHOUSE_ACCEPTABLE_SCORE ($LIGHTHOUSE_ACCEPTABLE_THRESHOLD less than the score of $LIGHTHOUSE_PRODUCTION_SCORE on $LIVE_URL)" 122 | 123 | if [[ -d tests/behat/$SITE_NAME && $CMS_FRAMEWORK == "wordpress" ]] 124 | then 125 | # Run Behat tests 126 | echo -e "\nStarting the behat test job via API for $SITE_NAME..." 127 | curl --user ${CIRCLE_TOKEN}: \ 128 | --data build_parameters[CIRCLE_JOB]=behat_test \ 129 | --data build_parameters[SITE_NAME]=$SITE_NAME \ 130 | --data build_parameters[VISUAL_REGRESSION_HTML_REPORT_URL]=$VISUAL_REGRESSION_HTML_REPORT_URL \ 131 | --data build_parameters[LIGHTHOUSE_SCORE]=$LIGHTHOUSE_SCORE \ 132 | --data build_parameters[LIGHTHOUSE_HTML_REPORT_URL]=$LIGHTHOUSE_HTML_REPORT_URL \ 133 | --data build_parameters[LIGHTHOUSE_PRODUCTION_SCORE]=$LIGHTHOUSE_PRODUCTION_SCORE \ 134 | --data build_parameters[LIGHTHOUSE_PRODUCTION_HTML_REPORT_URL]=$LIGHTHOUSE_PRODUCTION_HTML_REPORT_URL \ 135 | --data build_parameters[LIGHTHOUSE_ACCEPTABLE_THRESHOLD]=$LIGHTHOUSE_ACCEPTABLE_THRESHOLD \ 136 | --data build_parameters[SITE_UUID]=$SITE_UUID \ 137 | --data build_parameters[CREATE_BACKUPS]=$CREATE_BACKUPS \ 138 | --data build_parameters[RECREATE_MULTIDEV]=$RECREATE_MULTIDEV \ 139 | --data build_parameters[LIVE_URL]=$LIVE_URL \ 140 | --data revision=$CIRCLE_SHA1 \ 141 | https://circleci.com/api/v1.1/project/github/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/tree/$CIRCLE_BRANCH >/dev/null 142 | else 143 | # Deploy updates 144 | echo -e "\nStarting the deploy job via API for $SITE_NAME..." 145 | curl --user ${CIRCLE_TOKEN}: \ 146 | --data build_parameters[CIRCLE_JOB]=deploy_updates \ 147 | --data build_parameters[SITE_NAME]=$SITE_NAME \ 148 | --data build_parameters[VISUAL_REGRESSION_HTML_REPORT_URL]=$VISUAL_REGRESSION_HTML_REPORT_URL \ 149 | --data build_parameters[LIGHTHOUSE_SCORE]=$LIGHTHOUSE_SCORE \ 150 | --data build_parameters[LIGHTHOUSE_HTML_REPORT_URL]=$LIGHTHOUSE_HTML_REPORT_URL \ 151 | --data build_parameters[LIGHTHOUSE_PRODUCTION_SCORE]=$LIGHTHOUSE_PRODUCTION_SCORE \ 152 | --data build_parameters[LIGHTHOUSE_PRODUCTION_HTML_REPORT_URL]=$LIGHTHOUSE_PRODUCTION_HTML_REPORT_URL \ 153 | --data build_parameters[LIGHTHOUSE_ACCEPTABLE_THRESHOLD]=$LIGHTHOUSE_ACCEPTABLE_THRESHOLD \ 154 | --data build_parameters[SITE_UUID]=$SITE_UUID \ 155 | --data build_parameters[CREATE_BACKUPS]=$CREATE_BACKUPS \ 156 | --data build_parameters[RECREATE_MULTIDEV]=$RECREATE_MULTIDEV \ 157 | --data build_parameters[LIVE_URL]=$LIVE_URL \ 158 | --data revision=$CIRCLE_SHA1 \ 159 | https://circleci.com/api/v1.1/project/github/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/tree/$CIRCLE_BRANCH >/dev/null 160 | fi 161 | fi 162 | -------------------------------------------------------------------------------- /.circleci/set-framework.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # login to Terminus 4 | echo -e "\nLogging into Terminus..." 5 | terminus auth:login --machine-token=${TERMINUS_MACHINE_TOKEN} > /dev/null 2>&1 6 | 7 | PANTHEON_FRAMEWORK="$(terminus site:info ${SITE_NAME} --field=framework)" 8 | 9 | if [[ ${PANTHEON_FRAMEWORK} == "wordpress" ]] 10 | then 11 | echo 'export CMS_FRAMEWORK="wordpress"' >> $BASH_ENV 12 | echo 'export CMS_NAME="WordPress"' >> $BASH_ENV 13 | echo 'export CMS_CONTRIB="WordPress plugins"' >> $BASH_ENV 14 | fi 15 | 16 | if [[ ${PANTHEON_FRAMEWORK} == "drupal" || ${PANTHEON_FRAMEWORK} == "drupal8" ]] 17 | then 18 | echo 'export CMS_FRAMEWORK="drupal"' >> $BASH_ENV 19 | echo 'export CMS_NAME="Drupal"' >> $BASH_ENV 20 | echo 'export CMS_CONTRIB="Drupal modules"' >> $BASH_ENV 21 | fi 22 | 23 | source $BASH_ENV 24 | -------------------------------------------------------------------------------- /.circleci/set-up-globals.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | #========================================================================= 6 | # Commands below this line would not be transferable to a docker container 7 | #========================================================================= 8 | 9 | #===================================================================================================================== 10 | # Start EXPORTing needed environment variables 11 | # Circle CI 2.0 does not yet expand environment variables so they have to be manually EXPORTed 12 | # Once environment variables can be expanded this section can be removed 13 | # See: https://discuss.circleci.com/t/unclear-how-to-work-with-user-variables-circleci-provided-env-variables/12810/11 14 | # See: https://discuss.circleci.com/t/environment-variable-expansion-in-working-directory/11322 15 | # See: https://discuss.circleci.com/t/circle-2-0-global-environment-variables/8681 16 | #===================================================================================================================== 17 | 18 | # Check to see if the multidev is already defined in the environment variable. If not, define it now. 19 | if [ -z $MULTIDEV ] 20 | then 21 | echo 'export MULTIDEV=auto-update' >> $BASH_ENV 22 | MULTIDEV=auto-update 23 | fi 24 | 25 | echo 'export GREEN_HEX="008000"' >> $BASH_ENV 26 | echo 'export RED_HEX="FF0000"' >> $BASH_ENV 27 | RANDOM_PASS=$(openssl rand -hex 8) 28 | echo "export CMS_ADMIN_USERNAME='pantheon'" >> $BASH_ENV 29 | echo "export CMS_ADMIN_PASSWORD='$RANDOM_PASS'" >> $BASH_ENV 30 | 31 | # Stash site URLs 32 | echo "export MULTIDEV_URL='https://$MULTIDEV-$SITE_NAME.pantheonsite.io/'" >> $BASH_ENV 33 | if [ -z "$LIVE_URL" ] || [ "$LIVE_URL" == "0" ] 34 | then 35 | echo "export LIVE_URL='https://live-$SITE_NAME.pantheonsite.io/'" >> $BASH_ENV 36 | else 37 | echo "using existing LIVE_URL $LIVE_URL for $SITE_NAME" 38 | fi 39 | 40 | echo 'export PATH=$PATH:$HOME/bin:$HOME/terminus/bin' >> $BASH_ENV 41 | 42 | source $BASH_ENV 43 | 44 | #=========================================== 45 | # End EXPORTing needed environment variables 46 | #=========================================== 47 | 48 | # Bail on errors 49 | set +ex 50 | 51 | # Disable host checking 52 | if [ ! -d $HOME/.ssh ] 53 | then 54 | mkdir -p $HOME/.ssh 55 | fi 56 | touch $HOME/.ssh/config 57 | echo "StrictHostKeyChecking no" >> "$HOME/.ssh/config" -------------------------------------------------------------------------------- /.circleci/sites-to-update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Read which sites to update from sites-to-update.json 4 | while IFS= read -r SITE_UUID && 5 | IFS= read -r SITE_NAME && 6 | IFS= read -r CREATE_BACKUPS && 7 | IFS= read -r RECREATE_MULTIDEV && 8 | IFS= read -r LIVE_URL; do 9 | 10 | # Start check_for_updates job via API 11 | echo -e "\nStarting the check for updates job via API for $SITE_NAME..." 12 | 13 | if [[ "$CREATE_BACKUPS" == "0" ]] 14 | then 15 | echo -e "Skipping backups for $SITE_NAME..." 16 | fi 17 | 18 | curl --user ${CIRCLE_TOKEN}: \ 19 | --data build_parameters[CIRCLE_JOB]=check_for_updates \ 20 | --data build_parameters[SITE_NAME]=$SITE_NAME \ 21 | --data build_parameters[SITE_UUID]=$SITE_UUID \ 22 | --data build_parameters[CREATE_BACKUPS]=$CREATE_BACKUPS \ 23 | --data build_parameters[RECREATE_MULTIDEV]=$RECREATE_MULTIDEV \ 24 | --data build_parameters[LIVE_URL]=$LIVE_URL \ 25 | --data revision=$CIRCLE_SHA1 \ 26 | https://circleci.com/api/v1.1/project/github/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/tree/$CIRCLE_BRANCH >/dev/null 27 | 28 | done < <(jq -r '.[] | (.SITE_UUID, .SITE_NAME, .CREATE_BACKUPS, .RECREATE_MULTIDEV, .LIVE_URL)' < "$(dirname "$pwd")/sites-to-auto-update.json") -------------------------------------------------------------------------------- /.circleci/visual-regression-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Bail on errors 4 | set +ex 5 | 6 | echo -e "\nRunning visual regression tests for $SITE_NAME with UUID $SITE_UUID..." 7 | 8 | # Variables 9 | BUILD_DIR=$(pwd) 10 | GITHUB_API_URL="https://api.github.com/repos/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME" 11 | 12 | # Make artifacts directories 13 | CIRCLE_ARTIFACTS='artifacts' 14 | CIRCLE_ARTIFACTS_DIR='/tmp/artifacts' 15 | mkdir -p $CIRCLE_ARTIFACTS_DIR 16 | 17 | # Stash Circle Artifacts URL 18 | CIRCLE_ARTIFACTS_URL="$CIRCLE_BUILD_URL/artifacts/$CIRCLE_NODE_INDEX/$CIRCLE_ARTIFACTS" 19 | 20 | # Ping the multidev environment to wake it from sleep 21 | echo -e "\nPinging the ${MULTIDEV} multidev environment to wake it from sleep for $SITE_NAME..." 22 | curl -I "$MULTIDEV_URL" >/dev/null 23 | 24 | # Ping the live environment to wake it from sleep 25 | echo -e "\nPinging the live environment to wake it from sleep for $SITE_NAME..." 26 | curl -I "$LIVE_URL" >/dev/null 27 | 28 | # Check for custom backstop.json for the specific site 29 | if [ -f "$SITE_NAME.backstop.json" ] || [ -f "$SITE_NAME.backstop-config.js" ]; then 30 | 31 | echo -e "\nCustom Backstop template $SITE_NAME.backstop.json or $SITE_NAME.backstop-config.js found for $SITE_NAME, skipping URL crawl..." 32 | 33 | if [ -f "$SITE_NAME.backstop.json" ]; then 34 | cp "$SITE_NAME.backstop.json" backstop.json 35 | fi 36 | 37 | else 38 | # Otherwise create Backstop config file dynamically by crawling site URLs 39 | echo -e "\nCreating backstop.js config file with backstop-crawl for $SITE_NAME..." 40 | backstop-crawl $LIVE_URL --referenceUrl="$MULTIDEV_URL" --ignore-robots --limit-similar=1 41 | fi 42 | 43 | # Backstop visual regression 44 | echo -e "\nRunning backstop reference for $SITE_NAME against the $MULTIDEV_URL..." 45 | 46 | if [ -f "$SITE_NAME.backstop-config.js" ]; then 47 | backstop reference --config="$SITE_NAME.backstop-config.js" 48 | else 49 | backstop reference 50 | fi 51 | 52 | echo -e "\nRunning backstop test for $SITE_NAME against the $LIVE_URL..." 53 | 54 | if [ -f "$SITE_NAME.backstop-config.js" ]; then 55 | VISUAL_REGRESSION_RESULTS="$(backstop test --config=$SITE_NAME.backstop-config.js || echo 'true' )" 56 | else 57 | VISUAL_REGRESSION_RESULTS=$(backstop test || echo 'true') 58 | fi 59 | 60 | echo "${VISUAL_REGRESSION_RESULTS}" 61 | 62 | # Rsync files to CIRCLE_ARTIFACTS_DIR 63 | echo -e "\nRsyncing backstop_data files to $CIRCLE_ARTIFACTS_DIR for $SITE_NAME..." 64 | rsync -rlvz backstop_data $CIRCLE_ARTIFACTS_DIR 65 | 66 | DIFF_REPORT="$CIRCLE_ARTIFACTS_DIR/backstop_data/html_report/index.html" 67 | 68 | if [ ! -f $DIFF_REPORT ]; then 69 | echo -e "\nDiff report file $DIFF_REPORT not found for $SITE_NAME!" 70 | exit 1 71 | fi 72 | 73 | VISUAL_REGRESSION_HTML_REPORT_URL="$CIRCLE_ARTIFACTS_URL/backstop_data/html_report/index.html" 74 | 75 | if [[ ${VISUAL_REGRESSION_RESULTS} == *"Mismatch errors found"* ]] 76 | then 77 | # visual regression failed 78 | echo -e "\nVisual regression tests failed! Please manually check the ${MULTIDEV} multidev for $SITE_NAME..." 79 | SLACK_MESSAGE="Circle CI update check #${CIRCLE_BUILD_NUM} by ${CIRCLE_PROJECT_USERNAME} on ${SITE_NAME}. Visual regression tests failed on the ${MULTIDEV} environment! Please test manually." 80 | 81 | SLACK_ATTACHEMENTS="\"attachments\": [{\"fallback\": \"View the visual regression report in CircleCI artifacts\",\"color\": \"${RED_HEX}\",\"actions\": [{\"type\": \"button\",\"text\": \"BackstopJS Report\",\"url\":\"${VISUAL_REGRESSION_HTML_REPORT_URL}\"},{\"type\": \"button\",\"text\": \"${MULTIDEV} Site\",\"url\":\"${MULTIDEV_URL}\"},{\"type\": \"button\",\"text\": \"${MULTIDEV} Dashboard\",\"url\":\"https://dashboard.pantheon.io/sites/${SITE_UUID}#${MULTIDEV}/code\"}]}]" 82 | 83 | echo -e "\nSending a message to the ${SLACK_CHANNEL} Slack channel" 84 | curl -X POST --data "payload={\"channel\": \"${SLACK_CHANNEL}\",${SLACK_ATTACHEMENTS}, \"username\": \"${SLACK_USERNAME}\", \"text\": \"${SLACK_MESSAGE}\"}" $SLACK_HOOK_URL 85 | else 86 | # visual regression passed 87 | echo -e "\nVisual regression tests passed between the ${MULTIDEV} multidev and live for $SITE_NAME." 88 | 89 | # Lighthouse performance testing 90 | echo -e "\nStarting the Lighthouse performance testing job via API for $SITE_NAME..." 91 | curl --user ${CIRCLE_TOKEN}: \ 92 | --data build_parameters[CIRCLE_JOB]=lighthouse_performance_test \ 93 | --data build_parameters[VISUAL_REGRESSION_HTML_REPORT_URL]=$VISUAL_REGRESSION_HTML_REPORT_URL \ 94 | --data build_parameters[SITE_NAME]=$SITE_NAME \ 95 | --data build_parameters[SITE_UUID]=$SITE_UUID \ 96 | --data build_parameters[CREATE_BACKUPS]=$CREATE_BACKUPS \ 97 | --data build_parameters[RECREATE_MULTIDEV]=$RECREATE_MULTIDEV \ 98 | --data build_parameters[LIVE_URL]=$LIVE_URL \ 99 | --data revision=$CIRCLE_SHA1 \ 100 | https://circleci.com/api/v1.1/project/github/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/tree/$CIRCLE_BRANCH >/dev/null 101 | fi -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | backstop_data/bitmaps_reference/ 4 | backstop_data/bitmaps_test/ 5 | backstop.json 6 | vendor 7 | .DS_Store 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Pantheon 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pantheon Example Terminus Auto Update Script 2 | 3 | ## Repository Archived 2019-06-13 4 | 5 | This repository was archived on the 26th of June 2019. It remains as a reference implementation but is no longer used or maintained. The sites previously updated by this script have been migrated to [StagingPilot](https://pantheon.io/blog/robots-autopilot-and-holy-grail-webops). 6 | 7 | ## Description 8 | 9 | Scalable automated testing and deployment of upstream (core), plugin and theme updates on [Pantheon](https://pantheon.io) sites. This repository uses these open source tools: 10 | * [Terminus](https://github.com/pantheon-systems/terminus) for interacting with Pantheon on the command line 11 | * [CircleCI](https://circleci.com) for running jobs in the cloud 12 | * [WP-CLI](http://wp-cli.org/) for interacting with WordPress on the command line 13 | * [Drush](https://www.drush.org/) for interacting with Drupal on the command line 14 | * [Behat](http://behat.org/) for integration and acceptance testing 15 | * [WordHat](https://wordhat.info/) for WordPress-specific functionality for common testing scenarios in Behat 16 | * [Google Lighthouse](https://developers.google.com/web/tools/lighthouse/) for performance testing 17 | * [BackstopJS](https://garris.github.io/BackstopJS/) for visual regression testing 18 | * [Slack](https://slack.com/) for communication 19 | 20 | ## Disclaimer 21 | While this script has worked well for us your mileage may vary. This repository is a proof of concept example of advanced Pantheon platform usage and is provided without warranty or direct support. 22 | 23 | Issues and questions may be filed in GitHub but their resolution is not guaranteed. 24 | 25 | ## The Process 26 | 27 | This script will loop through all sites in `sites-to-auto-update.json` and: 28 | 29 | 1. Authenticate with [Terminus](https://github.com/pantheon-systems/terminus) via machine token 30 | 2. Delete the multidev environment `auto-update` 31 | 3. Recreate the multidev environment `auto-update` 32 | * Deletion and recreation is done to clear any existing changes and pull the latest database/files from the live environment 33 | * This is opt-out per site and should only be disabled if using Solr or multidev creation takes an excessively long time due to large file and database sizes 34 | 4. Switch the multidev environment `auto-update` to git mode 35 | 5. Check for and apply [Pantheon upstream updates](https://pantheon.io/docs/upstream-updates/) 36 | * WordPress or Drupal core updates are managed in the default upstream 37 | * Custom upstream updates will be applied if using a custom upstream 38 | 6. Switch the multidev environment `auto-update` to SFTP mode 39 | 7. Check for and apply WordPress plugin or Drupal module updates, if available 40 | 8. Check for and apply WordPress theme updates, if available 41 | * If no updates are available the script will stop here 42 | 9. Run a visual regression test between the live environment and the multidev environment 43 | * If the visual regression test fails the script will stop here and post a link to the visual regression report in Slack 44 | 10. Merge the multidev environment with the dev environment 45 | 11. Deploy the dev environment to the test environment 46 | 12. Create a backup of the test environment 47 | * This is opt-out per site and should only be disabled if backups take an excessively long time due to large file and database sizes **and** you have regularly backups scheduled via another method. 48 | 13. Create a backup of the live environment 49 | * This is opt-out per site and should only be disabled if backups take an excessively long time due to large file and database sizes **and** you have regularly backups scheduled via another method. 50 | 14. Deploy the test environment to the live environment 51 | 15. Post a success message to Slack 52 | * Test failures will also be reported to Slack 53 | 54 | ## Setup 55 | 0. Create a new GitHub repository 56 | 1. Don't fork this repository, instead clone it and [change the remote URL](https://help.github.com/articles/changing-a-remote-s-url/) to the GitHub repository above and push the code there 57 | 2. Update `backstop.template.json` to meet your needs 58 | * For example, you may want to tweak things like `viewport` 59 | 3. Create a [CircleCI](https://circleci.com) project 60 | * It should be linked to your GitHub repository 61 | 4. Add [environment variables to CircleCI](https://circleci.com/docs/environment-variables/) for the following: 62 | * `MULTIDEV`: The multidev name to use for applying/testing updates. Defaults to `auto-update` 63 | * `CIRCLE_TOKEN`: A CircleCI API token with access to the CircleCI project created above. 64 | * `TERMINUS_MACHINE_TOKEN`: A [Pantheon Terminus machine token](https://pantheon.io/docs/machine-tokens/) with access to all the sites you plan to update. 65 | * `SLACK_HOOK_URL`: The [Slack incoming webhook URL](https://api.slack.com/incoming-webhooks) 66 | * `SLACK_CHANNEL`: The Slack channel to post notifications to 67 | * `SLACK_USERNAME`: The username to post to Slack with 68 | 5. Add an [SSH key to Pantheon](https://pantheon.io/docs/ssh-keys/) and [to the CircleCI project](https://circleci.com/docs/2.0/add-ssh-key/) 69 | 6. Edit `sites-to-auto-update.json` and set the following key for each JSON object for sites you wish to auto update. **The order is important** do not change the order of the keys in the object or skip keys. 70 | * `SITE_UUID`: The site UUID, which can be acquired with `terminus site:list` or is in the dashboard URL for the site. 71 | * `SITE_NAME`: The site machine name, which can be acquired with `terminus site:list`. 72 | * `CREATE_BACKUPS`: `0` or `1` to determine if a backup of the site is made before deployment. You may want to disable backups for sites where a backup takes an excessively long time due to large file and database sizes **and** you have regularly backups scheduled via another method. 73 | * `RECREATE_MULTIDEV`: `0` or `1` to determine if the multidev is deleted and recreated with each run. 74 | * `LIVE_URL`: The preferred custom domain (full URL) for the live environment to use in automated testing **or** set to `0` to use the default Pantheon hosted URL, 75 | 76 | ## Know Limitations 77 | * Backups of sites with large a large database or media files are taking too long and timing out on Circle CI 78 | * Sites with a Solr Index fail visual regression tests as the multidev created doesn't have items indexed in Solr 79 | * `backstop-crawl` on sites with many (~100+) URLs are taking too long and timing out on Circle CI. 80 | * This can be alleviated with a custom `SITE_NAME.backstop.json` or `SITE_NAME.backstop-config.js` file. 81 | * If automated testing fails **and** `RECREATE_MULTIDEV` is set to `0` then a multidev with updates applied will persist causing subsequent update checks to return no updates and prevent automated tests from running again. This cycle will break when there are further updates released to be applied. 82 | * [Composer](https"//getcomposer.org) managed sites are not supported. For Composer managed sites a service like [dependencies.io](https://www.dependencies.io/), which will create pull requests for Composer updates, is useful. 83 | 84 | ## Configuring Backstop JS 85 | `backstop.template.json` is used as a generic template for `backstop-crawl` when creating `backstop.json` files dynamically. 86 | 87 | For each site a custom template in the form of `SITE_NAME.backstop.json` or `SITE_NAME.backstop-config.js`, where `SITE_NAME` is the machine name for the Pantheon site, can be also be created and will take precedence over the template above. The former is a hard coded Backstop JS file and the latter is a JavaScript file that must export valid JSON contents of a Backstop JS file. 88 | 89 | The custom templates above are most useful for sites with many URLs where a crawl will timeout. In this case manually specifying which URLs to test is needed. 90 | 91 | ## Behat Tests 92 | Behat testing is currently only supported for WordPress sites. To have Behat tests run for a site create Behat feature files in the directory `tests/behat//features`, replacing `` with the Pantheon site machine name. 93 | 94 | ## Notes 95 | This workflow assumes that the Dev and Test environments on Pantheon are always in a shippable state as the script will automatically deploy changes from Dev to Test and Live if the visual regression tests of updates pass. 96 | 97 | All work that isn't ready for deployment to production should be kept in a [Pantheon multidev environment](https://pantheon.io/docs/multidev/), on a separate git branch. 98 | 99 | Scalability relies on the number of CircleCI workers available. If workers are available to process jobs in parallel this script will scale very well. 100 | 101 | ## Changelog 102 | ### `1.0.0-beta-1` 103 | * Initial beta release 104 | 105 | ## License 106 | MIT 107 | -------------------------------------------------------------------------------- /backstop.template.json: -------------------------------------------------------------------------------- 1 | { 2 | "viewports": [ 3 | { 4 | "name": "phone", 5 | "width": 320, 6 | "height": 480 7 | }, 8 | { 9 | "name": "tablet_v", 10 | "width": 568, 11 | "height": 1024 12 | }, 13 | { 14 | "name": "tablet_h", 15 | "width": 1024, 16 | "height": 768 17 | }, 18 | { 19 | "name": "desktop", 20 | "width": 1920, 21 | "height": 1080 22 | } 23 | ], 24 | "scenarios": [], 25 | "defaultScenario": { 26 | "label": "Default", 27 | "url": "", 28 | "referenceUrl": "", 29 | "hideSelectors": [], 30 | "selectors": [ 31 | "document" 32 | ], 33 | "readyEvent": null, 34 | "delay": 1500, 35 | "misMatchThreshold": 0.1 36 | }, 37 | "paths": { 38 | "bitmaps_reference": "backstop_data/bitmaps_reference", 39 | "bitmaps_test": "backstop_data/bitmaps_test", 40 | "compare_data": "backstop_data/bitmaps_test/compare.json", 41 | "casper_scripts": "backstop_data/casper_scripts" 42 | }, 43 | "engine": "chrome", 44 | "report": [ "CLI" ], 45 | "casperFlags": [], 46 | "debug": false, 47 | "port": 3001 48 | } 49 | -------------------------------------------------------------------------------- /backstop_data/casper_scripts/onBefore.js: -------------------------------------------------------------------------------- 1 | module.exports = function(casper, scenario, vp) { 2 | casper.echo('onBeforeEach.js', 'INFO'); 3 | casper.wait(50); 4 | }; 5 | 6 | 7 | // // EXAMPLE: LOGIN BEFORE RUNNING TESTS 8 | // module.exports = function(casper, scenario, vp) { 9 | // casper.thenOpen(scenario.url, function(){ 10 | // if (this.exists('form#user-login-form')) { 11 | // this.fill('form#loginForm',{ 12 | // 'username': 'test', 13 | // 'password': 'changeme' 14 | // }, true); 15 | // } 16 | // }); 17 | // }; 18 | -------------------------------------------------------------------------------- /backstop_data/casper_scripts/onReady.js: -------------------------------------------------------------------------------- 1 | module.exports = function(casper, scenario, vp) { 2 | casper.echo('onReady.js', 'INFO'); 3 | casper.evaluate(function(){ 4 | 5 | }); 6 | casper.wait(50); 7 | }; 8 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pantheon-systems/example-terminus-auto-update-script", 3 | "description": "", 4 | "version": "1.0.0", 5 | "type": "project", 6 | "keywords": [], 7 | "minimum-stability": "dev", 8 | "repositories": [ 9 | { 10 | "type": "composer", 11 | "url": "https://wpackagist.org" 12 | }, 13 | { 14 | "type": "vcs", 15 | "url": "https://github.com/paulgibbs/behat-wordpress-extension" 16 | } 17 | ], 18 | "require": { 19 | "php": ">=7.1" 20 | }, 21 | "require-dev": { 22 | "behat/mink": "~1.5", 23 | "behat/mink-goutte-driver": "^1.2@dev", 24 | "behat/mink-selenium2-driver": "^1.3@dev", 25 | "paulgibbs/behat-wordpress-extension": "dev-185-path-fix" 26 | }, 27 | "config": { 28 | "vendor-dir": "vendor", 29 | "preferred-install": "dist", 30 | "optimize-autoloader": true, 31 | "sort-packages": true 32 | }, 33 | "scripts": { 34 | "wordhat-scenarios": [ 35 | "./vendor/bin/behat -dl --config=tests/behat/behat-pantheon.yml" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /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 | "content-hash": "022b7785bdb7affcd024ae1f2a9943dc", 8 | "packages": [], 9 | "packages-dev": [ 10 | { 11 | "name": "behat/behat", 12 | "version": "v3.4.3", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/Behat/Behat.git", 16 | "reference": "d60b161bff1b95ec4bb80bb8cb210ccf890314c2" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/Behat/Behat/zipball/d60b161bff1b95ec4bb80bb8cb210ccf890314c2", 21 | "reference": "d60b161bff1b95ec4bb80bb8cb210ccf890314c2", 22 | "shasum": "" 23 | }, 24 | "require": { 25 | "behat/gherkin": "^4.5.1", 26 | "behat/transliterator": "^1.2", 27 | "container-interop/container-interop": "^1.2", 28 | "ext-mbstring": "*", 29 | "php": ">=5.3.3", 30 | "psr/container": "^1.0", 31 | "symfony/class-loader": "~2.1||~3.0||~4.0", 32 | "symfony/config": "~2.3||~3.0||~4.0", 33 | "symfony/console": "~2.5||~3.0||~4.0", 34 | "symfony/dependency-injection": "~2.1||~3.0||~4.0", 35 | "symfony/event-dispatcher": "~2.1||~3.0||~4.0", 36 | "symfony/translation": "~2.3||~3.0||~4.0", 37 | "symfony/yaml": "~2.1||~3.0||~4.0" 38 | }, 39 | "require-dev": { 40 | "herrera-io/box": "~1.6.1", 41 | "phpunit/phpunit": "^4.8.36|^6.3", 42 | "symfony/process": "~2.5|~3.0|~4.0" 43 | }, 44 | "suggest": { 45 | "behat/mink-extension": "for integration with Mink testing framework", 46 | "behat/symfony2-extension": "for integration with Symfony2 web framework", 47 | "behat/yii-extension": "for integration with Yii web framework" 48 | }, 49 | "bin": [ 50 | "bin/behat" 51 | ], 52 | "type": "library", 53 | "extra": { 54 | "branch-alias": { 55 | "dev-master": "3.2.x-dev" 56 | } 57 | }, 58 | "autoload": { 59 | "psr-0": { 60 | "Behat\\Behat": "src/", 61 | "Behat\\Testwork": "src/" 62 | } 63 | }, 64 | "notification-url": "https://packagist.org/downloads/", 65 | "license": [ 66 | "MIT" 67 | ], 68 | "authors": [ 69 | { 70 | "name": "Konstantin Kudryashov", 71 | "email": "ever.zet@gmail.com", 72 | "homepage": "http://everzet.com" 73 | } 74 | ], 75 | "description": "Scenario-oriented BDD framework for PHP 5.3", 76 | "homepage": "http://behat.org/", 77 | "keywords": [ 78 | "Agile", 79 | "BDD", 80 | "ScenarioBDD", 81 | "Scrum", 82 | "StoryBDD", 83 | "User story", 84 | "business", 85 | "development", 86 | "documentation", 87 | "examples", 88 | "symfony", 89 | "testing" 90 | ], 91 | "time": "2017-11-27T10:37:56+00:00" 92 | }, 93 | { 94 | "name": "behat/gherkin", 95 | "version": "v4.5.1", 96 | "source": { 97 | "type": "git", 98 | "url": "https://github.com/Behat/Gherkin.git", 99 | "reference": "74ac03d52c5e23ad8abd5c5cce4ab0e8dc1b530a" 100 | }, 101 | "dist": { 102 | "type": "zip", 103 | "url": "https://api.github.com/repos/Behat/Gherkin/zipball/74ac03d52c5e23ad8abd5c5cce4ab0e8dc1b530a", 104 | "reference": "74ac03d52c5e23ad8abd5c5cce4ab0e8dc1b530a", 105 | "shasum": "" 106 | }, 107 | "require": { 108 | "php": ">=5.3.1" 109 | }, 110 | "require-dev": { 111 | "phpunit/phpunit": "~4.5|~5", 112 | "symfony/phpunit-bridge": "~2.7|~3", 113 | "symfony/yaml": "~2.3|~3" 114 | }, 115 | "suggest": { 116 | "symfony/yaml": "If you want to parse features, represented in YAML files" 117 | }, 118 | "type": "library", 119 | "extra": { 120 | "branch-alias": { 121 | "dev-master": "4.4-dev" 122 | } 123 | }, 124 | "autoload": { 125 | "psr-0": { 126 | "Behat\\Gherkin": "src/" 127 | } 128 | }, 129 | "notification-url": "https://packagist.org/downloads/", 130 | "license": [ 131 | "MIT" 132 | ], 133 | "authors": [ 134 | { 135 | "name": "Konstantin Kudryashov", 136 | "email": "ever.zet@gmail.com", 137 | "homepage": "http://everzet.com" 138 | } 139 | ], 140 | "description": "Gherkin DSL parser for PHP 5.3", 141 | "homepage": "http://behat.org/", 142 | "keywords": [ 143 | "BDD", 144 | "Behat", 145 | "Cucumber", 146 | "DSL", 147 | "gherkin", 148 | "parser" 149 | ], 150 | "time": "2017-08-30T11:04:43+00:00" 151 | }, 152 | { 153 | "name": "behat/mink", 154 | "version": "dev-master", 155 | "source": { 156 | "type": "git", 157 | "url": "https://github.com/minkphp/Mink.git", 158 | "reference": "04ab7af68536ac2c80fd6c08a6fd3620d3409891" 159 | }, 160 | "dist": { 161 | "type": "zip", 162 | "url": "https://api.github.com/repos/minkphp/Mink/zipball/04ab7af68536ac2c80fd6c08a6fd3620d3409891", 163 | "reference": "04ab7af68536ac2c80fd6c08a6fd3620d3409891", 164 | "shasum": "" 165 | }, 166 | "require": { 167 | "php": ">=5.3.1", 168 | "symfony/css-selector": "^2.7|^3.0|^4.0" 169 | }, 170 | "require-dev": { 171 | "symfony/phpunit-bridge": "^3.3|^4.0" 172 | }, 173 | "suggest": { 174 | "behat/mink-browserkit-driver": "extremely fast headless driver for Symfony\\Kernel-based apps (Sf2, Silex)", 175 | "behat/mink-goutte-driver": "fast headless driver for any app without JS emulation", 176 | "behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)", 177 | "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)" 178 | }, 179 | "type": "library", 180 | "extra": { 181 | "branch-alias": { 182 | "dev-master": "1.7.x-dev" 183 | } 184 | }, 185 | "autoload": { 186 | "psr-4": { 187 | "Behat\\Mink\\": "src/" 188 | } 189 | }, 190 | "notification-url": "https://packagist.org/downloads/", 191 | "license": [ 192 | "MIT" 193 | ], 194 | "authors": [ 195 | { 196 | "name": "Konstantin Kudryashov", 197 | "email": "ever.zet@gmail.com", 198 | "homepage": "http://everzet.com" 199 | } 200 | ], 201 | "description": "Browser controller/emulator abstraction for PHP", 202 | "homepage": "http://mink.behat.org/", 203 | "keywords": [ 204 | "browser", 205 | "testing", 206 | "web" 207 | ], 208 | "time": "2018-01-07T17:25:05+00:00" 209 | }, 210 | { 211 | "name": "behat/mink-browserkit-driver", 212 | "version": "dev-master", 213 | "source": { 214 | "type": "git", 215 | "url": "https://github.com/minkphp/MinkBrowserKitDriver.git", 216 | "reference": "7c45c64264895c2972cbdc21d51da7e9aaba6b47" 217 | }, 218 | "dist": { 219 | "type": "zip", 220 | "url": "https://api.github.com/repos/minkphp/MinkBrowserKitDriver/zipball/7c45c64264895c2972cbdc21d51da7e9aaba6b47", 221 | "reference": "7c45c64264895c2972cbdc21d51da7e9aaba6b47", 222 | "shasum": "" 223 | }, 224 | "require": { 225 | "behat/mink": "^1.7.1@dev", 226 | "php": ">=5.3.6", 227 | "symfony/browser-kit": "~2.3|~3.0|~4.0", 228 | "symfony/dom-crawler": "~2.3|~3.0|~4.0" 229 | }, 230 | "require-dev": { 231 | "mink/driver-testsuite": "dev-master", 232 | "symfony/http-kernel": "~2.3|~3.0|~4.0" 233 | }, 234 | "type": "mink-driver", 235 | "extra": { 236 | "branch-alias": { 237 | "dev-master": "1.3.x-dev" 238 | } 239 | }, 240 | "autoload": { 241 | "psr-4": { 242 | "Behat\\Mink\\Driver\\": "src/" 243 | } 244 | }, 245 | "notification-url": "https://packagist.org/downloads/", 246 | "license": [ 247 | "MIT" 248 | ], 249 | "authors": [ 250 | { 251 | "name": "Konstantin Kudryashov", 252 | "email": "ever.zet@gmail.com", 253 | "homepage": "http://everzet.com" 254 | } 255 | ], 256 | "description": "Symfony2 BrowserKit driver for Mink framework", 257 | "homepage": "http://mink.behat.org/", 258 | "keywords": [ 259 | "Mink", 260 | "Symfony2", 261 | "browser", 262 | "testing" 263 | ], 264 | "time": "2017-12-04T14:53:23+00:00" 265 | }, 266 | { 267 | "name": "behat/mink-extension", 268 | "version": "v2.2", 269 | "source": { 270 | "type": "git", 271 | "url": "https://github.com/Behat/MinkExtension.git", 272 | "reference": "5b4bda64ff456104564317e212c823e45cad9d59" 273 | }, 274 | "dist": { 275 | "type": "zip", 276 | "url": "https://api.github.com/repos/Behat/MinkExtension/zipball/5b4bda64ff456104564317e212c823e45cad9d59", 277 | "reference": "5b4bda64ff456104564317e212c823e45cad9d59", 278 | "shasum": "" 279 | }, 280 | "require": { 281 | "behat/behat": "~3.0,>=3.0.5", 282 | "behat/mink": "~1.5", 283 | "php": ">=5.3.2", 284 | "symfony/config": "~2.2|~3.0" 285 | }, 286 | "require-dev": { 287 | "behat/mink-goutte-driver": "~1.1", 288 | "phpspec/phpspec": "~2.0" 289 | }, 290 | "type": "behat-extension", 291 | "extra": { 292 | "branch-alias": { 293 | "dev-master": "2.1.x-dev" 294 | } 295 | }, 296 | "autoload": { 297 | "psr-0": { 298 | "Behat\\MinkExtension": "src/" 299 | } 300 | }, 301 | "notification-url": "https://packagist.org/downloads/", 302 | "license": [ 303 | "MIT" 304 | ], 305 | "authors": [ 306 | { 307 | "name": "Christophe Coevoet", 308 | "email": "stof@notk.org" 309 | }, 310 | { 311 | "name": "Konstantin Kudryashov", 312 | "email": "ever.zet@gmail.com" 313 | } 314 | ], 315 | "description": "Mink extension for Behat", 316 | "homepage": "http://extensions.behat.org/mink", 317 | "keywords": [ 318 | "browser", 319 | "gui", 320 | "test", 321 | "web" 322 | ], 323 | "time": "2016-02-15T07:55:18+00:00" 324 | }, 325 | { 326 | "name": "behat/mink-goutte-driver", 327 | "version": "dev-master", 328 | "source": { 329 | "type": "git", 330 | "url": "https://github.com/minkphp/MinkGoutteDriver.git", 331 | "reference": "7a4b2d49511865e23d61463514fa2754d42ec658" 332 | }, 333 | "dist": { 334 | "type": "zip", 335 | "url": "https://api.github.com/repos/minkphp/MinkGoutteDriver/zipball/7a4b2d49511865e23d61463514fa2754d42ec658", 336 | "reference": "7a4b2d49511865e23d61463514fa2754d42ec658", 337 | "shasum": "" 338 | }, 339 | "require": { 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 | "mink/driver-testsuite": "dev-master" 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-10-14T20:19:06+00:00" 378 | }, 379 | { 380 | "name": "behat/mink-selenium2-driver", 381 | "version": "dev-master", 382 | "source": { 383 | "type": "git", 384 | "url": "https://github.com/minkphp/MinkSelenium2Driver.git", 385 | "reference": "93474c65a2a7bf959200ab5f7a14cc450645c185" 386 | }, 387 | "dist": { 388 | "type": "zip", 389 | "url": "https://api.github.com/repos/minkphp/MinkSelenium2Driver/zipball/93474c65a2a7bf959200ab5f7a14cc450645c185", 390 | "reference": "93474c65a2a7bf959200ab5f7a14cc450645c185", 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 | "mink/driver-testsuite": "dev-master" 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": "2018-01-07T19:17:08+00:00" 439 | }, 440 | { 441 | "name": "behat/transliterator", 442 | "version": "dev-master", 443 | "source": { 444 | "type": "git", 445 | "url": "https://github.com/Behat/Transliterator.git", 446 | "reference": "826ce7e9c2a6664c0d1f381cbb38b1fb80a7ee2c" 447 | }, 448 | "dist": { 449 | "type": "zip", 450 | "url": "https://api.github.com/repos/Behat/Transliterator/zipball/826ce7e9c2a6664c0d1f381cbb38b1fb80a7ee2c", 451 | "reference": "826ce7e9c2a6664c0d1f381cbb38b1fb80a7ee2c", 452 | "shasum": "" 453 | }, 454 | "require": { 455 | "php": ">=5.3.3" 456 | }, 457 | "require-dev": { 458 | "chuyskywalker/rolling-curl": "^3.1", 459 | "php-yaoi/php-yaoi": "^1.0" 460 | }, 461 | "type": "library", 462 | "extra": { 463 | "branch-alias": { 464 | "dev-master": "1.2-dev" 465 | } 466 | }, 467 | "autoload": { 468 | "psr-0": { 469 | "Behat\\Transliterator": "src/" 470 | } 471 | }, 472 | "notification-url": "https://packagist.org/downloads/", 473 | "license": [ 474 | "Artistic-1.0" 475 | ], 476 | "description": "String transliterator", 477 | "keywords": [ 478 | "i18n", 479 | "slug", 480 | "transliterator" 481 | ], 482 | "time": "2017-04-04T11:38:05+00:00" 483 | }, 484 | { 485 | "name": "container-interop/container-interop", 486 | "version": "1.2.0", 487 | "source": { 488 | "type": "git", 489 | "url": "https://github.com/container-interop/container-interop.git", 490 | "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8" 491 | }, 492 | "dist": { 493 | "type": "zip", 494 | "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8", 495 | "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8", 496 | "shasum": "" 497 | }, 498 | "require": { 499 | "psr/container": "^1.0" 500 | }, 501 | "type": "library", 502 | "autoload": { 503 | "psr-4": { 504 | "Interop\\Container\\": "src/Interop/Container/" 505 | } 506 | }, 507 | "notification-url": "https://packagist.org/downloads/", 508 | "license": [ 509 | "MIT" 510 | ], 511 | "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", 512 | "homepage": "https://github.com/container-interop/container-interop", 513 | "time": "2017-02-14T19:40:03+00:00" 514 | }, 515 | { 516 | "name": "fabpot/goutte", 517 | "version": "dev-master", 518 | "source": { 519 | "type": "git", 520 | "url": "https://github.com/FriendsOfPHP/Goutte.git", 521 | "reference": "395f61d7c2e15a813839769553a4de16fa3b3c96" 522 | }, 523 | "dist": { 524 | "type": "zip", 525 | "url": "https://api.github.com/repos/FriendsOfPHP/Goutte/zipball/395f61d7c2e15a813839769553a4de16fa3b3c96", 526 | "reference": "395f61d7c2e15a813839769553a4de16fa3b3c96", 527 | "shasum": "" 528 | }, 529 | "require": { 530 | "guzzlehttp/guzzle": "^6.0", 531 | "php": ">=5.5.0", 532 | "symfony/browser-kit": "~2.1|~3.0|~4.0", 533 | "symfony/css-selector": "~2.1|~3.0|~4.0", 534 | "symfony/dom-crawler": "~2.1|~3.0|~4.0" 535 | }, 536 | "require-dev": { 537 | "symfony/phpunit-bridge": "^3.3 || ^4" 538 | }, 539 | "type": "application", 540 | "extra": { 541 | "branch-alias": { 542 | "dev-master": "3.2-dev" 543 | } 544 | }, 545 | "autoload": { 546 | "psr-4": { 547 | "Goutte\\": "Goutte" 548 | }, 549 | "exclude-from-classmap": [ 550 | "Goutte/Tests" 551 | ] 552 | }, 553 | "notification-url": "https://packagist.org/downloads/", 554 | "license": [ 555 | "MIT" 556 | ], 557 | "authors": [ 558 | { 559 | "name": "Fabien Potencier", 560 | "email": "fabien@symfony.com" 561 | } 562 | ], 563 | "description": "A simple PHP Web Scraper", 564 | "homepage": "https://github.com/FriendsOfPHP/Goutte", 565 | "keywords": [ 566 | "scraper" 567 | ], 568 | "time": "2017-11-19T08:45:40+00:00" 569 | }, 570 | { 571 | "name": "guzzlehttp/guzzle", 572 | "version": "6.3.0", 573 | "source": { 574 | "type": "git", 575 | "url": "https://github.com/guzzle/guzzle.git", 576 | "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699" 577 | }, 578 | "dist": { 579 | "type": "zip", 580 | "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f4db5a78a5ea468d4831de7f0bf9d9415e348699", 581 | "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699", 582 | "shasum": "" 583 | }, 584 | "require": { 585 | "guzzlehttp/promises": "^1.0", 586 | "guzzlehttp/psr7": "^1.4", 587 | "php": ">=5.5" 588 | }, 589 | "require-dev": { 590 | "ext-curl": "*", 591 | "phpunit/phpunit": "^4.0 || ^5.0", 592 | "psr/log": "^1.0" 593 | }, 594 | "suggest": { 595 | "psr/log": "Required for using the Log middleware" 596 | }, 597 | "type": "library", 598 | "extra": { 599 | "branch-alias": { 600 | "dev-master": "6.2-dev" 601 | } 602 | }, 603 | "autoload": { 604 | "files": [ 605 | "src/functions_include.php" 606 | ], 607 | "psr-4": { 608 | "GuzzleHttp\\": "src/" 609 | } 610 | }, 611 | "notification-url": "https://packagist.org/downloads/", 612 | "license": [ 613 | "MIT" 614 | ], 615 | "authors": [ 616 | { 617 | "name": "Michael Dowling", 618 | "email": "mtdowling@gmail.com", 619 | "homepage": "https://github.com/mtdowling" 620 | } 621 | ], 622 | "description": "Guzzle is a PHP HTTP client library", 623 | "homepage": "http://guzzlephp.org/", 624 | "keywords": [ 625 | "client", 626 | "curl", 627 | "framework", 628 | "http", 629 | "http client", 630 | "rest", 631 | "web service" 632 | ], 633 | "time": "2017-06-22T18:50:49+00:00" 634 | }, 635 | { 636 | "name": "guzzlehttp/promises", 637 | "version": "dev-master", 638 | "source": { 639 | "type": "git", 640 | "url": "https://github.com/guzzle/promises.git", 641 | "reference": "2e48ae638dc0bf0849772f5590835fcd700a2e1d" 642 | }, 643 | "dist": { 644 | "type": "zip", 645 | "url": "https://api.github.com/repos/guzzle/promises/zipball/2e48ae638dc0bf0849772f5590835fcd700a2e1d", 646 | "reference": "2e48ae638dc0bf0849772f5590835fcd700a2e1d", 647 | "shasum": "" 648 | }, 649 | "require": { 650 | "php": ">=5.5.0" 651 | }, 652 | "require-dev": { 653 | "phpunit/phpunit": "^4.8.36" 654 | }, 655 | "type": "library", 656 | "extra": { 657 | "branch-alias": { 658 | "dev-master": "1.4-dev" 659 | } 660 | }, 661 | "autoload": { 662 | "psr-4": { 663 | "GuzzleHttp\\Promise\\": "src/" 664 | }, 665 | "files": [ 666 | "src/functions_include.php" 667 | ] 668 | }, 669 | "notification-url": "https://packagist.org/downloads/", 670 | "license": [ 671 | "MIT" 672 | ], 673 | "authors": [ 674 | { 675 | "name": "Michael Dowling", 676 | "email": "mtdowling@gmail.com", 677 | "homepage": "https://github.com/mtdowling" 678 | } 679 | ], 680 | "description": "Guzzle promises library", 681 | "keywords": [ 682 | "promise" 683 | ], 684 | "time": "2017-12-07T21:04:15+00:00" 685 | }, 686 | { 687 | "name": "guzzlehttp/psr7", 688 | "version": "dev-master", 689 | "source": { 690 | "type": "git", 691 | "url": "https://github.com/guzzle/psr7.git", 692 | "reference": "d2537c86fa8b004c29e9b9f5e10028f0a29df101" 693 | }, 694 | "dist": { 695 | "type": "zip", 696 | "url": "https://api.github.com/repos/guzzle/psr7/zipball/d2537c86fa8b004c29e9b9f5e10028f0a29df101", 697 | "reference": "d2537c86fa8b004c29e9b9f5e10028f0a29df101", 698 | "shasum": "" 699 | }, 700 | "require": { 701 | "php": ">=5.4.0", 702 | "psr/http-message": "~1.0" 703 | }, 704 | "provide": { 705 | "psr/http-message-implementation": "1.0" 706 | }, 707 | "require-dev": { 708 | "phpunit/phpunit": "~4.0" 709 | }, 710 | "type": "library", 711 | "extra": { 712 | "branch-alias": { 713 | "dev-master": "1.4-dev" 714 | } 715 | }, 716 | "autoload": { 717 | "psr-4": { 718 | "GuzzleHttp\\Psr7\\": "src/" 719 | }, 720 | "files": [ 721 | "src/functions_include.php" 722 | ] 723 | }, 724 | "notification-url": "https://packagist.org/downloads/", 725 | "license": [ 726 | "MIT" 727 | ], 728 | "authors": [ 729 | { 730 | "name": "Michael Dowling", 731 | "email": "mtdowling@gmail.com", 732 | "homepage": "https://github.com/mtdowling" 733 | }, 734 | { 735 | "name": "Tobias Schultze", 736 | "homepage": "https://github.com/Tobion" 737 | } 738 | ], 739 | "description": "PSR-7 message implementation that also provides common utility methods", 740 | "keywords": [ 741 | "http", 742 | "message", 743 | "request", 744 | "response", 745 | "stream", 746 | "uri", 747 | "url" 748 | ], 749 | "time": "2017-10-07T03:19:56+00:00" 750 | }, 751 | { 752 | "name": "instaclick/php-webdriver", 753 | "version": "1.4.5", 754 | "source": { 755 | "type": "git", 756 | "url": "https://github.com/instaclick/php-webdriver.git", 757 | "reference": "6fa959452e774dcaed543faad3a9d1a37d803327" 758 | }, 759 | "dist": { 760 | "type": "zip", 761 | "url": "https://api.github.com/repos/instaclick/php-webdriver/zipball/6fa959452e774dcaed543faad3a9d1a37d803327", 762 | "reference": "6fa959452e774dcaed543faad3a9d1a37d803327", 763 | "shasum": "" 764 | }, 765 | "require": { 766 | "ext-curl": "*", 767 | "php": ">=5.3.2" 768 | }, 769 | "require-dev": { 770 | "phpunit/phpunit": "^4.8", 771 | "satooshi/php-coveralls": "^1.0||^2.0" 772 | }, 773 | "type": "library", 774 | "extra": { 775 | "branch-alias": { 776 | "dev-master": "1.4.x-dev" 777 | } 778 | }, 779 | "autoload": { 780 | "psr-0": { 781 | "WebDriver": "lib/" 782 | } 783 | }, 784 | "notification-url": "https://packagist.org/downloads/", 785 | "license": [ 786 | "Apache-2.0" 787 | ], 788 | "authors": [ 789 | { 790 | "name": "Justin Bishop", 791 | "email": "jubishop@gmail.com", 792 | "role": "Developer" 793 | }, 794 | { 795 | "name": "Anthon Pang", 796 | "email": "apang@softwaredevelopment.ca", 797 | "role": "Fork Maintainer" 798 | } 799 | ], 800 | "description": "PHP WebDriver for Selenium 2", 801 | "homepage": "http://instaclick.com/", 802 | "keywords": [ 803 | "browser", 804 | "selenium", 805 | "webdriver", 806 | "webtest" 807 | ], 808 | "time": "2017-06-30T04:02:48+00:00" 809 | }, 810 | { 811 | "name": "ocramius/package-versions", 812 | "version": "1.3.0", 813 | "source": { 814 | "type": "git", 815 | "url": "https://github.com/Ocramius/PackageVersions.git", 816 | "reference": "4489d5002c49d55576fa0ba786f42dbb009be46f" 817 | }, 818 | "dist": { 819 | "type": "zip", 820 | "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/4489d5002c49d55576fa0ba786f42dbb009be46f", 821 | "reference": "4489d5002c49d55576fa0ba786f42dbb009be46f", 822 | "shasum": "" 823 | }, 824 | "require": { 825 | "composer-plugin-api": "^1.0.0", 826 | "php": "^7.1.0" 827 | }, 828 | "require-dev": { 829 | "composer/composer": "^1.6.3", 830 | "ext-zip": "*", 831 | "infection/infection": "^0.7.1", 832 | "phpunit/phpunit": "^7.0.0" 833 | }, 834 | "type": "composer-plugin", 835 | "extra": { 836 | "class": "PackageVersions\\Installer", 837 | "branch-alias": { 838 | "dev-master": "2.0.x-dev" 839 | } 840 | }, 841 | "autoload": { 842 | "psr-4": { 843 | "PackageVersions\\": "src/PackageVersions" 844 | } 845 | }, 846 | "notification-url": "https://packagist.org/downloads/", 847 | "license": [ 848 | "MIT" 849 | ], 850 | "authors": [ 851 | { 852 | "name": "Marco Pivetta", 853 | "email": "ocramius@gmail.com" 854 | } 855 | ], 856 | "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", 857 | "time": "2018-02-05T13:05:30+00:00" 858 | }, 859 | { 860 | "name": "ocramius/proxy-manager", 861 | "version": "2.0.4", 862 | "source": { 863 | "type": "git", 864 | "url": "https://github.com/Ocramius/ProxyManager.git", 865 | "reference": "a55d08229f4f614bf335759ed0cf63378feeb2e6" 866 | }, 867 | "dist": { 868 | "type": "zip", 869 | "url": "https://api.github.com/repos/Ocramius/ProxyManager/zipball/a55d08229f4f614bf335759ed0cf63378feeb2e6", 870 | "reference": "a55d08229f4f614bf335759ed0cf63378feeb2e6", 871 | "shasum": "" 872 | }, 873 | "require": { 874 | "ocramius/package-versions": "^1.0", 875 | "php": "7.0.0 - 7.0.5 || ^7.0.7", 876 | "zendframework/zend-code": "3.0.0 - 3.0.2 || ^3.0.4" 877 | }, 878 | "require-dev": { 879 | "couscous/couscous": "^1.4.0", 880 | "ext-phar": "*", 881 | "phpbench/phpbench": "^0.11.2", 882 | "phpunit/phpunit": "^5.4.6", 883 | "squizlabs/php_codesniffer": "^2.6.0" 884 | }, 885 | "suggest": { 886 | "ocramius/generated-hydrator": "To have very fast object to array to object conversion for ghost objects", 887 | "zendframework/zend-json": "To have the JsonRpc adapter (Remote Object feature)", 888 | "zendframework/zend-soap": "To have the Soap adapter (Remote Object feature)", 889 | "zendframework/zend-xmlrpc": "To have the XmlRpc adapter (Remote Object feature)" 890 | }, 891 | "type": "library", 892 | "extra": { 893 | "branch-alias": { 894 | "dev-master": "3.0.x-dev" 895 | } 896 | }, 897 | "autoload": { 898 | "psr-0": { 899 | "ProxyManager\\": "src" 900 | } 901 | }, 902 | "notification-url": "https://packagist.org/downloads/", 903 | "license": [ 904 | "MIT" 905 | ], 906 | "authors": [ 907 | { 908 | "name": "Marco Pivetta", 909 | "email": "ocramius@gmail.com", 910 | "homepage": "http://ocramius.github.io/" 911 | } 912 | ], 913 | "description": "A library providing utilities to generate, instantiate and generally operate with Object Proxies", 914 | "homepage": "https://github.com/Ocramius/ProxyManager", 915 | "keywords": [ 916 | "aop", 917 | "lazy loading", 918 | "proxy", 919 | "proxy pattern", 920 | "service proxies" 921 | ], 922 | "time": "2016-11-04T15:53:15+00:00" 923 | }, 924 | { 925 | "name": "paulgibbs/behat-wordpress-extension", 926 | "version": "dev-185-path-fix", 927 | "source": { 928 | "type": "git", 929 | "url": "https://github.com/paulgibbs/behat-wordpress-extension.git", 930 | "reference": "6dd7b709a321e396c98f6237def0b1f8cb9e156a" 931 | }, 932 | "dist": { 933 | "type": "zip", 934 | "url": "https://api.github.com/repos/paulgibbs/behat-wordpress-extension/zipball/6dd7b709a321e396c98f6237def0b1f8cb9e156a", 935 | "reference": "6dd7b709a321e396c98f6237def0b1f8cb9e156a", 936 | "shasum": "" 937 | }, 938 | "require": { 939 | "behat/behat": "~3.1", 940 | "behat/mink-extension": "v2.2", 941 | "ocramius/proxy-manager": "2.0.4", 942 | "php": "~7.0", 943 | "sensiolabs/behat-page-object-extension": "~2.1", 944 | "zendframework/zend-code": "3.1.0" 945 | }, 946 | "require-dev": { 947 | "behat/mink-goutte-driver": "^1.2", 948 | "behat/mink-selenium2-driver": "^1.3", 949 | "joomla-projects/selenium-server-standalone": "~3.5", 950 | "phing/phing": "~2.16", 951 | "phpstan/phpstan": "~0.9", 952 | "squizlabs/php_codesniffer": "~3.0", 953 | "wp-cli/wp-cli": "~1.5" 954 | }, 955 | "suggest": { 956 | "behat/mink-goutte-driver": "Headless Mink driver", 957 | "behat/mink-selenium2-driver": "JS-enabled Mink driver (requires Selenium2)" 958 | }, 959 | "type": "behat-extension", 960 | "autoload": { 961 | "psr-4": { 962 | "PaulGibbs\\WordpressBehatExtension\\": "src" 963 | }, 964 | "files": [ 965 | "src/Util/functions.php" 966 | ] 967 | }, 968 | "scripts": { 969 | "phpcs": [ 970 | "phpcs --standard=phpcs-ruleset.xml -p -s -v -n src --extensions=php" 971 | ], 972 | "phpcbf": [ 973 | "phpcbf --standard=phpcs-ruleset.xml -n src" 974 | ], 975 | "phpstan": [ 976 | "vendor/bin/phpstan analyse -c phpstan.neon --level=1 src" 977 | ], 978 | "commit": [ 979 | "@phpcs", 980 | "@phpstan" 981 | ] 982 | }, 983 | "license": [ 984 | "GPL-3.0-or-later" 985 | ], 986 | "authors": [ 987 | { 988 | "name": "Paul Gibbs", 989 | "email": "djpaul@gmail.com", 990 | "homepage": "http://byotos.com" 991 | } 992 | ], 993 | "description": "WordHat is a Behat extension, integrating Behat, Mink, and WordPress. It provides WordPress-specific functionality for common testing scenarios specific to WordPress sites.", 994 | "homepage": "https://wordhat.info", 995 | "keywords": [ 996 | "WordPress", 997 | "bdd", 998 | "behat", 999 | "extension", 1000 | "mink" 1001 | ], 1002 | "support": { 1003 | "source": "https://github.com/paulgibbs/behat-wordpress-extension/tree/185-path-fix", 1004 | "issues": "https://github.com/paulgibbs/behat-wordpress-extension/issues" 1005 | }, 1006 | "time": "2018-02-17T13:27:39+00:00" 1007 | }, 1008 | { 1009 | "name": "psr/container", 1010 | "version": "dev-master", 1011 | "source": { 1012 | "type": "git", 1013 | "url": "https://github.com/php-fig/container.git", 1014 | "reference": "2cc4a01788191489dc7459446ba832fa79a216a7" 1015 | }, 1016 | "dist": { 1017 | "type": "zip", 1018 | "url": "https://api.github.com/repos/php-fig/container/zipball/2cc4a01788191489dc7459446ba832fa79a216a7", 1019 | "reference": "2cc4a01788191489dc7459446ba832fa79a216a7", 1020 | "shasum": "" 1021 | }, 1022 | "require": { 1023 | "php": ">=5.3.0" 1024 | }, 1025 | "type": "library", 1026 | "extra": { 1027 | "branch-alias": { 1028 | "dev-master": "1.0.x-dev" 1029 | } 1030 | }, 1031 | "autoload": { 1032 | "psr-4": { 1033 | "Psr\\Container\\": "src/" 1034 | } 1035 | }, 1036 | "notification-url": "https://packagist.org/downloads/", 1037 | "license": [ 1038 | "MIT" 1039 | ], 1040 | "authors": [ 1041 | { 1042 | "name": "PHP-FIG", 1043 | "homepage": "http://www.php-fig.org/" 1044 | } 1045 | ], 1046 | "description": "Common Container Interface (PHP FIG PSR-11)", 1047 | "homepage": "https://github.com/php-fig/container", 1048 | "keywords": [ 1049 | "PSR-11", 1050 | "container", 1051 | "container-interface", 1052 | "container-interop", 1053 | "psr" 1054 | ], 1055 | "time": "2017-06-28T15:35:32+00:00" 1056 | }, 1057 | { 1058 | "name": "psr/http-message", 1059 | "version": "dev-master", 1060 | "source": { 1061 | "type": "git", 1062 | "url": "https://github.com/php-fig/http-message.git", 1063 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" 1064 | }, 1065 | "dist": { 1066 | "type": "zip", 1067 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", 1068 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", 1069 | "shasum": "" 1070 | }, 1071 | "require": { 1072 | "php": ">=5.3.0" 1073 | }, 1074 | "type": "library", 1075 | "extra": { 1076 | "branch-alias": { 1077 | "dev-master": "1.0.x-dev" 1078 | } 1079 | }, 1080 | "autoload": { 1081 | "psr-4": { 1082 | "Psr\\Http\\Message\\": "src/" 1083 | } 1084 | }, 1085 | "notification-url": "https://packagist.org/downloads/", 1086 | "license": [ 1087 | "MIT" 1088 | ], 1089 | "authors": [ 1090 | { 1091 | "name": "PHP-FIG", 1092 | "homepage": "http://www.php-fig.org/" 1093 | } 1094 | ], 1095 | "description": "Common interface for HTTP messages", 1096 | "homepage": "https://github.com/php-fig/http-message", 1097 | "keywords": [ 1098 | "http", 1099 | "http-message", 1100 | "psr", 1101 | "psr-7", 1102 | "request", 1103 | "response" 1104 | ], 1105 | "time": "2016-08-06T14:39:51+00:00" 1106 | }, 1107 | { 1108 | "name": "sensiolabs/behat-page-object-extension", 1109 | "version": "v2.1.0", 1110 | "source": { 1111 | "type": "git", 1112 | "url": "https://github.com/sensiolabs/BehatPageObjectExtension.git", 1113 | "reference": "bd2a34221ba65ea8c86d8e693992d718de03dbae" 1114 | }, 1115 | "dist": { 1116 | "type": "zip", 1117 | "url": "https://api.github.com/repos/sensiolabs/BehatPageObjectExtension/zipball/bd2a34221ba65ea8c86d8e693992d718de03dbae", 1118 | "reference": "bd2a34221ba65ea8c86d8e693992d718de03dbae", 1119 | "shasum": "" 1120 | }, 1121 | "require": { 1122 | "behat/behat": "^3.0.6", 1123 | "behat/mink": "^1.6", 1124 | "behat/mink-extension": "^2.0", 1125 | "ocramius/proxy-manager": "^1.0||^2.0", 1126 | "php": ">=5.3.0" 1127 | }, 1128 | "require-dev": { 1129 | "behat/mink-goutte-driver": "^1.0", 1130 | "bossa/phpspec2-expect": "^1.0.3||^2.0", 1131 | "fabpot/goutte": "^1.0.4||^2.0||^3.0", 1132 | "phpspec/phpspec": "^2.5||^3.0", 1133 | "symfony/filesystem": "^2.8||^3.0", 1134 | "symfony/process": "^2.8||^3.0", 1135 | "symfony/yaml": "^2.8||^3.0" 1136 | }, 1137 | "suggest": { 1138 | "bossa/phpspec2-expect": "Allows to use PHPSpec2 matchers in Behat context files" 1139 | }, 1140 | "type": "library", 1141 | "extra": { 1142 | "branch-alias": { 1143 | "dev-master": "2.0-dev" 1144 | } 1145 | }, 1146 | "autoload": { 1147 | "psr-0": { 1148 | "SensioLabs\\Behat\\PageObjectExtension\\": "src/" 1149 | } 1150 | }, 1151 | "notification-url": "https://packagist.org/downloads/", 1152 | "license": [ 1153 | "MIT" 1154 | ], 1155 | "authors": [ 1156 | { 1157 | "name": "Marcello Duarte", 1158 | "email": "mduarte@inviqa.com" 1159 | }, 1160 | { 1161 | "name": "Jakub Zalas", 1162 | "email": "jakub@zalas.pl" 1163 | } 1164 | ], 1165 | "description": "Page object extension for Behat", 1166 | "homepage": "https://github.com/sensiolabs/BehatPageObjectExtension", 1167 | "keywords": [ 1168 | "BDD", 1169 | "Behat", 1170 | "page" 1171 | ], 1172 | "time": "2017-05-22T14:16:06+00:00" 1173 | }, 1174 | { 1175 | "name": "symfony/browser-kit", 1176 | "version": "dev-master", 1177 | "source": { 1178 | "type": "git", 1179 | "url": "https://github.com/symfony/browser-kit.git", 1180 | "reference": "8f1614d00ff697fe9ab93820bd0d1d6579fd9f3b" 1181 | }, 1182 | "dist": { 1183 | "type": "zip", 1184 | "url": "https://api.github.com/repos/symfony/browser-kit/zipball/8f1614d00ff697fe9ab93820bd0d1d6579fd9f3b", 1185 | "reference": "8f1614d00ff697fe9ab93820bd0d1d6579fd9f3b", 1186 | "shasum": "" 1187 | }, 1188 | "require": { 1189 | "php": "^7.1.3", 1190 | "symfony/dom-crawler": "~3.4|~4.0" 1191 | }, 1192 | "require-dev": { 1193 | "symfony/css-selector": "~3.4|~4.0", 1194 | "symfony/process": "~3.4|~4.0" 1195 | }, 1196 | "suggest": { 1197 | "symfony/process": "" 1198 | }, 1199 | "type": "library", 1200 | "extra": { 1201 | "branch-alias": { 1202 | "dev-master": "4.1-dev" 1203 | } 1204 | }, 1205 | "autoload": { 1206 | "psr-4": { 1207 | "Symfony\\Component\\BrowserKit\\": "" 1208 | }, 1209 | "exclude-from-classmap": [ 1210 | "/Tests/" 1211 | ] 1212 | }, 1213 | "notification-url": "https://packagist.org/downloads/", 1214 | "license": [ 1215 | "MIT" 1216 | ], 1217 | "authors": [ 1218 | { 1219 | "name": "Fabien Potencier", 1220 | "email": "fabien@symfony.com" 1221 | }, 1222 | { 1223 | "name": "Symfony Community", 1224 | "homepage": "https://symfony.com/contributors" 1225 | } 1226 | ], 1227 | "description": "Symfony BrowserKit Component", 1228 | "homepage": "https://symfony.com", 1229 | "time": "2018-01-03T07:38:11+00:00" 1230 | }, 1231 | { 1232 | "name": "symfony/class-loader", 1233 | "version": "dev-master", 1234 | "source": { 1235 | "type": "git", 1236 | "url": "https://github.com/symfony/class-loader.git", 1237 | "reference": "2141b7653aca7407c80981371146a24da83a228c" 1238 | }, 1239 | "dist": { 1240 | "type": "zip", 1241 | "url": "https://api.github.com/repos/symfony/class-loader/zipball/2141b7653aca7407c80981371146a24da83a228c", 1242 | "reference": "2141b7653aca7407c80981371146a24da83a228c", 1243 | "shasum": "" 1244 | }, 1245 | "require": { 1246 | "php": "^5.5.9|>=7.0.8" 1247 | }, 1248 | "require-dev": { 1249 | "symfony/finder": "~2.8|~3.0|~4.0", 1250 | "symfony/polyfill-apcu": "~1.1" 1251 | }, 1252 | "suggest": { 1253 | "symfony/polyfill-apcu": "For using ApcClassLoader on HHVM" 1254 | }, 1255 | "type": "library", 1256 | "extra": { 1257 | "branch-alias": { 1258 | "dev-master": "3.4-dev" 1259 | } 1260 | }, 1261 | "autoload": { 1262 | "psr-4": { 1263 | "Symfony\\Component\\ClassLoader\\": "" 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 ClassLoader Component", 1284 | "homepage": "https://symfony.com", 1285 | "time": "2017-10-02T06:49:52+00:00" 1286 | }, 1287 | { 1288 | "name": "symfony/config", 1289 | "version": "3.4.x-dev", 1290 | "source": { 1291 | "type": "git", 1292 | "url": "https://github.com/symfony/config.git", 1293 | "reference": "05e10567b529476a006b00746c5f538f1636810e" 1294 | }, 1295 | "dist": { 1296 | "type": "zip", 1297 | "url": "https://api.github.com/repos/symfony/config/zipball/05e10567b529476a006b00746c5f538f1636810e", 1298 | "reference": "05e10567b529476a006b00746c5f538f1636810e", 1299 | "shasum": "" 1300 | }, 1301 | "require": { 1302 | "php": "^5.5.9|>=7.0.8", 1303 | "symfony/filesystem": "~2.8|~3.0|~4.0" 1304 | }, 1305 | "conflict": { 1306 | "symfony/dependency-injection": "<3.3", 1307 | "symfony/finder": "<3.3" 1308 | }, 1309 | "require-dev": { 1310 | "symfony/dependency-injection": "~3.3|~4.0", 1311 | "symfony/event-dispatcher": "~3.3|~4.0", 1312 | "symfony/finder": "~3.3|~4.0", 1313 | "symfony/yaml": "~3.0|~4.0" 1314 | }, 1315 | "suggest": { 1316 | "symfony/yaml": "To use the yaml reference dumper" 1317 | }, 1318 | "type": "library", 1319 | "extra": { 1320 | "branch-alias": { 1321 | "dev-master": "3.4-dev" 1322 | } 1323 | }, 1324 | "autoload": { 1325 | "psr-4": { 1326 | "Symfony\\Component\\Config\\": "" 1327 | }, 1328 | "exclude-from-classmap": [ 1329 | "/Tests/" 1330 | ] 1331 | }, 1332 | "notification-url": "https://packagist.org/downloads/", 1333 | "license": [ 1334 | "MIT" 1335 | ], 1336 | "authors": [ 1337 | { 1338 | "name": "Fabien Potencier", 1339 | "email": "fabien@symfony.com" 1340 | }, 1341 | { 1342 | "name": "Symfony Community", 1343 | "homepage": "https://symfony.com/contributors" 1344 | } 1345 | ], 1346 | "description": "Symfony Config Component", 1347 | "homepage": "https://symfony.com", 1348 | "time": "2018-02-14T10:03:57+00:00" 1349 | }, 1350 | { 1351 | "name": "symfony/console", 1352 | "version": "dev-master", 1353 | "source": { 1354 | "type": "git", 1355 | "url": "https://github.com/symfony/console.git", 1356 | "reference": "4de97e8d0ff6d4822f0b4d1486b63edf9028eac8" 1357 | }, 1358 | "dist": { 1359 | "type": "zip", 1360 | "url": "https://api.github.com/repos/symfony/console/zipball/4de97e8d0ff6d4822f0b4d1486b63edf9028eac8", 1361 | "reference": "4de97e8d0ff6d4822f0b4d1486b63edf9028eac8", 1362 | "shasum": "" 1363 | }, 1364 | "require": { 1365 | "php": "^7.1.3", 1366 | "symfony/polyfill-mbstring": "~1.0" 1367 | }, 1368 | "conflict": { 1369 | "symfony/dependency-injection": "<3.4", 1370 | "symfony/process": "<3.3" 1371 | }, 1372 | "require-dev": { 1373 | "psr/log": "~1.0", 1374 | "symfony/config": "~3.4|~4.0", 1375 | "symfony/dependency-injection": "~3.4|~4.0", 1376 | "symfony/event-dispatcher": "~3.4|~4.0", 1377 | "symfony/lock": "~3.4|~4.0", 1378 | "symfony/process": "~3.4|~4.0" 1379 | }, 1380 | "suggest": { 1381 | "psr/log": "For using the console logger", 1382 | "symfony/event-dispatcher": "", 1383 | "symfony/lock": "", 1384 | "symfony/process": "" 1385 | }, 1386 | "type": "library", 1387 | "extra": { 1388 | "branch-alias": { 1389 | "dev-master": "4.1-dev" 1390 | } 1391 | }, 1392 | "autoload": { 1393 | "psr-4": { 1394 | "Symfony\\Component\\Console\\": "" 1395 | }, 1396 | "exclude-from-classmap": [ 1397 | "/Tests/" 1398 | ] 1399 | }, 1400 | "notification-url": "https://packagist.org/downloads/", 1401 | "license": [ 1402 | "MIT" 1403 | ], 1404 | "authors": [ 1405 | { 1406 | "name": "Fabien Potencier", 1407 | "email": "fabien@symfony.com" 1408 | }, 1409 | { 1410 | "name": "Symfony Community", 1411 | "homepage": "https://symfony.com/contributors" 1412 | } 1413 | ], 1414 | "description": "Symfony Console Component", 1415 | "homepage": "https://symfony.com", 1416 | "time": "2018-02-09T15:48:09+00:00" 1417 | }, 1418 | { 1419 | "name": "symfony/css-selector", 1420 | "version": "dev-master", 1421 | "source": { 1422 | "type": "git", 1423 | "url": "https://github.com/symfony/css-selector.git", 1424 | "reference": "a77f0d8ddd26167edb45d702a20c2d502b09e8c4" 1425 | }, 1426 | "dist": { 1427 | "type": "zip", 1428 | "url": "https://api.github.com/repos/symfony/css-selector/zipball/a77f0d8ddd26167edb45d702a20c2d502b09e8c4", 1429 | "reference": "a77f0d8ddd26167edb45d702a20c2d502b09e8c4", 1430 | "shasum": "" 1431 | }, 1432 | "require": { 1433 | "php": "^7.1.3" 1434 | }, 1435 | "type": "library", 1436 | "extra": { 1437 | "branch-alias": { 1438 | "dev-master": "4.1-dev" 1439 | } 1440 | }, 1441 | "autoload": { 1442 | "psr-4": { 1443 | "Symfony\\Component\\CssSelector\\": "" 1444 | }, 1445 | "exclude-from-classmap": [ 1446 | "/Tests/" 1447 | ] 1448 | }, 1449 | "notification-url": "https://packagist.org/downloads/", 1450 | "license": [ 1451 | "MIT" 1452 | ], 1453 | "authors": [ 1454 | { 1455 | "name": "Jean-François Simon", 1456 | "email": "jeanfrancois.simon@sensiolabs.com" 1457 | }, 1458 | { 1459 | "name": "Fabien Potencier", 1460 | "email": "fabien@symfony.com" 1461 | }, 1462 | { 1463 | "name": "Symfony Community", 1464 | "homepage": "https://symfony.com/contributors" 1465 | } 1466 | ], 1467 | "description": "Symfony CssSelector Component", 1468 | "homepage": "https://symfony.com", 1469 | "time": "2018-02-03T14:58:56+00:00" 1470 | }, 1471 | { 1472 | "name": "symfony/dependency-injection", 1473 | "version": "dev-master", 1474 | "source": { 1475 | "type": "git", 1476 | "url": "https://github.com/symfony/dependency-injection.git", 1477 | "reference": "fa4cebb97bb6b9867c192f72c6a59ad93e46d3ea" 1478 | }, 1479 | "dist": { 1480 | "type": "zip", 1481 | "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/fa4cebb97bb6b9867c192f72c6a59ad93e46d3ea", 1482 | "reference": "fa4cebb97bb6b9867c192f72c6a59ad93e46d3ea", 1483 | "shasum": "" 1484 | }, 1485 | "require": { 1486 | "php": "^7.1.3", 1487 | "psr/container": "^1.0" 1488 | }, 1489 | "conflict": { 1490 | "symfony/config": "<3.4", 1491 | "symfony/finder": "<3.4", 1492 | "symfony/proxy-manager-bridge": "<3.4", 1493 | "symfony/yaml": "<3.4" 1494 | }, 1495 | "provide": { 1496 | "psr/container-implementation": "1.0" 1497 | }, 1498 | "require-dev": { 1499 | "symfony/config": "~3.4|~4.0", 1500 | "symfony/expression-language": "~3.4|~4.0", 1501 | "symfony/yaml": "~3.4|~4.0" 1502 | }, 1503 | "suggest": { 1504 | "symfony/config": "", 1505 | "symfony/expression-language": "For using expressions in service container configuration", 1506 | "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", 1507 | "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", 1508 | "symfony/yaml": "" 1509 | }, 1510 | "type": "library", 1511 | "extra": { 1512 | "branch-alias": { 1513 | "dev-master": "4.1-dev" 1514 | } 1515 | }, 1516 | "autoload": { 1517 | "psr-4": { 1518 | "Symfony\\Component\\DependencyInjection\\": "" 1519 | }, 1520 | "exclude-from-classmap": [ 1521 | "/Tests/" 1522 | ] 1523 | }, 1524 | "notification-url": "https://packagist.org/downloads/", 1525 | "license": [ 1526 | "MIT" 1527 | ], 1528 | "authors": [ 1529 | { 1530 | "name": "Fabien Potencier", 1531 | "email": "fabien@symfony.com" 1532 | }, 1533 | { 1534 | "name": "Symfony Community", 1535 | "homepage": "https://symfony.com/contributors" 1536 | } 1537 | ], 1538 | "description": "Symfony DependencyInjection Component", 1539 | "homepage": "https://symfony.com", 1540 | "time": "2018-02-14T14:11:22+00:00" 1541 | }, 1542 | { 1543 | "name": "symfony/dom-crawler", 1544 | "version": "dev-master", 1545 | "source": { 1546 | "type": "git", 1547 | "url": "https://github.com/symfony/dom-crawler.git", 1548 | "reference": "e2ed2b820e37d08454fe23bc30c70572eeb66580" 1549 | }, 1550 | "dist": { 1551 | "type": "zip", 1552 | "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/e2ed2b820e37d08454fe23bc30c70572eeb66580", 1553 | "reference": "e2ed2b820e37d08454fe23bc30c70572eeb66580", 1554 | "shasum": "" 1555 | }, 1556 | "require": { 1557 | "php": "^7.1.3", 1558 | "symfony/polyfill-mbstring": "~1.0" 1559 | }, 1560 | "require-dev": { 1561 | "symfony/css-selector": "~3.4|~4.0" 1562 | }, 1563 | "suggest": { 1564 | "symfony/css-selector": "" 1565 | }, 1566 | "type": "library", 1567 | "extra": { 1568 | "branch-alias": { 1569 | "dev-master": "4.1-dev" 1570 | } 1571 | }, 1572 | "autoload": { 1573 | "psr-4": { 1574 | "Symfony\\Component\\DomCrawler\\": "" 1575 | }, 1576 | "exclude-from-classmap": [ 1577 | "/Tests/" 1578 | ] 1579 | }, 1580 | "notification-url": "https://packagist.org/downloads/", 1581 | "license": [ 1582 | "MIT" 1583 | ], 1584 | "authors": [ 1585 | { 1586 | "name": "Fabien Potencier", 1587 | "email": "fabien@symfony.com" 1588 | }, 1589 | { 1590 | "name": "Symfony Community", 1591 | "homepage": "https://symfony.com/contributors" 1592 | } 1593 | ], 1594 | "description": "Symfony DomCrawler Component", 1595 | "homepage": "https://symfony.com", 1596 | "time": "2018-01-03T07:38:11+00:00" 1597 | }, 1598 | { 1599 | "name": "symfony/event-dispatcher", 1600 | "version": "dev-master", 1601 | "source": { 1602 | "type": "git", 1603 | "url": "https://github.com/symfony/event-dispatcher.git", 1604 | "reference": "59994ed23212494d0a7c2d4bd1b83a5490e25c16" 1605 | }, 1606 | "dist": { 1607 | "type": "zip", 1608 | "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/59994ed23212494d0a7c2d4bd1b83a5490e25c16", 1609 | "reference": "59994ed23212494d0a7c2d4bd1b83a5490e25c16", 1610 | "shasum": "" 1611 | }, 1612 | "require": { 1613 | "php": "^7.1.3" 1614 | }, 1615 | "conflict": { 1616 | "symfony/dependency-injection": "<3.4" 1617 | }, 1618 | "require-dev": { 1619 | "psr/log": "~1.0", 1620 | "symfony/config": "~3.4|~4.0", 1621 | "symfony/dependency-injection": "~3.4|~4.0", 1622 | "symfony/expression-language": "~3.4|~4.0", 1623 | "symfony/stopwatch": "~3.4|~4.0" 1624 | }, 1625 | "suggest": { 1626 | "symfony/dependency-injection": "", 1627 | "symfony/http-kernel": "" 1628 | }, 1629 | "type": "library", 1630 | "extra": { 1631 | "branch-alias": { 1632 | "dev-master": "4.1-dev" 1633 | } 1634 | }, 1635 | "autoload": { 1636 | "psr-4": { 1637 | "Symfony\\Component\\EventDispatcher\\": "" 1638 | }, 1639 | "exclude-from-classmap": [ 1640 | "/Tests/" 1641 | ] 1642 | }, 1643 | "notification-url": "https://packagist.org/downloads/", 1644 | "license": [ 1645 | "MIT" 1646 | ], 1647 | "authors": [ 1648 | { 1649 | "name": "Fabien Potencier", 1650 | "email": "fabien@symfony.com" 1651 | }, 1652 | { 1653 | "name": "Symfony Community", 1654 | "homepage": "https://symfony.com/contributors" 1655 | } 1656 | ], 1657 | "description": "Symfony EventDispatcher Component", 1658 | "homepage": "https://symfony.com", 1659 | "time": "2018-02-14T14:11:22+00:00" 1660 | }, 1661 | { 1662 | "name": "symfony/filesystem", 1663 | "version": "dev-master", 1664 | "source": { 1665 | "type": "git", 1666 | "url": "https://github.com/symfony/filesystem.git", 1667 | "reference": "94281d227ea7a154eb23c618d06c9c2ee76c1e59" 1668 | }, 1669 | "dist": { 1670 | "type": "zip", 1671 | "url": "https://api.github.com/repos/symfony/filesystem/zipball/94281d227ea7a154eb23c618d06c9c2ee76c1e59", 1672 | "reference": "94281d227ea7a154eb23c618d06c9c2ee76c1e59", 1673 | "shasum": "" 1674 | }, 1675 | "require": { 1676 | "php": "^7.1.3" 1677 | }, 1678 | "type": "library", 1679 | "extra": { 1680 | "branch-alias": { 1681 | "dev-master": "4.1-dev" 1682 | } 1683 | }, 1684 | "autoload": { 1685 | "psr-4": { 1686 | "Symfony\\Component\\Filesystem\\": "" 1687 | }, 1688 | "exclude-from-classmap": [ 1689 | "/Tests/" 1690 | ] 1691 | }, 1692 | "notification-url": "https://packagist.org/downloads/", 1693 | "license": [ 1694 | "MIT" 1695 | ], 1696 | "authors": [ 1697 | { 1698 | "name": "Fabien Potencier", 1699 | "email": "fabien@symfony.com" 1700 | }, 1701 | { 1702 | "name": "Symfony Community", 1703 | "homepage": "https://symfony.com/contributors" 1704 | } 1705 | ], 1706 | "description": "Symfony Filesystem Component", 1707 | "homepage": "https://symfony.com", 1708 | "time": "2018-01-03T07:38:11+00:00" 1709 | }, 1710 | { 1711 | "name": "symfony/polyfill-mbstring", 1712 | "version": "dev-master", 1713 | "source": { 1714 | "type": "git", 1715 | "url": "https://github.com/symfony/polyfill-mbstring.git", 1716 | "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b" 1717 | }, 1718 | "dist": { 1719 | "type": "zip", 1720 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b", 1721 | "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b", 1722 | "shasum": "" 1723 | }, 1724 | "require": { 1725 | "php": ">=5.3.3" 1726 | }, 1727 | "suggest": { 1728 | "ext-mbstring": "For best performance" 1729 | }, 1730 | "type": "library", 1731 | "extra": { 1732 | "branch-alias": { 1733 | "dev-master": "1.7-dev" 1734 | } 1735 | }, 1736 | "autoload": { 1737 | "psr-4": { 1738 | "Symfony\\Polyfill\\Mbstring\\": "" 1739 | }, 1740 | "files": [ 1741 | "bootstrap.php" 1742 | ] 1743 | }, 1744 | "notification-url": "https://packagist.org/downloads/", 1745 | "license": [ 1746 | "MIT" 1747 | ], 1748 | "authors": [ 1749 | { 1750 | "name": "Nicolas Grekas", 1751 | "email": "p@tchwork.com" 1752 | }, 1753 | { 1754 | "name": "Symfony Community", 1755 | "homepage": "https://symfony.com/contributors" 1756 | } 1757 | ], 1758 | "description": "Symfony polyfill for the Mbstring extension", 1759 | "homepage": "https://symfony.com", 1760 | "keywords": [ 1761 | "compatibility", 1762 | "mbstring", 1763 | "polyfill", 1764 | "portable", 1765 | "shim" 1766 | ], 1767 | "time": "2018-01-30T19:27:44+00:00" 1768 | }, 1769 | { 1770 | "name": "symfony/translation", 1771 | "version": "dev-master", 1772 | "source": { 1773 | "type": "git", 1774 | "url": "https://github.com/symfony/translation.git", 1775 | "reference": "b2256c134bb9e47d9a67397fe799629ad91f221b" 1776 | }, 1777 | "dist": { 1778 | "type": "zip", 1779 | "url": "https://api.github.com/repos/symfony/translation/zipball/b2256c134bb9e47d9a67397fe799629ad91f221b", 1780 | "reference": "b2256c134bb9e47d9a67397fe799629ad91f221b", 1781 | "shasum": "" 1782 | }, 1783 | "require": { 1784 | "php": "^7.1.3", 1785 | "symfony/polyfill-mbstring": "~1.0" 1786 | }, 1787 | "conflict": { 1788 | "symfony/config": "<3.4", 1789 | "symfony/dependency-injection": "<3.4", 1790 | "symfony/yaml": "<3.4" 1791 | }, 1792 | "require-dev": { 1793 | "psr/log": "~1.0", 1794 | "symfony/config": "~3.4|~4.0", 1795 | "symfony/dependency-injection": "~3.4|~4.0", 1796 | "symfony/finder": "~2.8|~3.0|~4.0", 1797 | "symfony/intl": "~3.4|~4.0", 1798 | "symfony/yaml": "~3.4|~4.0" 1799 | }, 1800 | "suggest": { 1801 | "psr/log": "To use logging capability in translator", 1802 | "symfony/config": "", 1803 | "symfony/yaml": "" 1804 | }, 1805 | "type": "library", 1806 | "extra": { 1807 | "branch-alias": { 1808 | "dev-master": "4.1-dev" 1809 | } 1810 | }, 1811 | "autoload": { 1812 | "psr-4": { 1813 | "Symfony\\Component\\Translation\\": "" 1814 | }, 1815 | "exclude-from-classmap": [ 1816 | "/Tests/" 1817 | ] 1818 | }, 1819 | "notification-url": "https://packagist.org/downloads/", 1820 | "license": [ 1821 | "MIT" 1822 | ], 1823 | "authors": [ 1824 | { 1825 | "name": "Fabien Potencier", 1826 | "email": "fabien@symfony.com" 1827 | }, 1828 | { 1829 | "name": "Symfony Community", 1830 | "homepage": "https://symfony.com/contributors" 1831 | } 1832 | ], 1833 | "description": "Symfony Translation Component", 1834 | "homepage": "https://symfony.com", 1835 | "time": "2018-02-15T08:01:21+00:00" 1836 | }, 1837 | { 1838 | "name": "symfony/yaml", 1839 | "version": "dev-master", 1840 | "source": { 1841 | "type": "git", 1842 | "url": "https://github.com/symfony/yaml.git", 1843 | "reference": "b33f2fbe7349704d2a06bacc5a15b1a4c94e468f" 1844 | }, 1845 | "dist": { 1846 | "type": "zip", 1847 | "url": "https://api.github.com/repos/symfony/yaml/zipball/b33f2fbe7349704d2a06bacc5a15b1a4c94e468f", 1848 | "reference": "b33f2fbe7349704d2a06bacc5a15b1a4c94e468f", 1849 | "shasum": "" 1850 | }, 1851 | "require": { 1852 | "php": "^7.1.3" 1853 | }, 1854 | "conflict": { 1855 | "symfony/console": "<3.4" 1856 | }, 1857 | "require-dev": { 1858 | "symfony/console": "~3.4|~4.0" 1859 | }, 1860 | "suggest": { 1861 | "symfony/console": "For validating YAML files using the lint command" 1862 | }, 1863 | "type": "library", 1864 | "extra": { 1865 | "branch-alias": { 1866 | "dev-master": "4.1-dev" 1867 | } 1868 | }, 1869 | "autoload": { 1870 | "psr-4": { 1871 | "Symfony\\Component\\Yaml\\": "" 1872 | }, 1873 | "exclude-from-classmap": [ 1874 | "/Tests/" 1875 | ] 1876 | }, 1877 | "notification-url": "https://packagist.org/downloads/", 1878 | "license": [ 1879 | "MIT" 1880 | ], 1881 | "authors": [ 1882 | { 1883 | "name": "Fabien Potencier", 1884 | "email": "fabien@symfony.com" 1885 | }, 1886 | { 1887 | "name": "Symfony Community", 1888 | "homepage": "https://symfony.com/contributors" 1889 | } 1890 | ], 1891 | "description": "Symfony Yaml Component", 1892 | "homepage": "https://symfony.com", 1893 | "time": "2018-02-11T17:18:00+00:00" 1894 | }, 1895 | { 1896 | "name": "zendframework/zend-code", 1897 | "version": "3.1.0", 1898 | "source": { 1899 | "type": "git", 1900 | "url": "https://github.com/zendframework/zend-code.git", 1901 | "reference": "2899c17f83a7207f2d7f53ec2f421204d3beea27" 1902 | }, 1903 | "dist": { 1904 | "type": "zip", 1905 | "url": "https://api.github.com/repos/zendframework/zend-code/zipball/2899c17f83a7207f2d7f53ec2f421204d3beea27", 1906 | "reference": "2899c17f83a7207f2d7f53ec2f421204d3beea27", 1907 | "shasum": "" 1908 | }, 1909 | "require": { 1910 | "php": "^5.6 || 7.0.0 - 7.0.4 || ^7.0.6", 1911 | "zendframework/zend-eventmanager": "^2.6 || ^3.0" 1912 | }, 1913 | "require-dev": { 1914 | "doctrine/annotations": "~1.0", 1915 | "ext-phar": "*", 1916 | "phpunit/phpunit": "^4.8.21", 1917 | "squizlabs/php_codesniffer": "^2.5", 1918 | "zendframework/zend-stdlib": "^2.7 || ^3.0" 1919 | }, 1920 | "suggest": { 1921 | "doctrine/annotations": "Doctrine\\Common\\Annotations >=1.0 for annotation features", 1922 | "zendframework/zend-stdlib": "Zend\\Stdlib component" 1923 | }, 1924 | "type": "library", 1925 | "extra": { 1926 | "branch-alias": { 1927 | "dev-master": "3.1-dev", 1928 | "dev-develop": "3.2-dev" 1929 | } 1930 | }, 1931 | "autoload": { 1932 | "psr-4": { 1933 | "Zend\\Code\\": "src/" 1934 | } 1935 | }, 1936 | "notification-url": "https://packagist.org/downloads/", 1937 | "license": [ 1938 | "BSD-3-Clause" 1939 | ], 1940 | "description": "provides facilities to generate arbitrary code using an object oriented interface", 1941 | "homepage": "https://github.com/zendframework/zend-code", 1942 | "keywords": [ 1943 | "code", 1944 | "zf2" 1945 | ], 1946 | "time": "2016-10-24T13:23:32+00:00" 1947 | }, 1948 | { 1949 | "name": "zendframework/zend-eventmanager", 1950 | "version": "dev-develop", 1951 | "source": { 1952 | "type": "git", 1953 | "url": "https://github.com/zendframework/zend-eventmanager.git", 1954 | "reference": "969821ae236411f1540fa9a0267246ef07b02189" 1955 | }, 1956 | "dist": { 1957 | "type": "zip", 1958 | "url": "https://api.github.com/repos/zendframework/zend-eventmanager/zipball/969821ae236411f1540fa9a0267246ef07b02189", 1959 | "reference": "969821ae236411f1540fa9a0267246ef07b02189", 1960 | "shasum": "" 1961 | }, 1962 | "require": { 1963 | "php": "^5.6 || ^7.0" 1964 | }, 1965 | "require-dev": { 1966 | "container-interop/container-interop": "^1.1.0", 1967 | "phpbench/phpbench": "^0.13", 1968 | "phpunit/phpunit": "^6.0.7 || ^5.7.14", 1969 | "zendframework/zend-coding-standard": "~1.0.0", 1970 | "zendframework/zend-stdlib": "^2.7.3 || ^3.0" 1971 | }, 1972 | "suggest": { 1973 | "container-interop/container-interop": "^1.1.0, to use the lazy listeners feature", 1974 | "zendframework/zend-stdlib": "^2.7.3 || ^3.0, to use the FilterChain feature" 1975 | }, 1976 | "type": "library", 1977 | "extra": { 1978 | "branch-alias": { 1979 | "dev-master": "3.2-dev", 1980 | "dev-develop": "3.3-dev" 1981 | } 1982 | }, 1983 | "autoload": { 1984 | "psr-4": { 1985 | "Zend\\EventManager\\": "src/" 1986 | } 1987 | }, 1988 | "notification-url": "https://packagist.org/downloads/", 1989 | "license": [ 1990 | "BSD-3-Clause" 1991 | ], 1992 | "description": "Trigger and listen to events within a PHP application", 1993 | "homepage": "https://github.com/zendframework/zend-eventmanager", 1994 | "keywords": [ 1995 | "event", 1996 | "eventmanager", 1997 | "events", 1998 | "zf2" 1999 | ], 2000 | "time": "2017-10-09T10:07:30+00:00" 2001 | } 2002 | ], 2003 | "aliases": [], 2004 | "minimum-stability": "dev", 2005 | "stability-flags": { 2006 | "behat/mink-goutte-driver": 20, 2007 | "behat/mink-selenium2-driver": 20, 2008 | "paulgibbs/behat-wordpress-extension": 20 2009 | }, 2010 | "prefer-stable": false, 2011 | "prefer-lowest": false, 2012 | "platform": { 2013 | "php": ">=7.1" 2014 | }, 2015 | "platform-dev": [] 2016 | } 2017 | -------------------------------------------------------------------------------- /devrel-gutes.backstop-config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BackstopReferenceBaseUrl = 'https://auto-update-devrel-gutes.pantheonsite.io/'; 4 | const BackstopTestUrl = 'https://dev-devrel-gutes.pantheonsite.io/'; 5 | 6 | const simple_scenarios_paths = [ 7 | "/gutenberg-demo-post/", 8 | "/marky-markdown/", 9 | "/next-year-in-nashville/", 10 | "/the-wordcamp-us-live-demo/", 11 | "/tips-for-theming-with-gutenberg/", 12 | "/modernizing-wordpress-javascript/", 13 | "/welcome-to-the-gutenberg-editor-2/", 14 | ]; 15 | 16 | const config = { 17 | "id": "backstop_default", 18 | "viewports": [ 19 | { 20 | "name": "phone", 21 | "width": 320, 22 | "height": 480 23 | }, 24 | { 25 | "name": "tablet_v", 26 | "width": 568, 27 | "height": 1024 28 | }, 29 | { 30 | "name": "tablet_h", 31 | "width": 1024, 32 | "height": 768 33 | }, 34 | { 35 | "name": "desktop", 36 | "width": 1920, 37 | "height": 1080 38 | } 39 | ], 40 | "scenarios": [ 41 | { 42 | "label": "Homepage", 43 | "url": BackstopTestUrl, 44 | "referenceUrl": BackstopReferenceBaseUrl, 45 | "hideSelectors": [ 46 | ".wp-block-embed.is-provider-vimeo", 47 | ], 48 | "selectors": [ 49 | "document", 50 | ], 51 | "readyEvent": null, 52 | "delay": 1500, 53 | "misMatchThreshold": 0.1 54 | } 55 | ], 56 | "paths": { 57 | "bitmaps_reference": "backstop_data/bitmaps_reference", 58 | "bitmaps_test": "backstop_data/bitmaps_test", 59 | "compare_data": "backstop_data/bitmaps_test/compare.json", 60 | "casper_scripts": "backstop_data/casper_scripts" 61 | }, 62 | "engine": "chrome", 63 | "report": [ "CLI" ], 64 | "casperFlags": [], 65 | "debug": false, 66 | "port": 3001 67 | } 68 | 69 | 70 | const simple_scenarios = simple_scenarios_paths.map(function(path) { 71 | 72 | return { 73 | "label": path, 74 | "url": BackstopTestUrl + path, 75 | "referenceUrl":BackstopReferenceBaseUrl + path, 76 | "hideSelectors": [ 77 | ".wp-block-embed.is-provider-vimeo", 78 | ], 79 | "selectors": [ 80 | "document", 81 | ], 82 | "readyEvent": null, 83 | "delay": 1500, 84 | "misMatchThreshold": 0.1 85 | } 86 | }); 87 | 88 | config.scenarios = config.scenarios.concat(simple_scenarios); 89 | 90 | module.exports = config; 91 | -------------------------------------------------------------------------------- /review-signal-pantheon-elite-test-site.backstop-config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BackstopReferenceBaseUrl = 'https://auto-update-review-signal-pantheon-elite-test-site.pantheonsite.io/'; 4 | const BackstopTestUrl = 'https://live-review-signal-pantheon-elite-test-site.pantheonsite.io/'; 5 | 6 | const simple_scenarios_paths = [ 7 | // Single pages 8 | "/contact-us/", 9 | "/about/", 10 | "/hipster/", 11 | "/bacon/", 12 | // Single post 13 | "/2016/04/30/hello-world/", 14 | // Date archive 15 | "/2016/04/", 16 | // Category archive 17 | "/category/uncategorized/", 18 | ]; 19 | 20 | const config = { 21 | "id": "backstop_default", 22 | "viewports": [ 23 | { 24 | "name": "phone", 25 | "width": 320, 26 | "height": 480 27 | }, 28 | { 29 | "name": "tablet_v", 30 | "width": 568, 31 | "height": 1024 32 | }, 33 | { 34 | "name": "tablet_h", 35 | "width": 1024, 36 | "height": 768 37 | }, 38 | { 39 | "name": "desktop", 40 | "width": 1920, 41 | "height": 1080 42 | } 43 | ], 44 | "scenarios": [ 45 | { 46 | "label": "Homepage", 47 | "url": BackstopTestUrl, 48 | "referenceUrl": BackstopReferenceBaseUrl, 49 | "hideSelectors": [ 50 | ".wp-block-embed.is-provider-vimeo", 51 | ], 52 | "selectors": [ 53 | "document", 54 | ], 55 | "readyEvent": null, 56 | "delay": 1500, 57 | "misMatchThreshold": 0.1 58 | } 59 | ], 60 | "paths": { 61 | "bitmaps_reference": "backstop_data/bitmaps_reference", 62 | "bitmaps_test": "backstop_data/bitmaps_test", 63 | "compare_data": "backstop_data/bitmaps_test/compare.json", 64 | "casper_scripts": "backstop_data/casper_scripts" 65 | }, 66 | "engine": "chrome", 67 | "report": [ "CLI" ], 68 | "casperFlags": [], 69 | "debug": false, 70 | "port": 3001 71 | } 72 | 73 | 74 | const simple_scenarios = simple_scenarios_paths.map(function(path) { 75 | 76 | return { 77 | "label": path, 78 | "url": BackstopTestUrl + path, 79 | "referenceUrl":BackstopReferenceBaseUrl + path, 80 | "hideSelectors": [ 81 | ".wp-block-embed.is-provider-vimeo", 82 | ], 83 | "selectors": [ 84 | "document", 85 | ], 86 | "readyEvent": null, 87 | "delay": 1500, 88 | "misMatchThreshold": 0.1 89 | } 90 | }); 91 | 92 | config.scenarios = config.scenarios.concat(simple_scenarios); 93 | 94 | module.exports = config; 95 | -------------------------------------------------------------------------------- /review-signal-pantheon-personal-test-site.backstop-config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BackstopReferenceBaseUrl = 'https://auto-update-review-signal-pantheon-personal-test-site.pantheonsite.io/'; 4 | const BackstopTestUrl = 'https://live-review-signal-pantheon-personal-test-site.pantheonsite.io/'; 5 | 6 | const simple_scenarios_paths = [ 7 | // Single pages 8 | "/setup-instructions/", 9 | "/load-testing/", 10 | "/uptime-monitoring/", 11 | "/other-tools/", 12 | // Single post 13 | "/2016/04/30/review-signal-wordpress-hosting-performance-benchmarks/", 14 | // Date archive 15 | "/2016/04/", 16 | // Category archive 17 | "/category/uncategorized/", 18 | ]; 19 | 20 | const config = { 21 | "id": "backstop_default", 22 | "viewports": [ 23 | { 24 | "name": "phone", 25 | "width": 320, 26 | "height": 480 27 | }, 28 | { 29 | "name": "tablet_v", 30 | "width": 568, 31 | "height": 1024 32 | }, 33 | { 34 | "name": "tablet_h", 35 | "width": 1024, 36 | "height": 768 37 | }, 38 | { 39 | "name": "desktop", 40 | "width": 1920, 41 | "height": 1080 42 | } 43 | ], 44 | "scenarios": [ 45 | { 46 | "label": "Homepage", 47 | "url": BackstopTestUrl, 48 | "referenceUrl": BackstopReferenceBaseUrl, 49 | "hideSelectors": [ 50 | ".wp-block-embed.is-provider-vimeo", 51 | ], 52 | "selectors": [ 53 | "document", 54 | ], 55 | "readyEvent": null, 56 | "delay": 1500, 57 | "misMatchThreshold": 0.1 58 | } 59 | ], 60 | "paths": { 61 | "bitmaps_reference": "backstop_data/bitmaps_reference", 62 | "bitmaps_test": "backstop_data/bitmaps_test", 63 | "compare_data": "backstop_data/bitmaps_test/compare.json", 64 | "casper_scripts": "backstop_data/casper_scripts" 65 | }, 66 | "engine": "chrome", 67 | "report": [ "CLI" ], 68 | "casperFlags": [], 69 | "debug": false, 70 | "port": 3001 71 | } 72 | 73 | 74 | const simple_scenarios = simple_scenarios_paths.map(function(path) { 75 | 76 | return { 77 | "label": path, 78 | "url": BackstopTestUrl + path, 79 | "referenceUrl":BackstopReferenceBaseUrl + path, 80 | "hideSelectors": [ 81 | ".wp-block-embed.is-provider-vimeo", 82 | ], 83 | "selectors": [ 84 | "document", 85 | ], 86 | "readyEvent": null, 87 | "delay": 1500, 88 | "misMatchThreshold": 0.1 89 | } 90 | }); 91 | 92 | config.scenarios = config.scenarios.concat(simple_scenarios); 93 | 94 | module.exports = config; 95 | -------------------------------------------------------------------------------- /review-signal-pantheon-professional-test-site.backstop-config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BackstopReferenceBaseUrl = 'https://auto-update-review-signal-pantheon-professional-test-site.pantheonsite.io/'; 4 | const BackstopTestUrl = 'https://live-review-signal-pantheon-professional-test-site.pantheonsite.io/'; 5 | 6 | const simple_scenarios_paths = [ 7 | // Single pages 8 | "/setup-instructions/", 9 | "/load-testing/", 10 | "/uptime-monitoring/", 11 | "/other-tools/", 12 | // Single post 13 | "/2016/04/30/review-signal-wordpress-hosting-performance-benchmarks/", 14 | // Date archive 15 | "/2016/04/", 16 | // Category archive 17 | "/category/uncategorized/", 18 | ]; 19 | 20 | const config = { 21 | "id": "backstop_default", 22 | "viewports": [ 23 | { 24 | "name": "phone", 25 | "width": 320, 26 | "height": 480 27 | }, 28 | { 29 | "name": "tablet_v", 30 | "width": 568, 31 | "height": 1024 32 | }, 33 | { 34 | "name": "tablet_h", 35 | "width": 1024, 36 | "height": 768 37 | }, 38 | { 39 | "name": "desktop", 40 | "width": 1920, 41 | "height": 1080 42 | } 43 | ], 44 | "scenarios": [ 45 | { 46 | "label": "Homepage", 47 | "url": BackstopTestUrl, 48 | "referenceUrl": BackstopReferenceBaseUrl, 49 | "hideSelectors": [ 50 | ".wp-block-embed.is-provider-vimeo", 51 | ], 52 | "selectors": [ 53 | "document", 54 | ], 55 | "readyEvent": null, 56 | "delay": 1500, 57 | "misMatchThreshold": 0.1 58 | } 59 | ], 60 | "paths": { 61 | "bitmaps_reference": "backstop_data/bitmaps_reference", 62 | "bitmaps_test": "backstop_data/bitmaps_test", 63 | "compare_data": "backstop_data/bitmaps_test/compare.json", 64 | "casper_scripts": "backstop_data/casper_scripts" 65 | }, 66 | "engine": "chrome", 67 | "report": [ "CLI" ], 68 | "casperFlags": [], 69 | "debug": false, 70 | "port": 3001 71 | } 72 | 73 | 74 | const simple_scenarios = simple_scenarios_paths.map(function(path) { 75 | 76 | return { 77 | "label": path, 78 | "url": BackstopTestUrl + path, 79 | "referenceUrl":BackstopReferenceBaseUrl + path, 80 | "hideSelectors": [ 81 | ".wp-block-embed.is-provider-vimeo", 82 | ], 83 | "selectors": [ 84 | "document", 85 | ], 86 | "readyEvent": null, 87 | "delay": 1500, 88 | "misMatchThreshold": 0.1 89 | } 90 | }); 91 | 92 | config.scenarios = config.scenarios.concat(simple_scenarios); 93 | 94 | module.exports = config; 95 | -------------------------------------------------------------------------------- /sites-to-auto-update.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "SITE_UUID": "9d8e680f-bbc2-4da5-a6eb-9b6192c57454", 4 | "SITE_NAME": "drupalcon-nashville-demo", 5 | "CREATE_BACKUPS": 1, 6 | "RECREATE_MULTIDEV": 1, 7 | "LIVE_URL": 0 8 | } 9 | ] 10 | -------------------------------------------------------------------------------- /solr-power-demo.backstop.json: -------------------------------------------------------------------------------- 1 | { 2 | "viewports": [ 3 | { 4 | "name": "phone", 5 | "width": 320, 6 | "height": 480 7 | }, 8 | { 9 | "name": "tablet_v", 10 | "width": 568, 11 | "height": 1024 12 | }, 13 | { 14 | "name": "tablet_h", 15 | "width": 1024, 16 | "height": 768 17 | }, 18 | { 19 | "name": "desktop", 20 | "width": 1920, 21 | "height": 1080 22 | } 23 | ], 24 | "scenarios": [ 25 | { 26 | "label": "/", 27 | "url": "https://live-solr-power.pantheonsite.io/", 28 | "referenceUrl": "https://auto-update-solr-power.pantheonsite.io", 29 | "hideSelectors": [], 30 | "selectors": [ 31 | "document" 32 | ], 33 | "readyEvent": null, 34 | "delay": 1500, 35 | "misMatchThreshold": 0.1 36 | }, 37 | { 38 | "label": "/hello-world/", 39 | "url": "https://live-solr-power.pantheonsite.io/hello-world/", 40 | "referenceUrl": "https://auto-update-solr-power.pantheonsite.io/hello-world/", 41 | "hideSelectors": [], 42 | "selectors": [ 43 | "document" 44 | ], 45 | "readyEvent": null, 46 | "delay": 1500, 47 | "misMatchThreshold": 0.1 48 | }, 49 | { 50 | "label": "/author/ataylor/", 51 | "url": "https://live-solr-power.pantheonsite.io/author/ataylor/", 52 | "referenceUrl": "https://auto-update-solr-power.pantheonsite.io/author/ataylor/", 53 | "hideSelectors": [], 54 | "selectors": [ 55 | "document" 56 | ], 57 | "readyEvent": null, 58 | "delay": 1500, 59 | "misMatchThreshold": 0.1 60 | }, 61 | { 62 | "label": "/category/uncategorized/", 63 | "url": "https://live-solr-power.pantheonsite.io/category/uncategorized/", 64 | "referenceUrl": "https://auto-update-solr-power.pantheonsite.io/category/uncategorized/", 65 | "hideSelectors": [], 66 | "selectors": [ 67 | "document" 68 | ], 69 | "readyEvent": null, 70 | "delay": 1500, 71 | "misMatchThreshold": 0.1 72 | }, 73 | { 74 | "label": "/hello-world/?replytocom=1", 75 | "url": "https://live-solr-power.pantheonsite.io/hello-world/?replytocom=1", 76 | "referenceUrl": "https://auto-update-solr-power.pantheonsite.io/hello-world/?replytocom=1", 77 | "hideSelectors": [], 78 | "selectors": [ 79 | "document" 80 | ], 81 | "readyEvent": null, 82 | "delay": 1500, 83 | "misMatchThreshold": 0.1 84 | } 85 | ], 86 | "paths": { 87 | "bitmaps_reference": "backstop_data/bitmaps_reference", 88 | "bitmaps_test": "backstop_data/bitmaps_test", 89 | "compare_data": "backstop_data/bitmaps_test/compare.json", 90 | "casper_scripts": "backstop_data/casper_scripts" 91 | }, 92 | "engine": "chrome", 93 | "report": [ 94 | "CLI" 95 | ], 96 | "casperFlags": [], 97 | "debug": false, 98 | "port": 3001 99 | } 100 | -------------------------------------------------------------------------------- /tests/behat/behat-pantheon.yml: -------------------------------------------------------------------------------- 1 | # behat.yml 2 | default: 3 | suites: 4 | default: 5 | paths: 6 | - ./ 7 | contexts: 8 | - PaulGibbs\WordpressBehatExtension\Context\WordpressContext 9 | - Behat\MinkExtension\Context\MinkContext 10 | - PaulGibbs\WordpressBehatExtension\Context\ContentContext 11 | - PaulGibbs\WordpressBehatExtension\Context\DashboardContext 12 | - PaulGibbs\WordpressBehatExtension\Context\SiteContext 13 | - PaulGibbs\WordpressBehatExtension\Context\UserContext 14 | - PaulGibbs\WordpressBehatExtension\Context\EditPostContext 15 | - PaulGibbs\WordpressBehatExtension\Context\WidgetContext 16 | - PaulGibbs\WordpressBehatExtension\Context\ToolbarContext 17 | 18 | extensions: 19 | Behat\MinkExtension: 20 | # base_url set by ENV 21 | browser_name: chrome 22 | default_session: default 23 | javascript_session: selenium2 24 | sessions: 25 | default: 26 | goutte: 27 | guzzle_parameters: 28 | verify: false # Allow self-signed SSL certificates 29 | selenium2: 30 | selenium2: ~ 31 | 32 | PaulGibbs\WordpressBehatExtension: 33 | # WordPress username/password and site_url set by ENV 34 | default_driver: wpcli 35 | -------------------------------------------------------------------------------- /tests/behat/wp-microsite/features/admin-login.feature: -------------------------------------------------------------------------------- 1 | Feature: Login as an administrator (no-js) 2 | As a maintainer of the site 3 | I want basic login behavior to work 4 | So that I can administer the site 5 | 6 | Scenario: Confirm access to create users 7 | Given I am logged in as an admin 8 | When I am on the dashboard 9 | And I go to the menu "Users > Add New" 10 | Then I should see "Add New User" 11 | -------------------------------------------------------------------------------- /tests/behat/wp-quicksilver-demo/features/admin-login.feature: -------------------------------------------------------------------------------- 1 | Feature: Login as an administrator (no-js) 2 | As a maintainer of the site 3 | I want basic login behavior to work 4 | So that I can administer the site 5 | 6 | Scenario: Confirm access to create users 7 | Given I am logged in as an admin 8 | When I am on the dashboard 9 | And I go to the menu "Users > Add New" 10 | Then I should see "Add New User" 11 | -------------------------------------------------------------------------------- /wp-new-relic-demo.backstop-config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BackstopReferenceBaseUrl = 'https://auto-update-wp-new-relic-demo.pantheonsite.io/'; 4 | const BackstopTestUrl = 'https://live-wp-new-relic-demo.pantheonsite.io/'; 5 | 6 | const simple_scenarios_paths = [ 7 | "/top-25", 8 | "/hello-world", 9 | "/product-category/accessories", 10 | "/product-category/action-reflex-games", 11 | "/product-category/action-figures", 12 | "/product/medium-cleaner-kit-plastic", 13 | "/product/hair-red-bikini", 14 | "/product/black-egg", 15 | ]; 16 | 17 | const config = { 18 | "id": "backstop_default", 19 | "viewports": [ 20 | { 21 | "name": "phone", 22 | "width": 320, 23 | "height": 480 24 | }, 25 | { 26 | "name": "tablet_v", 27 | "width": 568, 28 | "height": 1024 29 | }, 30 | { 31 | "name": "tablet_h", 32 | "width": 1024, 33 | "height": 768 34 | }, 35 | { 36 | "name": "desktop", 37 | "width": 1920, 38 | "height": 1080 39 | } 40 | ], 41 | "scenarios": [ 42 | { 43 | "label": "Homepage", 44 | "url": BackstopTestUrl, 45 | "referenceUrl": BackstopReferenceBaseUrl, 46 | "hideSelectors": [], 47 | "selectors": ["document"], 48 | "readyEvent": null, 49 | "delay": 1500, 50 | "misMatchThreshold": 0.1 51 | } 52 | ], 53 | "paths": { 54 | "bitmaps_reference": "backstop_data/bitmaps_reference", 55 | "bitmaps_test": "backstop_data/bitmaps_test", 56 | "compare_data": "backstop_data/bitmaps_test/compare.json", 57 | "casper_scripts": "backstop_data/casper_scripts" 58 | }, 59 | "engine": "chrome", 60 | "report": [ "CLI" ], 61 | "casperFlags": [], 62 | "debug": false, 63 | "port": 3001 64 | } 65 | 66 | 67 | const simple_scenarios = simple_scenarios_paths.map(function(path) { 68 | 69 | return { 70 | "label": path, 71 | "url": BackstopTestUrl + path, 72 | "referenceUrl":BackstopReferenceBaseUrl + path, 73 | "hideSelectors": [], 74 | "selectors": ["document"], 75 | "readyEvent": null, 76 | "delay": 1500, 77 | "misMatchThreshold": 0.1 78 | } 79 | }); 80 | 81 | config.scenarios = config.scenarios.concat(simple_scenarios); 82 | 83 | module.exports = config; 84 | --------------------------------------------------------------------------------