From bdab263673af9b73b9727cd4f75bf2d7f4e91b8c Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 2 Jul 2019 14:37:16 +0200 Subject: [PATCH] Begin with some E2E Tests (#2708) --- .eslintrc | 16 +- .travis.yml | 16 +- bin/bootstrap-env.sh | 12 - bin/local-env/docker-compose.yml | 43 ++ bin/{ => local-env}/includes.sh | 0 bin/local-env/install-composer.sh | 41 ++ bin/{ => local-env}/install-node-nvm.sh | 10 +- bin/{ => local-env}/install-wordpress.sh | 58 +-- .../launch-containers.sh} | 18 +- bin/local-env/start.sh | 65 ++++ bin/local-env/stop.sh | 26 ++ bin/reset-e2e-tests.sh | 7 - bin/setup-local-env.sh | 39 -- contributing.md | 211 ++++++++-- docker-compose.yml | 95 ----- includes/class-amp-autoloader.php | 4 +- jest-puppeteer.config.js | 7 + package.json | 12 +- tests/e2e/config/bootstrap.js | 142 +++++++ tests/e2e/jest.config.js | 22 +- tests/e2e/specs/amp-options.test.js | 134 +++++++ tests/e2e/specs/demo.test.js | 45 --- tests/e2e/specs/hello.test.js | 14 + tests/e2e/specs/stories-admin-pointer.test.js | 14 + tests/{unit => js}/jest.config.js | 2 +- tests/{unit => js}/setup-globals.js | 0 tests/{ => php}/assets/1024x768.png | Bin tests/{ => php}/assets/350x150.png | Bin tests/{ => php}/assets/wordpress-logo.png | Bin tests/{ => php}/benchmark/run-benchmark.sh | 0 tests/{ => php}/stubs.php | 0 .../{ => php}/test-amp-analytics-options.php | 0 tests/{ => php}/test-amp-audio-converter.php | 0 .../test-amp-crowdsignal-embed-handler.php | 0 .../{ => php}/test-amp-dailymotion-embed.php | 0 tests/{ => php}/test-amp-facebook-embed.php | 0 tests/{ => php}/test-amp-form-sanitizer.php | 0 tests/{ => php}/test-amp-helper-functions.php | 0 tests/{ => php}/test-amp-iframe-sanitizer.php | 0 .../test-amp-image-dimension-extractor.php | 0 tests/{ => php}/test-amp-img-sanitizer.php | 0 tests/{ => php}/test-amp-instagram-embed.php | 0 .../test-amp-o2-player-sanitizer.php | 0 tests/{ => php}/test-amp-pinterest-embed.php | 0 .../{ => php}/test-amp-playbuzz-sanitizer.php | 0 tests/{ => php}/test-amp-render-post.php | 0 tests/{ => php}/test-amp-script-sanitizer.php | 0 tests/{ => php}/test-amp-soundcloud-embed.php | 0 tests/{ => php}/test-amp-story-sanitizer.php | 0 tests/{ => php}/test-amp-style-sanitizer.php | 0 ...nd-attribute-sanitizer-private-methods.php | 0 tests/{ => php}/test-amp-twitter-embed.php | 0 tests/{ => php}/test-amp-video-sanitizer.php | 0 tests/{ => php}/test-amp-vimeo-embed.php | 0 tests/{ => php}/test-amp-vine-embed.php | 0 tests/{ => php}/test-amp-youtube-embed.php | 0 tests/{ => php}/test-amp.php | 0 .../test-class-amp-admin-pointer.php | 0 .../test-class-amp-base-sanitizer.php | 0 .../test-class-amp-block-sanitizer.php | 0 tests/{ => php}/test-class-amp-cli.php | 0 .../test-class-amp-comments-sanitizer.php | 0 .../test-class-amp-content-sanitizer.php | 0 .../test-class-amp-core-block-handler.php | 0 tests/{ => php}/test-class-amp-dom-utils.php | 0 .../test-class-amp-editor-blocks.php | 0 ...test-class-amp-gallery-block-sanitizer.php | 0 .../test-class-amp-gfycat-embed-handler.php | 0 tests/{ => php}/test-class-amp-http.php | 0 .../test-class-amp-hulu-embed-handler.php | 0 .../test-class-amp-imgur-embed-handler.php | 0 tests/{ => php}/test-class-amp-meta-box.php | 0 ...st-class-amp-nav-menu-toggle-sanitizer.php | 0 .../test-class-amp-options-manager.php | 0 .../{ => php}/test-class-amp-options-menu.php | 0 .../test-class-amp-playlist-embed-handler.php | 0 .../test-class-amp-post-type-support.php | 0 .../test-class-amp-service-worker.php | 0 .../test-class-amp-story-post-type.php | 0 .../test-class-amp-story-templates.php | 0 .../test-class-amp-theme-support.php | 0 .../test-class-amp-vimeo-embed-handler.php | 0 .../test-class-amp-widget-archives.php | 0 .../test-class-amp-widget-categories.php | 0 .../{ => php}/test-class-amp-widget-text.php | 0 .../test-class-amp-youtube-embed-handler.php | 0 .../test-tag-and-attribute-sanitizer.php | 368 +++++++++--------- ...test-class-amp-validated-url-post-type.php | 0 ...st-class-amp-validation-error-taxonomy.php | 0 .../test-class-amp-validation-manager.php | 0 90 files changed, 932 insertions(+), 489 deletions(-) delete mode 100755 bin/bootstrap-env.sh create mode 100644 bin/local-env/docker-compose.yml rename bin/{ => local-env}/includes.sh (100%) create mode 100755 bin/local-env/install-composer.sh rename bin/{ => local-env}/install-node-nvm.sh (90%) rename bin/{ => local-env}/install-wordpress.sh (71%) rename bin/{install-docker.sh => local-env/launch-containers.sh} (55%) create mode 100755 bin/local-env/start.sh create mode 100755 bin/local-env/stop.sh delete mode 100755 bin/reset-e2e-tests.sh delete mode 100755 bin/setup-local-env.sh delete mode 100644 docker-compose.yml create mode 100644 jest-puppeteer.config.js create mode 100644 tests/e2e/config/bootstrap.js create mode 100644 tests/e2e/specs/amp-options.test.js delete mode 100644 tests/e2e/specs/demo.test.js create mode 100644 tests/e2e/specs/hello.test.js create mode 100644 tests/e2e/specs/stories-admin-pointer.test.js rename tests/{unit => js}/jest.config.js (92%) rename tests/{unit => js}/setup-globals.js (100%) rename tests/{ => php}/assets/1024x768.png (100%) rename tests/{ => php}/assets/350x150.png (100%) rename tests/{ => php}/assets/wordpress-logo.png (100%) rename tests/{ => php}/benchmark/run-benchmark.sh (100%) rename tests/{ => php}/stubs.php (100%) rename tests/{ => php}/test-amp-analytics-options.php (100%) rename tests/{ => php}/test-amp-audio-converter.php (100%) rename tests/{ => php}/test-amp-crowdsignal-embed-handler.php (100%) rename tests/{ => php}/test-amp-dailymotion-embed.php (100%) rename tests/{ => php}/test-amp-facebook-embed.php (100%) rename tests/{ => php}/test-amp-form-sanitizer.php (100%) rename tests/{ => php}/test-amp-helper-functions.php (100%) rename tests/{ => php}/test-amp-iframe-sanitizer.php (100%) rename tests/{ => php}/test-amp-image-dimension-extractor.php (100%) rename tests/{ => php}/test-amp-img-sanitizer.php (100%) rename tests/{ => php}/test-amp-instagram-embed.php (100%) rename tests/{ => php}/test-amp-o2-player-sanitizer.php (100%) rename tests/{ => php}/test-amp-pinterest-embed.php (100%) rename tests/{ => php}/test-amp-playbuzz-sanitizer.php (100%) rename tests/{ => php}/test-amp-render-post.php (100%) rename tests/{ => php}/test-amp-script-sanitizer.php (100%) rename tests/{ => php}/test-amp-soundcloud-embed.php (100%) rename tests/{ => php}/test-amp-story-sanitizer.php (100%) rename tests/{ => php}/test-amp-style-sanitizer.php (100%) rename tests/{ => php}/test-amp-tag-and-attribute-sanitizer-private-methods.php (100%) rename tests/{ => php}/test-amp-twitter-embed.php (100%) rename tests/{ => php}/test-amp-video-sanitizer.php (100%) rename tests/{ => php}/test-amp-vimeo-embed.php (100%) rename tests/{ => php}/test-amp-vine-embed.php (100%) rename tests/{ => php}/test-amp-youtube-embed.php (100%) rename tests/{ => php}/test-amp.php (100%) rename tests/{ => php}/test-class-amp-admin-pointer.php (100%) rename tests/{ => php}/test-class-amp-base-sanitizer.php (100%) rename tests/{ => php}/test-class-amp-block-sanitizer.php (100%) rename tests/{ => php}/test-class-amp-cli.php (100%) rename tests/{ => php}/test-class-amp-comments-sanitizer.php (100%) rename tests/{ => php}/test-class-amp-content-sanitizer.php (100%) rename tests/{ => php}/test-class-amp-core-block-handler.php (100%) rename tests/{ => php}/test-class-amp-dom-utils.php (100%) rename tests/{ => php}/test-class-amp-editor-blocks.php (100%) rename tests/{ => php}/test-class-amp-gallery-block-sanitizer.php (100%) rename tests/{ => php}/test-class-amp-gfycat-embed-handler.php (100%) rename tests/{ => php}/test-class-amp-http.php (100%) rename tests/{ => php}/test-class-amp-hulu-embed-handler.php (100%) rename tests/{ => php}/test-class-amp-imgur-embed-handler.php (100%) rename tests/{ => php}/test-class-amp-meta-box.php (100%) rename tests/{ => php}/test-class-amp-nav-menu-toggle-sanitizer.php (100%) rename tests/{ => php}/test-class-amp-options-manager.php (100%) rename tests/{ => php}/test-class-amp-options-menu.php (100%) rename tests/{ => php}/test-class-amp-playlist-embed-handler.php (100%) rename tests/{ => php}/test-class-amp-post-type-support.php (100%) rename tests/{ => php}/test-class-amp-service-worker.php (100%) rename tests/{ => php}/test-class-amp-story-post-type.php (100%) rename tests/{ => php}/test-class-amp-story-templates.php (100%) rename tests/{ => php}/test-class-amp-theme-support.php (100%) rename tests/{ => php}/test-class-amp-vimeo-embed-handler.php (100%) rename tests/{ => php}/test-class-amp-widget-archives.php (100%) rename tests/{ => php}/test-class-amp-widget-categories.php (100%) rename tests/{ => php}/test-class-amp-widget-text.php (100%) rename tests/{ => php}/test-class-amp-youtube-embed-handler.php (100%) rename tests/{ => php}/test-tag-and-attribute-sanitizer.php (87%) rename tests/{ => php}/validation/test-class-amp-validated-url-post-type.php (100%) rename tests/{ => php}/validation/test-class-amp-validation-error-taxonomy.php (100%) rename tests/{ => php}/validation/test-class-amp-validation-manager.php (100%) diff --git a/.eslintrc b/.eslintrc index fb606190908..d469eeec916 100644 --- a/.eslintrc +++ b/.eslintrc @@ -9,11 +9,23 @@ }, "globals": { "browser": true, - "page": true, "wp": true, "Set": true }, "rules": { "react/prop-types": 2 - } + }, + "overrides": [ + { + "files": [ "tests/e2e/**/*.js" ], + "env": { + "browser": true + }, + "globals": { + "browser": true, + "page": true, + "wp": true + } + } + ] } diff --git a/.travis.yml b/.travis.yml index 7962e2b6606..f4f18d536cb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,7 @@ notifications: cache: directories: - $HOME/.composer/cache + - $HOME/.jest-cache - $HOME/.npm - $HOME/.nvm/.cache - $HOME/phpunit-bin @@ -76,7 +77,20 @@ jobs: env: WP_VERSION=latest DEV_LIB_SKIP=phpcs,eslint,xmllint,phpsyntax,phpunit script: - source "$DEV_LIB_PATH/travis.script.sh" - - npm run test:js -- --ci + - npm run test:js -- --ci --cacheDirectory="$HOME/.jest-cache" + + - name: E2E tests + php: "7.3" + env: WP_VERSION=latest DEV_LIB_SKIP=phpcs,eslint,xmllint,phpsyntax,phpunit PUPPETEER_SKIP_CHROMIUM_DOWNLOAD= + install: + - nvm install + - composer install + # npm is handled by `npm run env:start` + script: + - npm run env:start + - npm run build:js # after npm dependencies have been installed + - npm run env:reset-site + - npm run test:e2e - name: PHP unit tests w/ external-http (7.3, WordPress latest) php: "7.3" diff --git a/bin/bootstrap-env.sh b/bin/bootstrap-env.sh deleted file mode 100755 index 3055a49b513..00000000000 --- a/bin/bootstrap-env.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -WP_VERSION=${WP_VERSION-latest} -WP_DEBUG=${WP_DEBUG-true} -SCRIPT_DEBUG=${SCRIPT_DEBUG-true} -DOCKER=${DOCKER-false} -DOCKER_ENV=${DOCKER_ENV-ci} -DOCKER_COMPOSE_FILE_OPTIONS="-f docker-compose.yml" - -if [ "$DOCKER_ENV" == "localwpdev" ]; then - DOCKER_COMPOSE_FILE_OPTIONS="${DOCKER_COMPOSE_FILE_OPTIONS} -f docker-compose-localdev.yml" -fi diff --git a/bin/local-env/docker-compose.yml b/bin/local-env/docker-compose.yml new file mode 100644 index 00000000000..929b5ae2eb4 --- /dev/null +++ b/bin/local-env/docker-compose.yml @@ -0,0 +1,43 @@ +version: '3.1' + +services: + wordpress: + image: wordpress + restart: always + ports: + - 8890:80 + environment: + WORDPRESS_DB_HOST: mysql + WORDPRESS_DB_PASSWORD: example + ABSPATH: /usr/src/wordpress/ + WORDPRESS_DEBUG: 1 + WORDPRESS_CONFIG_EXTRA: | + define( 'SCRIPT_DEBUG', true ); + volumes: + - wordpress_data:/var/www/html + - ../../:/var/www/html/wp-content/plugins/amp + - ../../node_modules/@wordpress/e2e-tests/plugins:/var/www/html/wp-content/plugins/gutenberg-test-plugins + - ../../node_modules/@wordpress/e2e-tests/mu-plugins:/var/www/html/wp-content/mu-plugins + depends_on: + - mysql + + cli: + image: wordpress:cli + restart: always + user: xfs + volumes: + - wordpress_data:/var/www/html + - ../../:/var/www/html/wp-content/plugins/amp + depends_on: + - mysql + - wordpress + + mysql: + image: mysql:5.7 + restart: always + environment: + MYSQL_ROOT_PASSWORD: example + MYSQL_DATABASE: wordpress_test + +volumes: + wordpress_data: diff --git a/bin/includes.sh b/bin/local-env/includes.sh similarity index 100% rename from bin/includes.sh rename to bin/local-env/includes.sh diff --git a/bin/local-env/install-composer.sh b/bin/local-env/install-composer.sh new file mode 100755 index 00000000000..f55530115a9 --- /dev/null +++ b/bin/local-env/install-composer.sh @@ -0,0 +1,41 @@ +#!/bin/bash +COMPOSER_VERSION=`curl -Ls -w %{url_effective} -o /dev/null https://github.com/composer/composer/releases/latest | rev | cut -d '/' -f 1 | rev` + +# Exit if any command fails +set -e + +# Include useful functions +. "$(dirname "$0")/includes.sh" + + +# Change to the expected directory +cd "$(dirname "$0")/../.." + +# Check if composer is installed +if [ "$TRAVIS" != "true" ] && ! command_exists "composer"; then + if ask "$(error_message "Composer isn't installed, would you like to download and install it automatically?")" Y; then + echo -en $(status_message "Installing Composer..." ) + download "https://getcomposer.org/installer" | bash >/dev/null 2>&1 + mkdir -p /usr/local/bin + mv composer.phar /usr/local/bin/composer + echo ' done!' + else + echo -e $(error_message "") + echo -e $(error_message "Please install Composer manually, then re-run the setup script to continue.") + echo -e $(error_message "Composer installation instructions can be found here: $(action_format "https://getcomposer.org/doc/00-intro.md")") + fi + + exit 1 +fi + +# Check if the current Composer version is up to date. +if [ "$TRAVIS" != "true" ] && ! [[ "$(composer --version)" == "Composer version $COMPOSER_VERSION "* ]]; then + echo -en $(status_message "Updating Composer..." ) + composer self-update + echo ' done!' +fi + + +# Install/update packages +echo -e $(status_message "Installing and updating Composer packages..." ) +composer install diff --git a/bin/install-node-nvm.sh b/bin/local-env/install-node-nvm.sh similarity index 90% rename from bin/install-node-nvm.sh rename to bin/local-env/install-node-nvm.sh index 9edc083833d..f4c29240ce5 100755 --- a/bin/install-node-nvm.sh +++ b/bin/local-env/install-node-nvm.sh @@ -1,5 +1,5 @@ #!/bin/bash -NVM_VERSION=`curl -Ls -w %{url_effective} -o /dev/null https://github.com/creationix/nvm/releases/latest | rev | cut -d '/' -f 1 | rev` +NVM_VERSION=`curl -Ls -w %{url_effective} -o /dev/null https://github.com/nvm-sh/nvm/releases/latest | rev | cut -d '/' -f 1 | rev` # Exit if any command fails set -e @@ -19,7 +19,7 @@ if [ -n "$NVM_DIR" ]; then fi # Change to the expected directory -cd "$(dirname "$0")/.." +cd "$(dirname "$0")/../.." # Check if nvm is installed if [ "$TRAVIS" != "true" ] && ! command_exists "nvm"; then @@ -30,7 +30,7 @@ if [ "$TRAVIS" != "true" ] && ! command_exists "nvm"; then fi echo -en $(status_message "Installing NVM..." ) - download "https://raw.githubusercontent.com/creationix/nvm/$NVM_VERSION/install.sh" | bash >/dev/null 2>&1 + download "https://raw.githubusercontent.com/nvm-sh/nvm/$NVM_VERSION/install.sh" | bash >/dev/null 2>&1 echo ' done!' echo -e $(warning_message "NVM was updated, please run this command to reload it:" ) @@ -39,7 +39,7 @@ if [ "$TRAVIS" != "true" ] && ! command_exists "nvm"; then else echo -e $(error_message "") echo -e $(error_message "Please install NVM manually, then re-run the setup script to continue.") - echo -e $(error_message "NVM installation instructions can be found here: $(action_format "https://github.com/creationix/nvm")") + echo -e $(error_message "NVM installation instructions can be found here: $(action_format "https://github.com/nvm-sh/nvm")") fi exit 1 @@ -48,7 +48,7 @@ fi # Check if the current nvm version is up to date. if [ "$TRAVIS" != "true" ] && [ $NVM_VERSION != "v$(nvm --version)" ]; then echo -en $(status_message "Updating NVM..." ) - download "https://raw.githubusercontent.com/creationix/nvm/$NVM_VERSION/install.sh" | bash >/dev/null 2>&1 + download "https://raw.githubusercontent.com/nvm-sh/nvm/$NVM_VERSION/install.sh" | bash >/dev/null 2>&1 echo ' done!' echo -e $(warning_message "NVM was updated, please run this command to reload it:" ) diff --git a/bin/install-wordpress.sh b/bin/local-env/install-wordpress.sh similarity index 71% rename from bin/install-wordpress.sh rename to bin/local-env/install-wordpress.sh index 5b3b8b83c0d..bb8d05efe30 100755 --- a/bin/install-wordpress.sh +++ b/bin/local-env/install-wordpress.sh @@ -3,32 +3,19 @@ # Exit if any command fails. set -e -# Gutenberg script includes. -. "$(dirname "$0")/includes.sh" +# Common variables. +DOCKER_COMPOSE_FILE_OPTIONS="-f $(dirname "$0")/docker-compose.yml" +WP_DEBUG=${WP_DEBUG-true} +SCRIPT_DEBUG=${SCRIPT_DEBUG-true} -# Set up environment variables -. "$(dirname "$0")/bootstrap-env.sh" +# Include useful functions +. "$(dirname "$0")/includes.sh" # These are the containers and values for the development site. CLI='cli' CONTAINER='wordpress' SITE_TITLE='AMP Dev' -# If we're installing/re-installing the test site, change the containers used. -if [ "$1" == '--e2e_tests' ]; then - CLI="${CLI}_e2e_tests" - CONTAINER="${CONTAINER}_e2e_tests" - SITE_TITLE='AMP Testing' - - if ! docker ps | grep -q $CONTAINER; then - echo -e $(error_message "WordPress e2e tests run in their own Docker container, but that container wasn't found.") - echo "Please restart your Docker containers by running 'docker-compose $DOCKER_COMPOSE_FILE_OPTIONS down && docker-compose $DOCKER_COMPOSE_FILE_OPTIONS up -d' or" - echo "by running './bin/setup-local-env.sh' again." - echo "" - exit 1 - fi -fi - # Get the host port for the WordPress container. HOST_PORT=$(docker-compose $DOCKER_COMPOSE_FILE_OPTIONS port $CONTAINER 80 | awk -F : '{printf $2}') @@ -43,7 +30,7 @@ echo '' # If this is the test site, we reset the database so no posts/comments/etc. # dirty up the tests. -if [ "$1" == '--e2e_tests' ]; then +if [ "$1" == '--reset-site' ]; then echo -e $(status_message "Resetting test database...") docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm -u 33 $CLI db reset --yes --quiet fi @@ -64,13 +51,8 @@ fi # Make sure the uploads and upgrade folders exist and we have permissions to add files. echo -e $(status_message "Ensuring that files can be uploaded...") -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm $CONTAINER chmod 767 /var/www/html/wp-content/plugins -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm $CONTAINER chmod 767 /var/www/html/wp-config.php -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm $CONTAINER chmod 767 /var/www/html/wp-settings.php -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm $CONTAINER mkdir -p /var/www/html/wp-content/uploads -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm $CONTAINER chmod -v 767 /var/www/html/wp-content/uploads -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm $CONTAINER mkdir -p /var/www/html/wp-content/upgrade -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm $CONTAINER chmod 767 /var/www/html/wp-content/upgrade +docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm $CONTAINER mkdir -p /var/www/html/wp-content/uploads /var/www/html/wp-content/upgrade +docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm $CONTAINER chmod 767 /var/www/html/wp-content/plugins /var/www/html/wp-config.php /var/www/html/wp-settings.php /var/www/html/wp-content/uploads /var/www/html/wp-content/upgrade CURRENT_WP_VERSION=$(docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run -T --rm $CLI core version) echo -e $(status_message "Current WordPress version: $CURRENT_WP_VERSION...") @@ -91,31 +73,31 @@ if [ "$CURRENT_URL" != "http://localhost:$HOST_PORT" ]; then docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm -u 33 $CLI option update siteurl "http://localhost:$HOST_PORT" --quiet fi +# Install a dummy favicon to avoid 404 errors. +echo -e $(status_message "Installing a dummy favicon...") +docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm $CONTAINER touch /var/www/html/favicon.ico + # Activate AMP plugin. echo -e $(status_message "Activating AMP plugin...") docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm -u 33 $CLI plugin activate amp --quiet -if [ "$POPULAR_PLUGINS" == "true" ]; then - echo -e $(status_message "Activating popular plugins...") - docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm -u 33 $CLI plugin install advanced-custom-fields --activate --quiet - docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm -u 33 $CLI plugin install jetpack --activate --quiet - docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm -u 33 $CLI plugin install wpforms-lite --activate --quiet -fi -# Install a dummy favicon to avoid 404 errors. -echo -e $(status_message "Installing a dummy favicon...") -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm $CONTAINER touch /var/www/html/favicon.ico +# Install & activate Gutenberg plugin. +echo -e $(status_message "Installing and activating Gutenberg plugin...") +# todo: Use `wp plugin install --activate` once WP-CLI is updated, see https://github.com/wp-cli/extension-command/issues/176. +docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm -u 33 $CLI plugin install gutenberg --activate --quiet +docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm -u 33 $CLI plugin activate gutenberg --quiet # Configure site constants. echo -e $(status_message "Configuring site constants...") WP_DEBUG_CURRENT=$(docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run -T --rm -u 33 $CLI config get --type=constant --format=json WP_DEBUG) -if [ $WP_DEBUG != $WP_DEBUG_CURRENT ]; then +if [ "$WP_DEBUG" != $WP_DEBUG_CURRENT ]; then docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm -u 33 $CLI config set WP_DEBUG $WP_DEBUG --raw --type=constant --quiet WP_DEBUG_RESULT=$(docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run -T --rm -u 33 $CLI config get --type=constant --format=json WP_DEBUG) echo -e $(status_message "WP_DEBUG: $WP_DEBUG_RESULT...") fi SCRIPT_DEBUG_CURRENT=$(docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run -T --rm -u 33 $CLI config get --type=constant --format=json SCRIPT_DEBUG) -if [ $SCRIPT_DEBUG != $SCRIPT_DEBUG_CURRENT ]; then +if [ "$SCRIPT_DEBUG" != $SCRIPT_DEBUG_CURRENT ]; then docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm -u 33 $CLI config set SCRIPT_DEBUG $SCRIPT_DEBUG --raw --type=constant --quiet SCRIPT_DEBUG_RESULT=$(docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run -T --rm -u 33 $CLI config get --type=constant --format=json SCRIPT_DEBUG) echo -e $(status_message "SCRIPT_DEBUG: $SCRIPT_DEBUG_RESULT...") diff --git a/bin/install-docker.sh b/bin/local-env/launch-containers.sh similarity index 55% rename from bin/install-docker.sh rename to bin/local-env/launch-containers.sh index 56bb4ad3ef1..dae82775f16 100755 --- a/bin/install-docker.sh +++ b/bin/local-env/launch-containers.sh @@ -3,14 +3,15 @@ # Exit if any command fails. set -e -. "$(dirname "$0")/bootstrap-env.sh" +# Common variables. +DOCKER_COMPOSE_FILE_OPTIONS="-f $(dirname "$0")/docker-compose.yml" # Include useful functions. . "$(dirname "$0")/includes.sh" # Check that Docker is installed. if ! command_exists "docker"; then - echo -e $(error_message "Docker doesn't seem to be installed. Please head on over to the Docker site to download it: $(action_format "https://www.docker.com/community-edition#/download")") + echo -e $(error_message "Docker doesn't seem to be installed. Please head on over to the Docker site to download it: $(action_format "https://www.docker.com/products/docker-desktop")") exit 1 fi @@ -31,16 +32,3 @@ docker-compose $DOCKER_COMPOSE_FILE_OPTIONS pull # Launch the containers. echo -e $(status_message "Starting Docker containers...") docker-compose $DOCKER_COMPOSE_FILE_OPTIONS up -d >/dev/null - -# Set up WordPress Development site. -# Note: we don't bother installing the test site right now, because that's -# done on every time `npm run test-e2e` is run. -. "$(dirname "$0")/install-wordpress.sh" - -# Install the PHPUnit test scaffolding. -echo -e $(status_message "Installing PHPUnit test scaffolding...") -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm wordpress_phpunit /app/bin/install-wp-tests.sh wordpress_test root example mysql $WP_VERSION false > /dev/null - -# Install Composer. This is only used to run WordPress Coding Standards checks. -echo -e $(status_message "Installing and updating Composer modules...") -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm composer install diff --git a/bin/local-env/start.sh b/bin/local-env/start.sh new file mode 100755 index 00000000000..64272b8cc44 --- /dev/null +++ b/bin/local-env/start.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +# Exit if any command fails +set -e + +# Include useful functions +. "$(dirname "$0")/includes.sh" + +# Change to the expected directory +cd "$(dirname "$0")/../.." + +# Check whether Node and NVM are installed +. "$(dirname "$0")/install-node-nvm.sh" + +# Check whether Composer installed +. "$(dirname "$0")/install-composer.sh" + +# Check whether Docker is installed and running +. "$(dirname "$0")/launch-containers.sh" + +# Set up WordPress Development site. +# Note: we don't bother installing the test site right now, because that's +# done on every time `npm run test-e2e` is run. +. "$(dirname "$0")/install-wordpress.sh" + +! read -d '' AMP <<"EOT" +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMWNXK0OOkkkkOO0KXNWMMMMMMMMMMMMMMMM +MMMMMMMMMMMMWX0kdlc:::::::::::ccodk0NWMMMMMMMMMMMM +MMMMMMMMMWXOdl::::::::::::::::::::::lx0NMMMMMMMMMM +MMMMMMMWKxl::::::::::::::::::::::::::::oOXWMMMMMMM +MMMMMMXkl:::::::::::::::::col::::::::::::oONMMMMMM +MMMMW0o:::::::::::::::::ox0Xk:::::::::::::cxXWMMMM +MMMW0l:::::::::::::::::dKWWXd:::::::::::::::dXMMMM +MMW0l::::::::::::::::cxXWMM0l::::::::::::::::dXMMM +MMXd::::::::::::::::ckNMMMWkc::::::::::::::::ckWMM +MWOc:::::::::::::::lONMMMMNkooool:::::::::::::oXMM +MWk:::::::::::::::l0WMMMMMMWNWNNOc::::::::::::l0MM +MNx::::::::::::::oKWMMMMMMMMMMW0l:::::::::::::cOWM +MNx:::::::::::::oKWWWMMMMMMMMNOl::::::::::::::c0MM +MWOc::::::::::::cddddxKWMMMMNkc:::::::::::::::oKMM +MMXd:::::::::::::::::l0MMMMXdc:::::::::::::::ckWMM +MMW0l::::::::::::::::dXMWWKd:::::::::::::::::oXMMM +MMMWOl:::::::::::::::kWW0xo:::::::::::::::::oKWMMM +MMMMW0l:::::::::::::l0NOl::::::::::::::::::dKWMMMM +MMMMMWKdc:::::::::::cooc:::::::::::::::::lkNMMMMMM +MMMMMMMN0dc::::::::::::::::::::::::::::lxKWMMMMMMM +MMMMMMMMMWKxoc::::::::::::::::::::::coOXWMMMMMMMMM +MMMMMMMMMMMWNKkdoc:::::::::::::cloxOKWMMMMMMMMMMMM +MMMMMMMMMMMMMMMWNX0OkkxxxxxxkO0KXWWMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM + +EOT + +CURRENT_URL=$(docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run -T --rm cli option get siteurl) + +echo -e "\nWelcome to...\n" +echo -e "\033[95m$AMP\033[0m" + +# Give the user more context to what they should do next: Build the plugin and start testing! +echo -e "\nRun $(action_format "npm run dev") to build the latest version of the AMP plugin," +echo -e "then open $(action_format "$CURRENT_URL") to get started!" + +echo -e "\n\nAccess the above install using the following credentials:" +echo -e "Default username: $(action_format "admin"), password: $(action_format "password")" diff --git a/bin/local-env/stop.sh b/bin/local-env/stop.sh new file mode 100755 index 00000000000..51c2bdc5c3b --- /dev/null +++ b/bin/local-env/stop.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Exit if any command fails. +set -e + +# Common variables. +DOCKER_COMPOSE_FILE_OPTIONS="-f $(dirname "$0")/docker-compose.yml" + +# Include useful functions. +. "$(dirname "$0")/includes.sh" + +# Check that Docker is installed. +if ! command_exists "docker"; then + echo -e $(error_message "Docker doesn't seem to be installed. Please head on over to the Docker site to download it: $(action_format "https://www.docker.com/products/docker-desktop")") + exit 1 +fi + +# Check that Docker is running. +if ! docker info >/dev/null 2>&1; then + echo -e $(error_message "Docker isn't running. Please check that you've started your Docker app, and see it in your system tray.") + exit 1 +fi + +# Stop existing containers. +echo -e $(status_message "Stopping Docker containers...") +docker-compose $DOCKER_COMPOSE_FILE_OPTIONS down --remove-orphans >/dev/null 2>&1 diff --git a/bin/reset-e2e-tests.sh b/bin/reset-e2e-tests.sh deleted file mode 100755 index fb1e080f9da..00000000000 --- a/bin/reset-e2e-tests.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -# Exit if any command fails. -set -e - -# Set up WordPress site used for end-to-end (e2e) tests. -. "$(dirname "$0")/install-wordpress.sh" --e2e_tests diff --git a/bin/setup-local-env.sh b/bin/setup-local-env.sh deleted file mode 100755 index dcc86df34a2..00000000000 --- a/bin/setup-local-env.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash - -# Exit if any command fails -set -e - -# Set up environment variables -. "$(dirname "$0")/bootstrap-env.sh" - -# Include useful functions -. "$(dirname "$0")/includes.sh" - -# Change to the expected directory -cd "$(dirname "$0")/.." - -# Check Node and NVM are installed -. "$(dirname "$0")/install-node-nvm.sh" - -# Check Docker is installed and running -. "$(dirname "$0")/install-docker.sh" - -! read -d '' GUTENBERG <<"EOT" -,⁻⁻⁻· . | -| ،⁓’. . |--- ,---. ,---. |---. ,---. ,---. ,---. -| | | | | |---' | | | | |---' | | | -`---' `---' `---’ `---’ ' ` `---' `---’ ` `---| - `---' -EOT - -CURRENT_URL=$(docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run -T --rm cli option get siteurl) - -echo -e "\nWelcome to...\n" -echo -e "\033[95m$GUTENBERG\033[0m" - -# Give the user more context to what they should do next: Build Gutenberg and start testing! -echo -e "\nRun $(action_format "npm run dev") to build the latest Gutenberg packages," -echo -e "then open $(action_format "$CURRENT_URL") to get started!" - -echo -e "\n\nAccess the above install using the following credentials:" -echo -e "Default username: $(action_format "admin"), password: $(action_format "password")" diff --git a/contributing.md b/contributing.md index 91954ef4b2f..2bd8fb0ace0 100644 --- a/contributing.md +++ b/contributing.md @@ -44,9 +44,96 @@ The AMP Project accepts responsible security disclosures through the [Google App In addition to the Community Guidelines, this project follows an explicit [Code of Conduct](https://github.com/ampproject/amp-wp/blob/develop/code_of_conduct.md). -## Dev Setup +## Getting Started -To start, clone this repository into your WordPress install being used for development: +### Requirements + +To contribute to this plugin, you need the following tools installed on your computer: + +* [Composer](https://getcomposer.org/) - to install PHP dependencies. +* [Node.js](https://nodejs.org/en/) - to install JavaScript dependencies. +* [WordPress](https://wordpress.org/download/) - to run the actual plugin. + +You should be running a Node version matching the [current active LTS release](https://github.com/nodejs/Release#release-schedule) or newer for this plugin to work correctly. You can check your Node.js version by typing node -v in the Terminal prompt. + +If you have an incompatible version of Node in your development environment, you can use [nvm](https://github.com/creationix/nvm) to change node versions on the command line: + +```bash +nvm install +``` + +## Local Environment + +Since you need a WordPress environment to run the plugin in, the quickest way to get up and running is to use the provided Docker setup. Install [Docker](https://www.docker.com/products/docker-desktop) and [Docker Compose](https://docs.docker.com/compose/install/) by following the instructions on their website. + +You can then clone this project somewhere on your computer: + +```bash +git clone git@github.com:ampproject/amp-wp.git amp +cd amp +``` + +After that, run a script to set up the local environment. It will automatically verify whether Docker, Composer and Node.js are configured properly and start the local WordPress instance. You may need to run this script multiple times if prompted. + +```bash +./bin/local-env/start.sh +``` + +If everything was successful, you'll see this on your screen: + +``` +Welcome to... + +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMWNXK0OOkkkkOO0KXNWMMMMMMMMMMMMMMMM +MMMMMMMMMMMMWX0kdlc:::::::::::ccodk0NWMMMMMMMMMMMM +MMMMMMMMMWXOdl::::::::::::::::::::::lx0NMMMMMMMMMM +MMMMMMMWKxl::::::::::::::::::::::::::::oOXWMMMMMMM +MMMMMMXkl:::::::::::::::::col::::::::::::oONMMMMMM +MMMMW0o:::::::::::::::::ox0Xk:::::::::::::cxXWMMMM +MMMW0l:::::::::::::::::dKWWXd:::::::::::::::dXMMMM +MMW0l::::::::::::::::cxXWMM0l::::::::::::::::dXMMM +MMXd::::::::::::::::ckNMMMWkc::::::::::::::::ckWMM +MWOc:::::::::::::::lONMMMMNkooool:::::::::::::oXMM +MWk:::::::::::::::l0WMMMMMMWNWNNOc::::::::::::l0MM +MNx::::::::::::::oKWMMMMMMMMMMW0l:::::::::::::cOWM +MNx:::::::::::::oKWWWMMMMMMMMNOl::::::::::::::c0MM +MWOc::::::::::::cddddxKWMMMMNkc:::::::::::::::oKMM +MMXd:::::::::::::::::l0MMMMXdc:::::::::::::::ckWMM +MMW0l::::::::::::::::dXMWWKd:::::::::::::::::oXMMM +MMMWOl:::::::::::::::kWW0xo:::::::::::::::::oKWMMM +MMMMW0l:::::::::::::l0NOl::::::::::::::::::dKWMMMM +MMMMMWKdc:::::::::::cooc:::::::::::::::::lkNMMMMMM +MMMMMMMN0dc::::::::::::::::::::::::::::lxKWMMMMMMM +MMMMMMMMMWKxoc::::::::::::::::::::::coOXWMMMMMMMMM +MMMMMMMMMMMWNKkdoc:::::::::::::cloxOKWMMMMMMMMMMMM +MMMMMMMMMMMMMMMWNX0OkkxxxxxxkO0KXWWMMMMMMMMMMMMMMM +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +``` + +The WordPress installation should be available at http://localhost:8890 (**Username**: admin, **Password**: password). + +To later turn off the local environment, you can run: + +```bash +npm run env:stop +``` + +To bring it back later, run: + +```bash +npm run env:start +``` + +Also, if you need to reset the local environment's database, you can run: + +```bash +npm run env:reset-site +``` + +### Custom Environment + +Alternatively, you can use your own local WordPress environment and clone this repository right into your `wp-content/plugins` directory. ```bash cd wp-content/plugins && git clone git@github.com:ampproject/amp-wp.git amp @@ -62,30 +149,112 @@ npm install And lastly, do a build of the JavaScript: ```bash -npm run build +npm run build:js ``` Lastly, to get the plugin running in your WordPress install, run `composer install` and then activate the plugin via the WordPress dashboard or `wp plugin activate amp`. -To install the `pre-commit` hook, do `bash vendor/xwp/wp-dev-lib/scripts/install-pre-commit-hook.sh`. +## Developing the Plugin -Note that pull requests will be checked against [WordPress-Coding-Standards](https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards) with PHPCS, and for JavaScript linting is done with ESLint and (for now) JSCS and JSHint. +Whether you use the pre-existing local environment or a custom one, any PHP code changes will be directly visible during development. -## Modifying JavaScript for Blocks +However, for JavaScript this involves a build process. To watch for any JavaScript file changes and re-build it when needed, you can run the following command: -To edit JavaScript code which is built/complied, run `npm run dev` to watch the files which Webpack will build. These complied files are excluded from version control but they are included in the release packages. +```bash +npm run dev +``` + +This way you will get a development build of the JavaScript, which makes debugging easier. + +To get a production build, run: + +```bash +npm run build:js +``` -## Creating a Plugin Build +### Creating a Plugin Build -To create a build of the plugin for installing in WordPress as a ZIP package, do: +To create a build of the plugin for installing in WordPress as a ZIP package, run: ```bash -composer install # (if you haven't done so yet) -npm install # (if you haven't done so yet) npm run build ``` -This will create an `amp.zip` in the plugin directory which you can install. The contents of this ZIP are also located in the `build` directory which you can `rsync` somewhere as well. +This will create an `amp.zip` in the plugin directory which you can install. The contents of this ZIP are also located in the `build` directory which you can `rsync` somewhere as well if needed. + +### Writing Tests + +#### PHP Unit Tests + +The AMP plugin uses the [PHPUnit](https://phpunit.de/) testing framework to write unit and integration tests for the PHP part. + +To run the full test suite, you can use the following command: + +```bash +npm run test:php +``` + +You can also just run test for a specific function or class by using something like this: + +```bash +npm run test:php -- --filter=AMP_Theme_Support +``` + +See `npm run test:php:help` to see all the possible options. + +#### JavaScript Unit Tests + +[Jest](https://jestjs.io/) is used as the JavaScript unit testing framework. + +To run the full test suite, you can use the following command: + +```bash +npm run test:js +``` + +You can also watch for any file changes and only run tests that failed or have been modified: + +```bash +npm run test:js:watch +``` + +See `npm run test:js:help` to get a list of additional options that can be passed to the test runner. + +#### End-to-End Tests + +This project leverages the local Docker-based environment to facilitate end-to-end (e2e) testing using Puppeteer. + +To run the full test suite, you can use the following command: + +```bash +npm run test:e2e +``` + +You can also watch for any file changes and only run tests that failed or have been modified: + +```bash +npm run test:e2e:watch +``` + +Not using the built-in local environment? You can also pass any other URL to run the tests against. Example: + +```bash +npm run test:e2e -- --wordpress-base-url=https://my-amp-dev-site.local +``` + +For debugging purposes, you can also run the E2E tests in non-headless mode: + +```bash +HEADLESS=false npm run test:e2e +``` + +### Coding Standards + +All contributions to this project will be checked against [WordPress-Coding-Standards](https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards) with PHPCS, and for JavaScript linting is done with ESLint. + +To verify your code meets the requirements, you can run `npm run lint`. + +You can also install a `pre-commit` hook by running `bash vendor/xwp/wp-dev-lib/scripts/install-pre-commit-hook.sh`. This way, your code will be checked automatically before committing any changes. ## Updating Allowed Tags And Attributes @@ -136,24 +305,6 @@ The following script creates a post with all core Gutenberg blocks. To run it: 3. run `bash bin/create-gutenberge-test-post.sh` 4. go to the URL that is output in the command line -## PHPUnit Testing - -Please run these tests in an environment with WordPress unit tests installed, like [VVV](https://github.com/Varying-Vagrant-Vagrants/VVV). - -Run tests: - -``` bash -$ phpunit -``` - -Run tests with an HTML coverage report: - -``` bash -$ phpunit --coverage-html /tmp/report -``` - -When you push a commit to your PR, Travis CI will run the PHPUnit tests and sniffs against the WordPress Coding Standards. - ## Creating a Prerelease 1. Create changelog draft on [Wiki page](https://github.com/ampproject/amp-wp/wiki/Release-Changelog-Draft). diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 33c043e6822..00000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,95 +0,0 @@ -version: '3.1' - -services: - - wordpress: - image: wordpress - restart: always - ports: - - 8888:80 - environment: - WORDPRESS_DB_HOST: mysql - WORDPRESS_DB_PASSWORD: example - ABSPATH: /usr/src/wordpress/ - WORDPRESS_DEBUG: 1 - WORDPRESS_CONFIG_EXTRA: | - define( 'SCRIPT_DEBUG', true ); - volumes: - - wordpress_data:/var/www/html - - .:/var/www/html/wp-content/plugins/amp - - ./node_modules/@wordpress/e2e-tests/plugins:/var/www/html/wp-content/plugins/gutenberg-test-plugins - - ./node_modules/@wordpress/e2e-tests/mu-plugins:/var/www/html/wp-content/mu-plugins - depends_on: - - mysql - - cli: - image: wordpress:cli - restart: always - user: xfs - volumes: - - wordpress_data:/var/www/html - - .:/var/www/html/wp-content/plugins/amp - depends_on: - - mysql - - wordpress - - mysql: - image: mysql:5.7 - restart: always - environment: - MYSQL_ROOT_PASSWORD: example - MYSQL_DATABASE: wordpress_test - - wordpress_phpunit: - image: chriszarate/wordpress-phpunit - restart: always - environment: - PHPUNIT_DB_HOST: mysql - volumes: - - .:/app - - testsuite:/tmp - depends_on: - - mysql - - composer: - image: composer - restart: always - volumes: - - .:/app - - wordpress_e2e_tests: - image: wordpress - restart: always - ports: - - 8889:80 - environment: - WORDPRESS_DB_HOST: mysql - WORDPRESS_DB_NAME: wordpress_e2e_tests - WORDPRESS_DB_PASSWORD: example - ABSPATH: /usr/src/wordpress/ - WORDPRESS_DEBUG: 1 - WORDPRESS_CONFIG_EXTRA: | - define( 'SCRIPT_DEBUG', true ); - volumes: - - wordpress_e2e_tests_data:/var/www/html - - .:/var/www/html/wp-content/plugins/amp - - ./node_modules/@wordpress/e2e-tests/plugins:/var/www/html/wp-content/plugins/gutenberg-test-plugins - - ./node_modules/@wordpress/e2e-tests/mu-plugins:/var/www/html/wp-content/mu-plugins - depends_on: - - mysql - - cli_e2e_tests: - image: wordpress:cli - restart: always - user: xfs - volumes: - - wordpress_e2e_tests_data:/var/www/html - - .:/var/www/html/wp-content/plugins/amp - depends_on: - - mysql - - wordpress_e2e_tests - -volumes: - testsuite: - wordpress_data: - wordpress_e2e_tests_data: diff --git a/includes/class-amp-autoloader.php b/includes/class-amp-autoloader.php index ee2575c5c43..dfabb4f8f16 100644 --- a/includes/class-amp-autoloader.php +++ b/includes/class-amp-autoloader.php @@ -107,8 +107,8 @@ class AMP_Autoloader { 'AMP_Widget_Archives' => 'includes/widgets/class-amp-widget-archives', 'AMP_Widget_Categories' => 'includes/widgets/class-amp-widget-categories', 'AMP_Widget_Text' => 'includes/widgets/class-amp-widget-text', - 'AMP_Test_Stub_Sanitizer' => 'tests/stubs', - 'AMP_Test_World_Sanitizer' => 'tests/stubs', + 'AMP_Test_Stub_Sanitizer' => 'tests/php/stubs', + 'AMP_Test_World_Sanitizer' => 'tests/php/stubs', ); /** diff --git a/jest-puppeteer.config.js b/jest-puppeteer.config.js new file mode 100644 index 00000000000..ce1e29f057f --- /dev/null +++ b/jest-puppeteer.config.js @@ -0,0 +1,7 @@ +module.exports = { + launch: { + dumpio: true, + headless: process.env.HEADLESS !== 'false', + }, + browserContext: 'default', +}; diff --git a/package.json b/package.json index 5b7720152e8..f760e761cda 100644 --- a/package.json +++ b/package.json @@ -101,6 +101,9 @@ "check-licenses": "wp-scripts check-licenses --production", "deploy": "grunt deploy", "dev": "wp-scripts start", + "env:start": "./bin/local-env/start.sh", + "env:stop": "./bin/local-env/stop.sh", + "env:reset-site": "./bin/local-env/install-wordpress.sh --reset-site", "lint": "npm-run-all --parallel lint:*", "lint:css": "wp-scripts lint-style 'assets/**/*.css'", "lint:css:fix": "npm run lint:css -- --fix", @@ -111,13 +114,14 @@ "lint:pkg-json": "wp-scripts lint-pkg-json . --ignorePath .gitignore", "start": "wp-scripts start", "test": "npm-run-all --parallel test:*", - "pretest:e2e": "cross-env SCRIPT_DEBUG=false ./bin/reset-e2e-tests.sh", - "test:e2e": "wp-scripts test-e2e --config=tests/e2e/jest.config.js", + "test:e2e": "WP_BASE_URL=http://localhost:8890 wp-scripts test-e2e --config=tests/e2e/jest.config.js", + "test:e2e:help": "npm run test:e2e -- --help", "test:e2e:watch": "npm run test:e2e -- --watch", - "test:js": "wp-scripts test-unit-js --config=tests/unit/jest.config.js", + "test:js": "wp-scripts test-unit-js --config=tests/js/jest.config.js", "test:js:help": "wp-scripts test-unit-js --help", "test:js:watch": "npm run test:js -- --watch", - "test:php": "phpunit" + "test:php": "phpunit", + "test:php:help": "npm run test:php -- --help" }, "npmPackageJsonLintConfig": { "extends": "@wordpress/npm-package-json-lint-config", diff --git a/tests/e2e/config/bootstrap.js b/tests/e2e/config/bootstrap.js new file mode 100644 index 00000000000..101dd2560d9 --- /dev/null +++ b/tests/e2e/config/bootstrap.js @@ -0,0 +1,142 @@ +/** + * External dependencies + */ +import { get } from 'lodash'; + +/** + * WordPress dependencies + */ +import { + clearLocalStorage, + enablePageDialogAccept, + setBrowserViewport, +} from '@wordpress/e2e-test-utils'; + +/** + * Environment variables + */ +const { PUPPETEER_TIMEOUT } = process.env; + +/** + * Set of console logging types observed to protect against unexpected yet + * handled (i.e. not catastrophic) errors or warnings. Each key corresponds + * to the Puppeteer ConsoleMessage type, its value the corresponding function + * on the console global object. + * + * @type {Object} + */ +const OBSERVED_CONSOLE_MESSAGE_TYPES = { + warning: 'warn', + error: 'error', +}; + +/** + * Array of page event tuples of [ eventName, handler ]. + * + * @type {Array} + */ +const pageEvents = []; + +// The Jest timeout is increased because these tests are a bit slow +jest.setTimeout( PUPPETEER_TIMEOUT || 100000 ); + +/** + * Adds an event listener to the page to handle additions of page event + * handlers, to assure that they are removed at test teardown. + */ +function capturePageEventsForTearDown() { + page.on( 'newListener', ( eventName, listener ) => { + pageEvents.push( [ eventName, listener ] ); + } ); +} + +/** + * Removes all bound page event handlers. + */ +function removePageEvents() { + pageEvents.forEach( ( [ eventName, handler ] ) => { + page.removeListener( eventName, handler ); + } ); +} + +/** + * Adds a page event handler to emit uncaught exception to process if one of + * the observed console logging types is encountered. + */ +function observeConsoleLogging() { + page.on( 'console', ( message ) => { + const type = message.type(); + if ( ! OBSERVED_CONSOLE_MESSAGE_TYPES.hasOwnProperty( type ) ) { + return; + } + + let text = message.text(); + + // An exception is made for _blanket_ deprecation warnings: Those + // which log regardless of whether a deprecated feature is in use. + if ( text.includes( 'This is a global warning' ) ) { + return; + } + + // Viewing posts on the front end can result in this error, which + // has nothing to do with Gutenberg. + if ( text.includes( 'net::ERR_UNKNOWN_URL_SCHEME' ) ) { + return; + } + + // A bug present in WordPress 5.2 will produce console warnings when + // loading the Dashicons font. These can be safely ignored, as they do + // not otherwise regress on application behavior. This logic should be + // removed once the associated ticket has been closed. + // + // See: https://core.trac.wordpress.org/ticket/47183 + if ( + text.startsWith( 'Failed to decode downloaded font:' ) || + text.startsWith( 'OTS parsing error:' ) + ) { + return; + } + + const logFunction = OBSERVED_CONSOLE_MESSAGE_TYPES[ type ]; + + // As of Puppeteer 1.6.1, `message.text()` wrongly returns an object of + // type JSHandle for error logging, instead of the expected string. + // + // See: https://github.com/GoogleChrome/puppeteer/issues/3397 + // + // The recommendation there to asynchronously resolve the error value + // upon a console event may be prone to a race condition with the test + // completion, leaving a possibility of an error not being surfaced + // correctly. Instead, the logic here synchronously inspects the + // internal object shape of the JSHandle to find the error text. If it + // cannot be found, the default text value is used instead. + text = get( message.args(), [ 0, '_remoteObject', 'description' ], text ); + + // Disable reason: We intentionally bubble up the console message + // which, unless the test explicitly anticipates the logging via + // @wordpress/jest-console matchers, will cause the intended test + // failure. + + // eslint-disable-next-line no-console + console[ logFunction ]( text ); + } ); +} + +// Before every test suite run, delete all content created by the test. This ensures +// other posts/comments/etc. aren't dirtying tests and tests don't depend on +// each other's side-effects. +beforeAll( async () => { + capturePageEventsForTearDown(); + enablePageDialogAccept(); + observeConsoleLogging(); + await setBrowserViewport( 'large' ); +} ); + +afterEach( async () => { + await clearLocalStorage(); + await setBrowserViewport( 'large' ); +} ); + +afterAll( () => { + removePageEvents(); +} ); diff --git a/tests/e2e/jest.config.js b/tests/e2e/jest.config.js index bfeca49f2ac..1ac91d4cbf0 100644 --- a/tests/e2e/jest.config.js +++ b/tests/e2e/jest.config.js @@ -1,17 +1,21 @@ module.exports = { - rootDir: '../../', ...require( '@wordpress/scripts/config/jest-e2e.config' ), + setupFilesAfterEnv: [ + '/config/bootstrap.js', + ], + testMatch: [ + '/specs/**/__tests__/**/*.js', + '/specs/**/?(*.)(spec|test).js', + '/specs/**/test/*.js', + ], transform: { - '^.+\\.[jt]sx?$': '/node_modules/@wordpress/scripts/config/babel-transform', + '^.+\\.[jt]sx?$': '/../../node_modules/@wordpress/scripts/config/babel-transform', }, - setupFilesAfterEnv: [ - '/node_modules/@wordpress/jest-preset-default/scripts/setup-test-framework.js', - 'expect-puppeteer', + transformIgnorePatterns: [ + 'node_modules', ], testPathIgnorePatterns: [ - '/.git', - '/node_modules', - '/build', - '.*/e2e/.*', + '.git', + 'node_modules', ], }; diff --git a/tests/e2e/specs/amp-options.test.js b/tests/e2e/specs/amp-options.test.js new file mode 100644 index 00000000000..94ee9ac376d --- /dev/null +++ b/tests/e2e/specs/amp-options.test.js @@ -0,0 +1,134 @@ +/** + * WordPress dependencies + */ +import { visitAdminPage, switchUserToAdmin, switchUserToTest } from '@wordpress/e2e-test-utils'; + +/** + * Deactivates an active plugin. + * + * Not using the provided deactivatePlugin() utility because it uses page.click(), + * which does not work if the element is not in the view or obscured by another element + * like an admin pointer. + * + * @param {string} slug Plugin slug. + */ +async function deactivatePlugin( slug ) { + await switchUserToAdmin(); + await visitAdminPage( 'plugins.php' ); + + await page.evaluate( ( plugin ) => { + const disableLink = document.querySelector( `tr[data-slug="${ plugin }"] .deactivate a` ); + + if ( disableLink ) { + disableLink.scrollIntoView(); + disableLink.click(); + } + }, slug ); + + await page.waitForSelector( `tr[data-slug="${ slug }"] .delete a` ); + await switchUserToTest(); +} + +/** + * Activates an installed plugin. + * + * Not using the provided activatePlugin() utility because it uses page.click(), + * which does not work if the element is not in the view or obscured by another element + * like an admin pointer. + * + * @param {string} slug Plugin slug. + */ +async function activatePlugin( slug ) { + await switchUserToAdmin(); + await visitAdminPage( 'plugins.php' ); + + const disableLink = await page.$( `tr[data-slug="${ slug }"] .deactivate a` ); + if ( disableLink ) { + return; + } + + await page.evaluate( ( plugin ) => { + const enableLink = document.querySelector( `tr[data-slug="${ plugin }"] .activate a` ); + + if ( enableLink ) { + enableLink.scrollIntoView(); + enableLink.click(); + } + }, slug ); + + await page.waitForSelector( `tr[data-slug="${ slug }"] .deactivate a` ); + await switchUserToTest(); +} + +describe( 'AMP Settings Screen', () => { + it( 'Should display a welcome notice', async () => { + await visitAdminPage( 'admin.php', 'page=amp-options' ); + const nodes = await page.$x( + '//*[contains(@class,"amp-welcome-notice")]//h1[contains(text(), "Welcome to AMP for WordPress")]' + ); + expect( nodes.length ).not.toEqual( 0 ); + } ); + + it( 'Should display a warning about missing object cache', async () => { + await visitAdminPage( 'admin.php', 'page=amp-options' ); + const nodes = await page.$x( + '//*[contains(@class,"notice-warning")]//p[contains(text(), "The AMP plugin performs at its best when persistent object cache is enabled")]' + ); + expect( nodes.length ).not.toEqual( 0 ); + } ); + + it( 'Should display a message about theme compatibility', async () => { + await visitAdminPage( 'admin.php', 'page=amp-options' ); + const nodes = await page.$x( + '//*[contains(@class,"notice-success")]//p[contains(text(), "Your active theme is known to work well in standard or transitional mode.")]' + ); + expect( nodes.length ).not.toEqual( 0 ); + } ); + + it( 'Should toggle Website Mode section', async () => { + await visitAdminPage( 'admin.php', 'page=amp-options' ); + + await page.evaluate( () => { + document.querySelector( 'tr.amp-website-mode' ).scrollIntoView(); + } ); + + const websiteModeSection = await page.$( 'tr.amp-website-mode' ); + + expect( await websiteModeSection.isIntersectingViewport() ).toBe( true ); + + await page.click( '#website_experience' ); + + expect( await websiteModeSection.isIntersectingViewport() ).toBe( false ); + } ); + + it( 'Requires at least one AMP experience to be selected', async () => { + await visitAdminPage( 'admin.php', 'page=amp-options' ); + + expect( await page.$eval( '#amp-settings', ( el ) => el.matches( `:invalid` ) ) ).toBe( false ); + + await page.click( '#website_experience' ); + + expect( await page.$eval( '#amp-settings', ( el ) => el.matches( `:invalid` ) ) ).toBe( true ); + } ); + + it( 'Should not allow AMP Stories to be enabled when Gutenberg is not active', async () => { + await deactivatePlugin( 'gutenberg' ); + + await visitAdminPage( 'admin.php', 'page=amp-options' ); + + expect( await page.$eval( '#stories_experience', ( el ) => el.matches( `:disabled` ) ) ).toBe( true ); + + const nodes = await page.$x( + '//*[contains(@class,"notice-info")]//p[contains(text(), "To use stories, you currently must have the latest version")]' + ); + expect( nodes.length ).not.toEqual( 0 ); + + await activatePlugin( 'gutenberg' ); + } ); + + it( 'Should allow AMP Stories to be enabled when Gutenberg is active', async () => { + await visitAdminPage( 'admin.php', 'page=amp-options' ); + + expect( await page.$eval( '#stories_experience', ( el ) => el.matches( `:disabled` ) ) ).toBe( false ); + } ); +} ); diff --git a/tests/e2e/specs/demo.test.js b/tests/e2e/specs/demo.test.js deleted file mode 100644 index 80d3fbfeb29..00000000000 --- a/tests/e2e/specs/demo.test.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * WordPress dependencies - */ -import { visitAdminPage, createURLMatcher, setUpResponseMocking, mockOrTransform } from '@wordpress/e2e-test-utils'; - -const MOCK_VIMEO_RESPONSE = { - url: 'https://vimeo.com/22439234', - html: '', - type: 'video', - provider_name: 'Vimeo', - provider_url: 'https://vimeo.com', - version: '1.0', -}; - -const couldNotBePreviewed = ( embedObject ) => { - return 'Embed Handler' === embedObject.provider_name; -}; - -const stripIframeFromEmbed = ( embedObject ) => { - return { ...embedObject, html: embedObject.html.replace( /src=[^\s]+/, '' ) }; -}; - -describe( 'new editor state', () => { - beforeAll( async () => { - setUpResponseMocking( [ - { - match: createURLMatcher( 'oembed%2F1.0%2Fproxy' ), - onRequestMatch: mockOrTransform( couldNotBePreviewed, MOCK_VIMEO_RESPONSE, stripIframeFromEmbed ), - }, - ] ); - await visitAdminPage( 'post-new.php', 'gutenberg-demo' ); - } ); - - it( 'content should load without making the post dirty', async () => { - const isDirty = await page.evaluate( () => { - const { select } = window.wp.data; - return select( 'core/editor' ).isEditedPostDirty(); - } ); - expect( isDirty ).toBeFalsy(); - } ); - - it( 'should be immediately saveable', async () => { - expect( await page.$( 'button.editor-post-save-draft' ) ).toBeTruthy(); - } ); -} ); diff --git a/tests/e2e/specs/hello.test.js b/tests/e2e/specs/hello.test.js new file mode 100644 index 00000000000..1ab0e02223d --- /dev/null +++ b/tests/e2e/specs/hello.test.js @@ -0,0 +1,14 @@ +/** + * WordPress dependencies + */ +import { visitAdminPage } from '@wordpress/e2e-test-utils'; + +describe( 'Hello World', () => { + it( 'Should load properly', async () => { + await visitAdminPage( '/' ); + const nodes = await page.$x( + '//h2[contains(text(), "Welcome to WordPress!")]' + ); + expect( nodes.length ).not.toEqual( 0 ); + } ); +} ); diff --git a/tests/e2e/specs/stories-admin-pointer.test.js b/tests/e2e/specs/stories-admin-pointer.test.js new file mode 100644 index 00000000000..e2ec7553145 --- /dev/null +++ b/tests/e2e/specs/stories-admin-pointer.test.js @@ -0,0 +1,14 @@ +/** + * WordPress dependencies + */ +import { visitAdminPage } from '@wordpress/e2e-test-utils'; + +describe( 'AMP Stories Admin Pointer', () => { + it( 'Should be displayed', async () => { + await visitAdminPage( '/' ); + const nodes = await page.$x( + '//*[contains(@class,"wp-amp-pointer")]//p[contains(text(), "You can now enable Stories")]' + ); + expect( nodes.length ).not.toEqual( 0 ); + } ); +} ); diff --git a/tests/unit/jest.config.js b/tests/js/jest.config.js similarity index 92% rename from tests/unit/jest.config.js rename to tests/js/jest.config.js index b4b04e5a7e6..feae25af707 100644 --- a/tests/unit/jest.config.js +++ b/tests/js/jest.config.js @@ -5,7 +5,7 @@ module.exports = { '^.+\\.[jt]sx?$': '/node_modules/@wordpress/scripts/config/babel-transform', }, setupFiles: [ - '/tests/unit/setup-globals', + '/tests/js/setup-globals', ], testPathIgnorePatterns: [ '/.git', diff --git a/tests/unit/setup-globals.js b/tests/js/setup-globals.js similarity index 100% rename from tests/unit/setup-globals.js rename to tests/js/setup-globals.js diff --git a/tests/assets/1024x768.png b/tests/php/assets/1024x768.png similarity index 100% rename from tests/assets/1024x768.png rename to tests/php/assets/1024x768.png diff --git a/tests/assets/350x150.png b/tests/php/assets/350x150.png similarity index 100% rename from tests/assets/350x150.png rename to tests/php/assets/350x150.png diff --git a/tests/assets/wordpress-logo.png b/tests/php/assets/wordpress-logo.png similarity index 100% rename from tests/assets/wordpress-logo.png rename to tests/php/assets/wordpress-logo.png diff --git a/tests/benchmark/run-benchmark.sh b/tests/php/benchmark/run-benchmark.sh similarity index 100% rename from tests/benchmark/run-benchmark.sh rename to tests/php/benchmark/run-benchmark.sh diff --git a/tests/stubs.php b/tests/php/stubs.php similarity index 100% rename from tests/stubs.php rename to tests/php/stubs.php diff --git a/tests/test-amp-analytics-options.php b/tests/php/test-amp-analytics-options.php similarity index 100% rename from tests/test-amp-analytics-options.php rename to tests/php/test-amp-analytics-options.php diff --git a/tests/test-amp-audio-converter.php b/tests/php/test-amp-audio-converter.php similarity index 100% rename from tests/test-amp-audio-converter.php rename to tests/php/test-amp-audio-converter.php diff --git a/tests/test-amp-crowdsignal-embed-handler.php b/tests/php/test-amp-crowdsignal-embed-handler.php similarity index 100% rename from tests/test-amp-crowdsignal-embed-handler.php rename to tests/php/test-amp-crowdsignal-embed-handler.php diff --git a/tests/test-amp-dailymotion-embed.php b/tests/php/test-amp-dailymotion-embed.php similarity index 100% rename from tests/test-amp-dailymotion-embed.php rename to tests/php/test-amp-dailymotion-embed.php diff --git a/tests/test-amp-facebook-embed.php b/tests/php/test-amp-facebook-embed.php similarity index 100% rename from tests/test-amp-facebook-embed.php rename to tests/php/test-amp-facebook-embed.php diff --git a/tests/test-amp-form-sanitizer.php b/tests/php/test-amp-form-sanitizer.php similarity index 100% rename from tests/test-amp-form-sanitizer.php rename to tests/php/test-amp-form-sanitizer.php diff --git a/tests/test-amp-helper-functions.php b/tests/php/test-amp-helper-functions.php similarity index 100% rename from tests/test-amp-helper-functions.php rename to tests/php/test-amp-helper-functions.php diff --git a/tests/test-amp-iframe-sanitizer.php b/tests/php/test-amp-iframe-sanitizer.php similarity index 100% rename from tests/test-amp-iframe-sanitizer.php rename to tests/php/test-amp-iframe-sanitizer.php diff --git a/tests/test-amp-image-dimension-extractor.php b/tests/php/test-amp-image-dimension-extractor.php similarity index 100% rename from tests/test-amp-image-dimension-extractor.php rename to tests/php/test-amp-image-dimension-extractor.php diff --git a/tests/test-amp-img-sanitizer.php b/tests/php/test-amp-img-sanitizer.php similarity index 100% rename from tests/test-amp-img-sanitizer.php rename to tests/php/test-amp-img-sanitizer.php diff --git a/tests/test-amp-instagram-embed.php b/tests/php/test-amp-instagram-embed.php similarity index 100% rename from tests/test-amp-instagram-embed.php rename to tests/php/test-amp-instagram-embed.php diff --git a/tests/test-amp-o2-player-sanitizer.php b/tests/php/test-amp-o2-player-sanitizer.php similarity index 100% rename from tests/test-amp-o2-player-sanitizer.php rename to tests/php/test-amp-o2-player-sanitizer.php diff --git a/tests/test-amp-pinterest-embed.php b/tests/php/test-amp-pinterest-embed.php similarity index 100% rename from tests/test-amp-pinterest-embed.php rename to tests/php/test-amp-pinterest-embed.php diff --git a/tests/test-amp-playbuzz-sanitizer.php b/tests/php/test-amp-playbuzz-sanitizer.php similarity index 100% rename from tests/test-amp-playbuzz-sanitizer.php rename to tests/php/test-amp-playbuzz-sanitizer.php diff --git a/tests/test-amp-render-post.php b/tests/php/test-amp-render-post.php similarity index 100% rename from tests/test-amp-render-post.php rename to tests/php/test-amp-render-post.php diff --git a/tests/test-amp-script-sanitizer.php b/tests/php/test-amp-script-sanitizer.php similarity index 100% rename from tests/test-amp-script-sanitizer.php rename to tests/php/test-amp-script-sanitizer.php diff --git a/tests/test-amp-soundcloud-embed.php b/tests/php/test-amp-soundcloud-embed.php similarity index 100% rename from tests/test-amp-soundcloud-embed.php rename to tests/php/test-amp-soundcloud-embed.php diff --git a/tests/test-amp-story-sanitizer.php b/tests/php/test-amp-story-sanitizer.php similarity index 100% rename from tests/test-amp-story-sanitizer.php rename to tests/php/test-amp-story-sanitizer.php diff --git a/tests/test-amp-style-sanitizer.php b/tests/php/test-amp-style-sanitizer.php similarity index 100% rename from tests/test-amp-style-sanitizer.php rename to tests/php/test-amp-style-sanitizer.php diff --git a/tests/test-amp-tag-and-attribute-sanitizer-private-methods.php b/tests/php/test-amp-tag-and-attribute-sanitizer-private-methods.php similarity index 100% rename from tests/test-amp-tag-and-attribute-sanitizer-private-methods.php rename to tests/php/test-amp-tag-and-attribute-sanitizer-private-methods.php diff --git a/tests/test-amp-twitter-embed.php b/tests/php/test-amp-twitter-embed.php similarity index 100% rename from tests/test-amp-twitter-embed.php rename to tests/php/test-amp-twitter-embed.php diff --git a/tests/test-amp-video-sanitizer.php b/tests/php/test-amp-video-sanitizer.php similarity index 100% rename from tests/test-amp-video-sanitizer.php rename to tests/php/test-amp-video-sanitizer.php diff --git a/tests/test-amp-vimeo-embed.php b/tests/php/test-amp-vimeo-embed.php similarity index 100% rename from tests/test-amp-vimeo-embed.php rename to tests/php/test-amp-vimeo-embed.php diff --git a/tests/test-amp-vine-embed.php b/tests/php/test-amp-vine-embed.php similarity index 100% rename from tests/test-amp-vine-embed.php rename to tests/php/test-amp-vine-embed.php diff --git a/tests/test-amp-youtube-embed.php b/tests/php/test-amp-youtube-embed.php similarity index 100% rename from tests/test-amp-youtube-embed.php rename to tests/php/test-amp-youtube-embed.php diff --git a/tests/test-amp.php b/tests/php/test-amp.php similarity index 100% rename from tests/test-amp.php rename to tests/php/test-amp.php diff --git a/tests/test-class-amp-admin-pointer.php b/tests/php/test-class-amp-admin-pointer.php similarity index 100% rename from tests/test-class-amp-admin-pointer.php rename to tests/php/test-class-amp-admin-pointer.php diff --git a/tests/test-class-amp-base-sanitizer.php b/tests/php/test-class-amp-base-sanitizer.php similarity index 100% rename from tests/test-class-amp-base-sanitizer.php rename to tests/php/test-class-amp-base-sanitizer.php diff --git a/tests/test-class-amp-block-sanitizer.php b/tests/php/test-class-amp-block-sanitizer.php similarity index 100% rename from tests/test-class-amp-block-sanitizer.php rename to tests/php/test-class-amp-block-sanitizer.php diff --git a/tests/test-class-amp-cli.php b/tests/php/test-class-amp-cli.php similarity index 100% rename from tests/test-class-amp-cli.php rename to tests/php/test-class-amp-cli.php diff --git a/tests/test-class-amp-comments-sanitizer.php b/tests/php/test-class-amp-comments-sanitizer.php similarity index 100% rename from tests/test-class-amp-comments-sanitizer.php rename to tests/php/test-class-amp-comments-sanitizer.php diff --git a/tests/test-class-amp-content-sanitizer.php b/tests/php/test-class-amp-content-sanitizer.php similarity index 100% rename from tests/test-class-amp-content-sanitizer.php rename to tests/php/test-class-amp-content-sanitizer.php diff --git a/tests/test-class-amp-core-block-handler.php b/tests/php/test-class-amp-core-block-handler.php similarity index 100% rename from tests/test-class-amp-core-block-handler.php rename to tests/php/test-class-amp-core-block-handler.php diff --git a/tests/test-class-amp-dom-utils.php b/tests/php/test-class-amp-dom-utils.php similarity index 100% rename from tests/test-class-amp-dom-utils.php rename to tests/php/test-class-amp-dom-utils.php diff --git a/tests/test-class-amp-editor-blocks.php b/tests/php/test-class-amp-editor-blocks.php similarity index 100% rename from tests/test-class-amp-editor-blocks.php rename to tests/php/test-class-amp-editor-blocks.php diff --git a/tests/test-class-amp-gallery-block-sanitizer.php b/tests/php/test-class-amp-gallery-block-sanitizer.php similarity index 100% rename from tests/test-class-amp-gallery-block-sanitizer.php rename to tests/php/test-class-amp-gallery-block-sanitizer.php diff --git a/tests/test-class-amp-gfycat-embed-handler.php b/tests/php/test-class-amp-gfycat-embed-handler.php similarity index 100% rename from tests/test-class-amp-gfycat-embed-handler.php rename to tests/php/test-class-amp-gfycat-embed-handler.php diff --git a/tests/test-class-amp-http.php b/tests/php/test-class-amp-http.php similarity index 100% rename from tests/test-class-amp-http.php rename to tests/php/test-class-amp-http.php diff --git a/tests/test-class-amp-hulu-embed-handler.php b/tests/php/test-class-amp-hulu-embed-handler.php similarity index 100% rename from tests/test-class-amp-hulu-embed-handler.php rename to tests/php/test-class-amp-hulu-embed-handler.php diff --git a/tests/test-class-amp-imgur-embed-handler.php b/tests/php/test-class-amp-imgur-embed-handler.php similarity index 100% rename from tests/test-class-amp-imgur-embed-handler.php rename to tests/php/test-class-amp-imgur-embed-handler.php diff --git a/tests/test-class-amp-meta-box.php b/tests/php/test-class-amp-meta-box.php similarity index 100% rename from tests/test-class-amp-meta-box.php rename to tests/php/test-class-amp-meta-box.php diff --git a/tests/test-class-amp-nav-menu-toggle-sanitizer.php b/tests/php/test-class-amp-nav-menu-toggle-sanitizer.php similarity index 100% rename from tests/test-class-amp-nav-menu-toggle-sanitizer.php rename to tests/php/test-class-amp-nav-menu-toggle-sanitizer.php diff --git a/tests/test-class-amp-options-manager.php b/tests/php/test-class-amp-options-manager.php similarity index 100% rename from tests/test-class-amp-options-manager.php rename to tests/php/test-class-amp-options-manager.php diff --git a/tests/test-class-amp-options-menu.php b/tests/php/test-class-amp-options-menu.php similarity index 100% rename from tests/test-class-amp-options-menu.php rename to tests/php/test-class-amp-options-menu.php diff --git a/tests/test-class-amp-playlist-embed-handler.php b/tests/php/test-class-amp-playlist-embed-handler.php similarity index 100% rename from tests/test-class-amp-playlist-embed-handler.php rename to tests/php/test-class-amp-playlist-embed-handler.php diff --git a/tests/test-class-amp-post-type-support.php b/tests/php/test-class-amp-post-type-support.php similarity index 100% rename from tests/test-class-amp-post-type-support.php rename to tests/php/test-class-amp-post-type-support.php diff --git a/tests/test-class-amp-service-worker.php b/tests/php/test-class-amp-service-worker.php similarity index 100% rename from tests/test-class-amp-service-worker.php rename to tests/php/test-class-amp-service-worker.php diff --git a/tests/test-class-amp-story-post-type.php b/tests/php/test-class-amp-story-post-type.php similarity index 100% rename from tests/test-class-amp-story-post-type.php rename to tests/php/test-class-amp-story-post-type.php diff --git a/tests/test-class-amp-story-templates.php b/tests/php/test-class-amp-story-templates.php similarity index 100% rename from tests/test-class-amp-story-templates.php rename to tests/php/test-class-amp-story-templates.php diff --git a/tests/test-class-amp-theme-support.php b/tests/php/test-class-amp-theme-support.php similarity index 100% rename from tests/test-class-amp-theme-support.php rename to tests/php/test-class-amp-theme-support.php diff --git a/tests/test-class-amp-vimeo-embed-handler.php b/tests/php/test-class-amp-vimeo-embed-handler.php similarity index 100% rename from tests/test-class-amp-vimeo-embed-handler.php rename to tests/php/test-class-amp-vimeo-embed-handler.php diff --git a/tests/test-class-amp-widget-archives.php b/tests/php/test-class-amp-widget-archives.php similarity index 100% rename from tests/test-class-amp-widget-archives.php rename to tests/php/test-class-amp-widget-archives.php diff --git a/tests/test-class-amp-widget-categories.php b/tests/php/test-class-amp-widget-categories.php similarity index 100% rename from tests/test-class-amp-widget-categories.php rename to tests/php/test-class-amp-widget-categories.php diff --git a/tests/test-class-amp-widget-text.php b/tests/php/test-class-amp-widget-text.php similarity index 100% rename from tests/test-class-amp-widget-text.php rename to tests/php/test-class-amp-widget-text.php diff --git a/tests/test-class-amp-youtube-embed-handler.php b/tests/php/test-class-amp-youtube-embed-handler.php similarity index 100% rename from tests/test-class-amp-youtube-embed-handler.php rename to tests/php/test-class-amp-youtube-embed-handler.php diff --git a/tests/test-tag-and-attribute-sanitizer.php b/tests/php/test-tag-and-attribute-sanitizer.php similarity index 87% rename from tests/test-tag-and-attribute-sanitizer.php rename to tests/php/test-tag-and-attribute-sanitizer.php index 9ee79d00202..3fd5ba482f0 100644 --- a/tests/test-tag-and-attribute-sanitizer.php +++ b/tests/php/test-tag-and-attribute-sanitizer.php @@ -20,82 +20,82 @@ class AMP_Tag_And_Attribute_Sanitizer_Test extends WP_UnitTestCase { */ public function get_body_data() { return array( - 'empty_doc' => array( + 'empty_doc' => array( '', '', ), - 'a-test' => array( + 'a-test' => array( 'Show Image', ), - 'a4a' => array( + 'a4a' => array( '
', null, // No change. array( 'amp-ad' ), ), - 'ads' => array( + 'ads' => array( '
', null, // No change. array( 'amp-ad' ), ), - 'adsense' => array( + 'adsense' => array( '
', null, // No change. array( 'amp-ad' ), ), - 'amp-3q-player' => array( + 'amp-3q-player' => array( '', null, array( 'amp-3q-player' ), ), - 'amp-ad' => array( + 'amp-ad' => array( '', null, // No change. array( 'amp-ad' ), ), - 'amp-sticky-ad' => array( + 'amp-sticky-ad' => array( '', null, array( 'amp-ad', 'amp-sticky-ad' ), ), - 'amp-sticky-ad-bad-children' => array( + 'amp-sticky-ad-bad-children' => array( 'not allowednot ok', '', array(), ), - 'amp-animation' => array( + 'amp-animation' => array( 'badvery bad', '', array( 'amp-animation' ), ), - 'amp-call-tracking' => array( + 'amp-call-tracking' => array( 'bad--and not great: +1 (23) 456-789more badnot great', '--and not great: +1 (23) 456-789not great', array( 'amp-call-tracking' ), ), - 'amp-call-tracking_blacklisted_config' => array( + 'amp-call-tracking_blacklisted_config' => array( '+1 (23) 456-789', '', array(), // Important: This needs to be empty because the amp-call-tracking is stripped. ), - 'amp-embed' => array( + 'amp-embed' => array( '', null, // No change. array( 'amp-ad' ), ), - 'amp-facebook-comments' => array( + 'amp-facebook-comments' => array( '', null, // No change. array( 'amp-facebook-comments' ), @@ -107,7 +107,7 @@ public function get_body_data() { array(), // Empty because invalid. ), - 'amp-facebook-like' => array( + 'amp-facebook-like' => array( '', null, // No change. array( 'amp-facebook-like' ), @@ -119,37 +119,37 @@ public function get_body_data() { array(), // Empty because invalid. ), - 'amp-fit-text' => array( + 'amp-fit-text' => array( 'Lorem ipsum', null, // No change. array( 'amp-fit-text' ), ), - 'amp-gist' => array( + 'amp-gist' => array( '', null, // No change. array( 'amp-gist' ), ), - 'amp-gist_missing_mandatory_attribute' => array( + 'amp-gist_missing_mandatory_attribute' => array( '', '', array(), ), - 'amp-iframe' => array( + 'amp-iframe' => array( '', null, // No change. array( 'amp-iframe' ), ), - 'amp-iframe_incorrect_protocol' => array( + 'amp-iframe_incorrect_protocol' => array( '', '', array( 'amp-iframe' ), ), - 'amp-ima-video' => array( + 'amp-ima-video' => array( ' @@ -162,86 +162,86 @@ public function get_body_data() { array( 'amp-ima-video' ), ), - 'amp-ima-video_missing_required_attribute' => array( + 'amp-ima-video_missing_required_attribute' => array( '', '', ), - 'amp-imgur' => array( + 'amp-imgur' => array( '', null, // No change. array( 'amp-imgur' ), ), - 'amp-install-serviceworker' => array( + 'amp-install-serviceworker' => array( '', null, // No change. array( 'amp-install-serviceworker' ), ), - 'amp-izlesene' => array( + 'amp-izlesene' => array( '', null, // No change. array( 'amp-izlesene' ), ), - 'amp-mathml' => array( + 'amp-mathml' => array( '', null, // No change. array( 'amp-mathml' ), ), - 'amp-riddle-quiz' => array( + 'amp-riddle-quiz' => array( '', null, // No change. array( 'amp-riddle-quiz' ), ), - 'amp-wistia-player' => array( + 'amp-wistia-player' => array( '', null, // No change. array( 'amp-wistia-player' ), ), - 'amp-byside-content' => array( + 'amp-byside-content' => array( '', null, // No change. array( 'amp-byside-content' ), ), - 'amp-bind-macro' => array( + 'amp-bind-macro' => array( '', null, // No change. array( 'amp-bind' ), ), - 'amp-nexxtv-player' => array( + 'amp-nexxtv-player' => array( '', null, // No change. array( 'amp-nexxtv-player' ), ), - 'amp-playbuzz' => array( + 'amp-playbuzz' => array( '', null, // No change. array( 'amp-playbuzz' ), ), - 'amp-playbuzz_no_src' => array( + 'amp-playbuzz_no_src' => array( '', null, // @todo This actually should be stripped because . array( 'amp-playbuzz' ), ), // AMP-NEXT-PAGE > [separator]. - 'reference-point-amp-next-page-separator' => array( + 'reference-point-amp-next-page-separator' => array( '

Keep reading

', null, array( 'amp-next-page' ), ), // amp-next-page extension .json configuration. - 'reference-point-amp-next-page-json-config' => array( + 'reference-point-amp-next-page-json-config' => array( '', null, array( 'amp-next-page' ), @@ -253,25 +253,25 @@ public function get_body_data() { array( 'amp-carousel', 'amp-lightbox-gallery' ), ), - 'reference-point-lightbox-thumbnail-id' => array( + 'reference-point-lightbox-thumbnail-id' => array( '', null, array( 'amp-lightbox-gallery' ), ), - 'lightbox-with-amp-carousel' => array( + 'lightbox-with-amp-carousel' => array( '', null, array( 'amp-lightbox-gallery', 'amp-carousel' ), ), - 'reference-points-amp-live-list' => array( + 'reference-points-amp-live-list' => array( '
', null, array( 'amp-live-list' ), ), - 'reference-points-amp-story' => call_user_func( + 'reference-points-amp-story' => call_user_func( function () { $html = str_replace( array( "\n", "\t" ), @@ -331,96 +331,96 @@ function () { } ), - 'reference-points-bad' => array( + 'reference-points-bad' => array( '
BAD REFERENCE POINTS
', '
BAD REFERENCE POINTS
', array(), ), - 'amp-position-observer' => array( + 'amp-position-observer' => array( '', null, // No change. array( 'amp-position-observer' ), ), - 'amp-twitter' => array( + 'amp-twitter' => array( '', null, // No change. array( 'amp-twitter' ), ), - 'amp-user-notification' => array( + 'amp-user-notification' => array( 'This site uses cookies to personalize content.I accept', 'This site uses cookies to personalize content.I accept', array( 'amp-user-notification' ), ), - 'amp-video' => array( + 'amp-video' => array( '', null, // No change. array( 'amp-video' ), ), - 'amp_video_children' => array( + 'amp_video_children' => array( '
Placeholder
Fallback
', null, // No change. array( 'amp-video' ), ), - 'amp_audio_children' => array( + 'amp_audio_children' => array( '
Placeholder
Fallback
', null, // No change. array( 'amp-audio' ), ), - 'amp-vk' => array( + 'amp-vk' => array( '', null, // No change. array( 'amp-vk' ), ), - 'amp-apester-media' => array( + 'amp-apester-media' => array( '', '', array( 'amp-apester-media' ), ), - 'button' => array( + 'button' => array( '', null, ), - 'brid-player' => array( + 'brid-player' => array( '', null, array( 'amp-brid-player' ), ), - 'brightcove' => array( + 'brightcove' => array( '', '', array( 'amp-brightcove' ), ), - 'carousel_slides' => array( + 'carousel_slides' => array( '
hello world
hello world
', '
hello world
hello world
', array( 'amp-anim', 'amp-audio', 'amp-brightcove', 'amp-carousel', 'amp-dailymotion', 'amp-soundcloud', 'amp-video', 'amp-vimeo', 'amp-vine', 'amp-youtube' ), ), - 'carousel_simple' => array( + 'carousel_simple' => array( '', null, array( 'amp-carousel' ), ), - 'carousel_lightbox' => array( + 'carousel_lightbox' => array( '', null, array( 'amp-bind', 'amp-carousel', 'amp-lightbox-gallery' ), ), - 'base_carousel' => array( + 'base_carousel' => array( '
first slide
@@ -431,75 +431,75 @@ function () { array( 'amp-base-carousel' ), ), - 'amp-dailymotion' => array( + 'amp-dailymotion' => array( '

Default (responsive)

Custom

', null, array( 'amp-dailymotion', 'amp-video-docking' ), ), // Try to test for NAME_VALUE_PARENT_DISPATCH. - 'amp_ima_video' => array( + 'amp_ima_video' => array( '', null, // No change. array( 'amp-ima-video' ), ), // Try to test for NAME_VALUE_DISPATCH. - 'doubleclick-1' => array( + 'doubleclick-1' => array( '', '', array( 'amp-ad' ), ), // Try to test for NAME_DISPATCH. - 'nav_dispatch_key' => array( + 'nav_dispatch_key' => array( '', null, ), - 'json_linked_data' => array( + 'json_linked_data' => array( '', null, // No Change. ), - 'json_linked_data_with_bad_cdata' => array( + 'json_linked_data_with_bad_cdata' => array( '', '', ), - 'facebook' => array( + 'facebook' => array( '

More Posts

', '

More Posts

', array( 'amp-facebook' ), ), - 'font' => array( + 'font' => array( '', '', array( 'amp-font' ), ), - 'form' => array( + 'form' => array( '
', '
', array( 'amp-form' ), ), - 'gfycat' => array( + 'gfycat' => array( '', '', array( 'amp-gfycat' ), ), - 'h2' => array( + 'h2' => array( '

Example Text

', ), - 'empty_element' => array( + 'empty_element' => array( '
', ), - 'merge_two_attr_specs' => array( + 'merge_two_attr_specs' => array( '
Whatever
', '
Whatever
', ), @@ -509,15 +509,15 @@ function () { 'Click me.', ), - 'host_relative_url_allowed' => array( + 'host_relative_url_allowed' => array( 'Click me.', ), - 'protocol_relative_url_allowed' => array( + 'protocol_relative_url_allowed' => array( 'Click me.', ), - 'node_with_whiteilsted_protocol_http_allowed' => array( + 'node_with_whiteilsted_protocol_http_allowed' => array( 'Click me.', ), @@ -537,20 +537,20 @@ function () { ), ), - 'attribute_value_valid' => array( + 'attribute_value_valid' => array( '', null, array( 'amp-mustache' ), ), - 'attribute_value_invalid' => array( + 'attribute_value_invalid' => array( // type is mandatory, so the node is removed. '', '', array(), // No scripts because removed. ), - 'attribute_amp_accordion_value' => call_user_func( + 'attribute_amp_accordion_value' => call_user_func( function() { $html = str_replace( array( "\n", "\t" ), @@ -599,7 +599,7 @@ function() { 'Click me.', ), - 'attribute_value_with_required_regex' => array( + 'attribute_value_with_required_regex' => array( 'Click me.', ), @@ -644,13 +644,13 @@ function() { array( 'amp-dailymotion' ), ), - 'attribute_bad_attr_with_no_value_removed' => array( + 'attribute_bad_attr_with_no_value_removed' => array( '
something here
', '
something here
', array( 'amp-ad' ), ), - 'attribute_bad_attr_with_value_removed' => array( + 'attribute_bad_attr_with_value_removed' => array( 'something here', 'something here', array( 'amp-ad' ), @@ -662,22 +662,22 @@ function() { '', ), - 'remove_node_without_mandatory_attribute' => array( + 'remove_node_without_mandatory_attribute' => array( '', '', ), - 'remove_script_with_async_attribute' => array( + 'remove_script_with_async_attribute' => array( '', // phpcs:ignore '', ), - 'remove_invalid_json_script' => array( + 'remove_invalid_json_script' => array( '', '', ), - 'allow_node_with_valid_mandatory_attribute' => array( + 'allow_node_with_valid_mandatory_attribute' => array( '', null, // No change. array( 'amp-analytics' ), @@ -698,7 +698,7 @@ function() { '
', ), - 'replace_non_whitelisted_node_with_children' => array( + 'replace_non_whitelisted_node_with_children' => array( '

This is some text with a disallowed tag in the middle of it.

', '

This is some text with a disallowed tag in the middle of it.

', ), @@ -714,13 +714,13 @@ function() { array( 'amp-form' ), ), - 'disallowed_empty_attr_removed' => array( + 'disallowed_empty_attr_removed' => array( '', '', array( 'amp-user-notification' ), ), - 'allowed_empty_attr' => array( + 'allowed_empty_attr' => array( '', ), @@ -730,7 +730,7 @@ function() { array( 'amp-sidebar' ), ), - 'amp_story_with_amp_sidebar' => array( + 'amp_story_with_amp_sidebar' => array( str_replace( array( "\n", "\t" ), '', @@ -756,7 +756,7 @@ function() { array( 'amp-sidebar', 'amp-story' ), ), - 'amp_sidebar_with_autoscroll' => array( + 'amp_sidebar_with_autoscroll' => array( str_replace( array( "\n", "\t" ), '', @@ -780,12 +780,12 @@ function() { array( 'amp-sidebar' ), ), - 'remove_node_without_mandatory_ancestor' => array( + 'remove_node_without_mandatory_ancestor' => array( '
All I have is this div, when all you want is a noscript tag.
', '
All I have is this div, when all you want is a noscript tag.
', ), - 'amp-img_with_good_protocols' => array( + 'amp-img_with_good_protocols' => array( '', ), @@ -793,44 +793,44 @@ function() { '', ), - 'allowed_tag_only' => array( + 'allowed_tag_only' => array( '

Text

', '

Text

', ), - 'disallowed_attributes' => array( + 'disallowed_attributes' => array( 'Link', 'Link', ), - 'onclick_attribute' => array( + 'onclick_attribute' => array( 'Link', 'Link', ), - 'on_attribute' => array( + 'on_attribute' => array( '', ), - 'multiple_disallowed_attributes' => array( + 'multiple_disallowed_attributes' => array( 'Link', 'Link', ), - 'attribute_recursive' => array( + 'attribute_recursive' => array( '', '', ), - 'no_strip_amp_tags' => array( + 'no_strip_amp_tags' => array( '', ), - 'a_with_attachment_rel' => array( + 'a_with_attachment_rel' => array( 'Link', ), - 'a_with_invalid_name' => array( + 'a_with_invalid_name' => array( 'Shadow Root!', 'Shadow Root!', ), @@ -839,66 +839,66 @@ function() { 'Link', ), - 'a_with_rev' => array( + 'a_with_rev' => array( 'Link', ), - 'a_with_target_blank' => array( + 'a_with_target_blank' => array( 'Link', ), - 'a_with_target_uppercase_blank' => array( + 'a_with_target_uppercase_blank' => array( 'Link', 'Link', ), - 'a_with_target_new' => array( + 'a_with_target_new' => array( 'Link', 'Link', ), - 'a_with_target_self' => array( + 'a_with_target_self' => array( 'Link', ), - 'a_with_target_invalid' => array( + 'a_with_target_invalid' => array( 'Link', 'Link', ), - 'a_with_href_invalid' => array( + 'a_with_href_invalid' => array( 'Link', ), - 'a_with_href_scheme_tel' => array( + 'a_with_href_scheme_tel' => array( 'Call Me, Maybe', ), - 'a_with_href_scheme_sms' => array( + 'a_with_href_scheme_sms' => array( 'SMS Me, Maybe', ), - 'a_with_href_scheme_mailto' => array( + 'a_with_href_scheme_mailto' => array( 'Email Me, Maybe', ), - 'a_with_href_relative' => array( + 'a_with_href_relative' => array( 'Home', ), - 'a_with_anchor' => array( + 'a_with_anchor' => array( 'Home', ), - 'a_is_anchor' => array( + 'a_is_anchor' => array( '', ), - 'a_is_achor_with_id' => array( + 'a_is_achor_with_id' => array( '', ), - 'a_empty' => array( + 'a_empty' => array( 'Hello World', ), @@ -907,85 +907,85 @@ function() { 'Red&Orange', ), - 'spans_with_xml_namespaced_attributes' => array( + 'spans_with_xml_namespaced_attributes' => array( '

holamundo

', '

holamundo

', ), - 'h1_with_size' => array( + 'h1_with_size' => array( '

Headline

', '

Headline

', ), - 'font_tag' => array( + 'font_tag' => array( 'Headline', 'Headline', ), - 'span_with_custom_attr' => array( + 'span_with_custom_attr' => array( 'value', 'value', ), - 'a_with_custom_protocol' => array( + 'a_with_custom_protocol' => array( 'value', 'value', ), - 'a_with_wrong_host' => array( + 'a_with_wrong_host' => array( 'value', 'value', ), - 'a_with_encoded_host' => array( + 'a_with_encoded_host' => array( 'value', null, ), - 'a_with_wrong_schemeless_host' => array( + 'a_with_wrong_schemeless_host' => array( 'value', 'value', ), - 'a_with_mail_host' => array( + 'a_with_mail_host' => array( 'value', 'value', ), // font is removed so we should check that other elements are checked as well. - 'font_with_other_bad_elements' => array( + 'font_with_other_bad_elements' => array( 'HeadlineSpan', 'HeadlineSpan', ), - 'amp_bind_attr' => array( + 'amp_bind_attr' => array( '

Hello World

', null, // No change. array( 'amp-bind' ), ), - 'amp_bind_with_greater_than_symbol' => array( + 'amp_bind_with_greater_than_symbol' => array( '', '', array( 'amp-bind' ), ), - 'amp_bad_bind_attr' => array( + 'amp_bad_bind_attr' => array( 'test

', 'test

', array( 'amp-bind' ), ), - 'amp-state' => array( + 'amp-state' => array( '', null, array( 'amp-bind' ), ), - 'amp-state-bad' => array( + 'amp-state-bad' => array( 'bad', '', array(), ), - 'amp-state-src' => array( + 'amp-state-src' => array( '', null, array( 'amp-bind' ), @@ -1037,37 +1037,37 @@ function() { array( 'amp-selector', 'amp-form', 'amp-carousel' ), ), - 'amp_live_list_sort' => array( + 'amp_live_list_sort' => array( '
Hello
', null, // No change. array( 'amp-live-list' ), ), - 'amp_consent' => array( + 'amp_consent' => array( '', null, // No change. array( 'amp-consent' ), ), - 'amp_date_picker' => array( + 'amp_date_picker' => array( '
', null, // No change. array( 'amp-date-picker' ), ), - 'amp_date_picker_range' => array( + 'amp_date_picker_range' => array( '
', null, // No change. array( 'amp-date-picker', 'amp-bind', 'amp-mustache' ), ), - 'amp-delight-player' => array( + 'amp-delight-player' => array( '', null, // No change. array( 'amp-delight-player' ), ), - 'amp-img-layout-allowed' => array( + 'amp-img-layout-allowed' => array( implode( '', array( @@ -1084,43 +1084,43 @@ function() { array(), ), - 'amp-img-layout-illegal' => array( + 'amp-img-layout-illegal' => array( '', '', array(), ), - 'amp-img-layout-unknown' => array( + 'amp-img-layout-unknown' => array( '', '', array(), ), - 'non-layout-span-element-attrs' => array( + 'non-layout-span-element-attrs' => array( 'Test', 'Test', array(), ), - 'non-layout-col-element-attrs' => array( + 'non-layout-col-element-attrs' => array( '
123
', '
123
', array(), ), - 'amp-geo' => array( + 'amp-geo' => array( '', null, array( 'amp-geo' ), ), - 'amp-geo-bad-children' => array( + 'amp-geo-bad-children' => array( '
bad
', '', array(), ), - 'amp-addthis-valid' => array( + 'amp-addthis-valid' => array( ' array( + 'amp-addthis-responsive-layout' => array( ' array( + 'amp-addthis-custom-share-attributes' => array( ' array( + 'amp-addthis-wordpress-mode' => array( ' array( + 'amp-addthis-inline-using-widget-id' => array( ' array( + 'amp-addthis-inline-using-product-code' => array( ' array( + 'amp-addthis-floating-using-product-code' => array( ' array( + 'amp-addthis-with-invalid-attribute' => array( '', '', array( 'amp-addthis' ), ), - 'amp-3d-gltf' => array( + 'amp-3d-gltf' => array( '', null, array( 'amp-3d-gltf' ), ), - 'amp-date-countdown' => array( + 'amp-date-countdown' => array( '', null, array( 'amp-date-countdown', 'amp-mustache' ), ), - 'amp-google-document-embed' => array( + 'amp-google-document-embed' => array( '', null, array( 'amp-google-document-embed' ), ), - 'amp-orientation-observer' => array( + 'amp-orientation-observer' => array( '', null, array( 'amp-orientation-observer' ), ), - 'amp-pan-zoom' => array( + 'amp-pan-zoom' => array( ' ... ', null, array( 'amp-pan-zoom' ), ), - 'amp-yotpo' => array( + 'amp-yotpo' => array( '', null, array( 'amp-yotpo' ), ), - 'amp-embedly' => array( + 'amp-embedly' => array( '', null, array( 'amp-embedly-card' ), ), - 'amp-lightbox' => array( + 'amp-lightbox' => array( '', null, array( 'amp-lightbox', 'amp-bind' ), ), - 'amp-form-messages' => array( + 'amp-form-messages' => array( '
', null, array( 'amp-form', 'amp-mustache' ), ), - 'amp-input-mask' => array( + 'amp-input-mask' => array( '
', null, array( 'amp-form', 'amp-inputmask', 'amp-mustache' ), ), - 'amp_textarea_without_autoexpand' => array( + 'amp_textarea_without_autoexpand' => array( '', null, array(), @@ -1311,43 +1311,43 @@ function() { array( 'amp-form', 'amp-bind' ), ), - 'amp-viqeo-player' => array( + 'amp-viqeo-player' => array( '', null, array( 'amp-viqeo-player' ), ), - 'amp-image-slider' => array( + 'amp-image-slider' => array( 'Not allowedforbidden
This apple is green
not allowed
This apple is red
not ok
', '
This apple is green
This apple is red
', array( 'amp-image-slider' ), ), - 'amp-image-slider-bad-children' => array( + 'amp-image-slider-bad-children' => array( '', '', array(), ), - 'amp-fx-collection' => array( + 'amp-fx-collection' => array( '

A title that moves faster than other content.

', null, array( 'amp-fx-collection' ), ), - 'amp-date-display' => array( + 'amp-date-display' => array( '', null, array( 'amp-date-display', 'amp-mustache' ), ), - 'amp-list' => array( + 'amp-list' => array( '', null, array( 'amp-list', 'amp-mustache' ), ), - 'amp-list-load-more' => array( + 'amp-list-load-more' => array( str_replace( array( "\n", "\t" ), '', @@ -1375,38 +1375,38 @@ function() { array( 'amp-list', 'amp-mustache' ), ), - 'amp-recaptcha-input' => array( + 'amp-recaptcha-input' => array( '
', null, array( 'amp-form', 'amp-recaptcha-input' ), ), // @todo The poster should not be allowed if there is a placeholder. - 'amp-video-iframe' => array( + 'amp-video-iframe' => array( '', null, array( 'amp-video-iframe', 'amp-video-docking' ), ), - 'amp-youtube' => array( + 'amp-youtube' => array( '', null, array( 'amp-youtube', 'amp-video-docking' ), ), - 'details' => array( + 'details' => array( '
Learn more

You are educated

', null, array( 'amp-bind' ), ), - 'amp-plain-text-script-template' => array( + 'amp-plain-text-script-template' => array( '', null, array( 'amp-mustache' ), ), - 'amp-action-macro' => array( + 'amp-action-macro' => array( // @todo Should calling AMP.setState() automatically cause the amp-bind extension to be added? ' @@ -1417,18 +1417,18 @@ function() { array( 'amp-action-macro' ), ), - 'amp-smart-links' => array( + 'amp-smart-links' => array( '', null, array( 'amp-smartlinks' ), ), - 'amp-script-1' => array( + 'amp-script-1' => array( '', null, array( 'amp-script' ), ), - 'amp-script-2' => array( + 'amp-script-2' => array( '
@@ -1443,7 +1443,7 @@ function() { null, array( 'amp-script' ), ), - 'amp-script-3' => array( + 'amp-script-3' => array( '

todos

@@ -1453,7 +1453,7 @@ function() { array( 'amp-script' ), ), - 'amp-script-4' => array( + 'amp-script-4' => array( '
should be empty
@@ -1463,26 +1463,26 @@ function() { array( 'amp-script' ), ), - 'amp_img_with_object_fit_position' => array( + 'amp_img_with_object_fit_position' => array( '', null, array(), ), - 'amp_link_rewriter' => array( + 'amp_link_rewriter' => array( '', null, array( 'amp-link-rewriter' ), ), - 'unique_constraint' => array( + 'unique_constraint' => array( str_repeat( '', 2 ), '', array( 'amp-geo' ), array( 'duplicate_element' ), ), - 'amp-autocomplete' => array( + 'amp-autocomplete' => array( '
@@ -1497,13 +1497,13 @@ function() { array( 'amp-form', 'amp-autocomplete' ), ), - 'amp-connatix-player' => array( + 'amp-connatix-player' => array( '', null, array( 'amp-connatix-player' ), ), - 'amp-truncate-text' => array( + 'amp-truncate-text' => array( ' Some text that may get truncated. @@ -1515,7 +1515,7 @@ function() { array( 'amp-truncate-text' ), ), - 'amp-user-location' => array( + 'amp-user-location' => array( ' diff --git a/tests/validation/test-class-amp-validated-url-post-type.php b/tests/php/validation/test-class-amp-validated-url-post-type.php similarity index 100% rename from tests/validation/test-class-amp-validated-url-post-type.php rename to tests/php/validation/test-class-amp-validated-url-post-type.php diff --git a/tests/validation/test-class-amp-validation-error-taxonomy.php b/tests/php/validation/test-class-amp-validation-error-taxonomy.php similarity index 100% rename from tests/validation/test-class-amp-validation-error-taxonomy.php rename to tests/php/validation/test-class-amp-validation-error-taxonomy.php diff --git a/tests/validation/test-class-amp-validation-manager.php b/tests/php/validation/test-class-amp-validation-manager.php similarity index 100% rename from tests/validation/test-class-amp-validation-manager.php rename to tests/php/validation/test-class-amp-validation-manager.php