diff --git a/.phpstorm.meta.php b/.phpstorm.meta.php index 0065d6e2990..c65e3ae2f92 100644 --- a/.phpstorm.meta.php +++ b/.phpstorm.meta.php @@ -54,7 +54,6 @@ 'rest.scannable_urls_controller' => \AmpProject\AmpWP\Validation\ScannableURLsRestController::class, 'rest.validation_counts_controller' => \AmpProject\AmpWP\Validation\ValidationCountsRestController::class, 'sandboxing' => \AmpProject\AmpWP\Sandboxing::class, - 'save_post_validation_event' => \AmpProject\AmpWP\Validation\SavePostValidationEvent::class, 'server_timing' => \AmpProject\AmpWP\Instrumentation\ServerTiming::class, 'site_health_integration' => \AmpProject\AmpWP\Admin\SiteHealth::class, 'support' => \AmpProject\AmpWP\Support\SupportCliCommand::class, diff --git a/assets/src/admin/site-scan-notice/index.js b/assets/src/admin/site-scan-notice/index.js index 74c5b6d44c3..ff73fd6d559 100644 --- a/assets/src/admin/site-scan-notice/index.js +++ b/assets/src/admin/site-scan-notice/index.js @@ -49,7 +49,7 @@ function Providers( { children } ) { optionsRestPath={ OPTIONS_REST_PATH } populateDefaultValues={ false } > - + ); diff --git a/assets/src/components/site-scan-results/themes-with-amp-incompatibility.js b/assets/src/components/site-scan-results/themes-with-amp-incompatibility.js index c12068ad263..4b0a11b1051 100644 --- a/assets/src/components/site-scan-results/themes-with-amp-incompatibility.js +++ b/assets/src/components/site-scan-results/themes-with-amp-incompatibility.js @@ -72,7 +72,7 @@ export function ThemesWithAmpIncompatibility( { ); diff --git a/assets/src/components/themes-context-provider/index.js b/assets/src/components/themes-context-provider/index.js index ffd57c2243b..24bb6d8d6cc 100644 --- a/assets/src/components/themes-context-provider/index.js +++ b/assets/src/components/themes-context-provider/index.js @@ -6,39 +6,22 @@ import PropTypes from 'prop-types'; /** * WordPress dependencies */ -import { - createContext, - useContext, - useEffect, - useRef, - useState, -} from '@wordpress/element'; +import { createContext, useEffect, useRef, useState } from '@wordpress/element'; import apiFetch from '@wordpress/api-fetch'; - -/** - * Internal dependencies - */ -import { ErrorContext } from '../error-context-provider'; -import { useAsyncError } from '../../utils/use-async-error'; +import { addQueryArgs } from '@wordpress/url'; export const Themes = createContext(); /** * Themes context provider. * - * @param {Object} props Component props. - * @param {any} props.children Component children. - * @param {boolean} props.hasErrorBoundary Whether the component is wrapped in an error boundary. + * @param {Object} props Component props. + * @param {any} props.children Component children. */ -export function ThemesContextProvider( { - children, - hasErrorBoundary = false, -} ) { +export function ThemesContextProvider( { children } ) { const [ themes, setThemes ] = useState( [] ); const [ fetchingThemes, setFetchingThemes ] = useState( null ); - - const { error, setError } = useContext( ErrorContext ); - const { setAsyncError } = useAsyncError(); + const [ error, setError ] = useState(); /** * This component sets state inside async functions. @@ -62,7 +45,9 @@ export function ThemesContextProvider( { try { const fetchedThemes = await apiFetch( { - path: '/wp/v2/themes', + path: addQueryArgs( '/wp/v2/themes', { + _fields: [ 'author', 'name', 'status', 'stylesheet', 'version' ], + } ), } ); if ( hasUnmounted.current === true ) { @@ -76,17 +61,11 @@ export function ThemesContextProvider( { } setError( e ); - - if ( hasErrorBoundary ) { - setAsyncError( e ); - } - - return; } setFetchingThemes( false ); } )(); - }, [ error, fetchingThemes, hasErrorBoundary, themes, setAsyncError, setError ] ); + }, [ error, fetchingThemes, themes ] ); return ( - - + + - - + + - + { HAS_DEPENDENCY_SUPPORT && ( + + ) } diff --git a/includes/admin/functions.php b/includes/admin/functions.php index e2d53bfac64..3e0a29fa962 100644 --- a/includes/admin/functions.php +++ b/includes/admin/functions.php @@ -5,8 +5,10 @@ * @package AMP */ +use AmpProject\AmpWP\DependencySupport; use AmpProject\AmpWP\Option; use AmpProject\AmpWP\QueryVar; +use AmpProject\AmpWP\Services; /** * Sets up the AMP template editor for the Customizer. @@ -15,6 +17,39 @@ */ function amp_init_customizer() { + if ( ! Services::get( 'dependency_support' )->has_support() ) { + // @codeCoverageIgnoreStart + add_action( + 'customize_controls_init', + static function () { + global $wp_customize; + if ( + Services::get( 'reader_theme_loader' )->is_theme_overridden() + || + array_intersect( $wp_customize->get_autofocus(), [ 'panel' => AMP_Template_Customizer::PANEL_ID ] ) + || + isset( $_GET[ QueryVar::AMP_PREVIEW ] ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended + ) { + wp_die( + esc_html( + sprintf( + /* translators: %s is minimum WordPress version */ + __( 'Customizer for AMP is unavailable due to WordPress being out of date. Please upgrade to WordPress %s or greater.', 'amp' ), + DependencySupport::WP_MIN_VERSION + ) + ), + esc_html__( 'AMP Customizer Unavailable', 'amp' ), + [ + 'response' => 503, + 'back_link' => true, + ] + ); + } + } + ); + // @codeCoverageIgnoreEnd + } + // Fire up the AMP Customizer. add_action( 'customize_register', [ AMP_Template_Customizer::class, 'init' ], 500 ); diff --git a/includes/amp-helper-functions.php b/includes/amp-helper-functions.php index 060ed4e20f1..5d7cf737f99 100644 --- a/includes/amp-helper-functions.php +++ b/includes/amp-helper-functions.php @@ -92,6 +92,11 @@ function amp_bootstrap_plugin() { // Ensure async and custom-element/custom-template attributes are present on script tags. add_filter( 'script_loader_tag', 'amp_filter_script_loader_tag', PHP_INT_MAX, 2 ); + // Ensure ID attribute is present in WP<5.5. + if ( version_compare( get_bloginfo( 'version' ), '5.5', '<' ) ) { + add_filter( 'script_loader_tag', 'amp_ensure_id_attribute_on_script_loader_tag', ~PHP_INT_MAX, 2 ); + } + // Ensure crossorigin=anonymous is added to font links. add_filter( 'style_loader_tag', 'amp_filter_font_style_loader_tag_with_crossorigin_anonymous', 10, 4 ); @@ -1157,6 +1162,35 @@ function amp_filter_script_loader_tag( $tag, $handle ) { return $tag; } +/** + * Ensure ID attribute is added to printed scripts. + * + * Core started adding the ID attribute in WP 5.5. This attribute is used both by validation logic for sourcing + * attribution as well as in the script and comments sanitizers. + * + * @link https://core.trac.wordpress.org/changeset/48295 + * @since 2.2 + * @internal + * + * @param string $tag The script tag for the enqueued script. + * @param string $handle The script's registered handle. + * @return string Filtered script. + */ +function amp_ensure_id_attribute_on_script_loader_tag( $tag, $handle ) { + $tag = preg_replace_callback( + '/(]*?\ssrc=(["\']).*?\2)([^>]*?>)/', + static function ( $matches ) use ( $handle ) { + if ( false === strpos( $matches[0], 'id=' ) ) { + return $matches[1] . sprintf( ' id="%s"', esc_attr( "$handle-js" ) ) . $matches[3]; + } + return $matches[0]; + }, + $tag, + 1 + ); + return $tag; +} + /** * Explicitly opt-in to CORS mode by adding the crossorigin attribute to font stylesheet links. * diff --git a/includes/settings/class-amp-customizer-design-settings.php b/includes/settings/class-amp-customizer-design-settings.php index 28e91e3802e..205315b9c3e 100644 --- a/includes/settings/class-amp-customizer-design-settings.php +++ b/includes/settings/class-amp-customizer-design-settings.php @@ -6,6 +6,7 @@ */ use AmpProject\AmpWP\Option; +use AmpProject\AmpWP\Services; /** * Class AMP_Customizer_Design_Settings @@ -72,6 +73,9 @@ public static function init() { * Init customizer. */ public static function init_customizer() { + if ( ! Services::get( 'dependency_support' )->has_support() ) { + return; + } add_action( 'amp_customizer_register_settings', [ __CLASS__, 'register_customizer_settings' ] ); add_action( 'amp_customizer_register_ui', [ __CLASS__, 'register_customizer_ui' ] ); add_action( 'amp_customizer_enqueue_preview_scripts', [ __CLASS__, 'enqueue_customizer_preview_scripts' ] ); diff --git a/includes/validation/class-amp-validation-manager.php b/includes/validation/class-amp-validation-manager.php index af072d1b800..4ab6746c055 100644 --- a/includes/validation/class-amp-validation-manager.php +++ b/includes/validation/class-amp-validation-manager.php @@ -666,7 +666,20 @@ public static function add_validation_error_sourcing() { add_filter( 'do_shortcode_tag', [ __CLASS__, 'decorate_shortcode_source' ], PHP_INT_MAX, 2 ); add_filter( 'embed_oembed_html', [ __CLASS__, 'decorate_embed_source' ], PHP_INT_MAX, 3 ); - add_filter( 'the_content', [ __CLASS__, 'add_block_source_comments' ], 8 ); // The do_blocks() function runs at priority 9. + + // The `WP_Block_Type_Registry` class was added in WordPress 5.0.0. Because of that it sometimes caused issues + // on the AMP Validated URL screen when on WordPress 4.9. + if ( class_exists( 'WP_Block_Type_Registry' ) ) { + add_filter( + 'the_content', + [ + __CLASS__, + 'add_block_source_comments', + ], + 8 + ); // The do_blocks() function runs at priority 9. + } + add_filter( 'the_editor', [ __CLASS__, 'filter_the_editor_to_detect_sources' ] ); } @@ -938,9 +951,16 @@ protected static function has_dependency( WP_Dependencies $dependencies, $curren * @return bool */ protected static function is_matching_script( DOMElement $element, $script_handle ) { + + // Use the ID attribute which was added to printed scripts after WP ?.?. + if ( $element->getAttribute( Attribute::ID ) === "{$script_handle}-js" ) { + return true; + } + if ( ! isset( wp_scripts()->registered[ $script_handle ] ) ) { return false; } + $script_dependency = wp_scripts()->registered[ $script_handle ]; if ( empty( $script_dependency->src ) ) { return false; @@ -989,7 +1009,7 @@ public static function locate_sources( DOMNode $node ) { && 'link' === $node->nodeName && - preg_match( '/(?P.+)-css$/', (string) $node->getAttribute( 'id' ), $matches ) + preg_match( '/(?P.+)-css$/', (string) $node->getAttribute( Attribute::ID ), $matches ) && wp_styles()->query( $matches['handle'] ) ); @@ -1034,9 +1054,9 @@ static function ( $enqueued_style_source ) use ( $style_handle ) { && $node->firstChild instanceof DOMText && - $node->hasAttribute( 'id' ) + $node->hasAttribute( Attribute::ID ) && - preg_match( '/^(?P.+)-inline-css$/', $node->getAttribute( 'id' ), $matches ) + preg_match( '/^(?P.+)-inline-css$/', $node->getAttribute( Attribute::ID ), $matches ) && wp_styles()->query( $matches['handle'] ) && diff --git a/src/Admin/AmpPlugins.php b/src/Admin/AmpPlugins.php index 7162803c73e..ab71d942a39 100644 --- a/src/Admin/AmpPlugins.php +++ b/src/Admin/AmpPlugins.php @@ -9,8 +9,10 @@ use AmpProject\AmpWP\Infrastructure\Conditional; use AmpProject\AmpWP\Infrastructure\Delayed; +use AmpProject\AmpWP\Infrastructure\HasRequirements; use AmpProject\AmpWP\Infrastructure\Registerable; use AmpProject\AmpWP\Infrastructure\Service; +use AmpProject\AmpWP\Services; use WP_Screen; use function get_current_screen; use stdClass; @@ -21,7 +23,7 @@ * @since 2.2 * @internal */ -class AmpPlugins implements Conditional, Delayed, Service, Registerable { +class AmpPlugins implements Conditional, Delayed, HasRequirements, Service, Registerable { /** * Slug for amp-compatible. @@ -54,6 +56,15 @@ public static function get_registration_action() { return 'current_screen'; } + /** + * Get the list of service IDs required for this service to be registered. + * + * @return string[] List of required services. + */ + public static function get_requirements() { + return [ 'dependency_support' ]; + } + /** * Check whether the conditional object is currently needed. * @@ -61,6 +72,10 @@ public static function get_registration_action() { */ public static function is_needed() { + if ( ! Services::get( 'dependency_support' )->has_support() ) { + return false; + } + /** This filter is documented in src/Admin/AmpThemes.php */ return is_admin() && apply_filters( 'amp_compatible_ecosystem_shown', true, 'plugins' ); } diff --git a/src/Admin/AmpThemes.php b/src/Admin/AmpThemes.php index 7f4a25ecf2c..73aebd9ed7d 100644 --- a/src/Admin/AmpThemes.php +++ b/src/Admin/AmpThemes.php @@ -9,8 +9,10 @@ use AmpProject\AmpWP\Infrastructure\Conditional; use AmpProject\AmpWP\Infrastructure\Delayed; +use AmpProject\AmpWP\Infrastructure\HasRequirements; use AmpProject\AmpWP\Infrastructure\Registerable; use AmpProject\AmpWP\Infrastructure\Service; +use AmpProject\AmpWP\Services; use WP_Screen; use stdClass; @@ -20,7 +22,7 @@ * @since 2.2 * @internal */ -class AmpThemes implements Service, Registerable, Conditional, Delayed { +class AmpThemes implements Service, HasRequirements, Registerable, Conditional, Delayed { /** * Slug for amp-compatible. @@ -49,10 +51,18 @@ class AmpThemes implements Service, Registerable, Conditional, Delayed { * @return string Registration action to use. */ public static function get_registration_action() { - return 'admin_init'; } + /** + * Get the list of service IDs required for this service to be registered. + * + * @return string[] List of required services. + */ + public static function get_requirements() { + return [ 'dependency_support' ]; + } + /** * Check whether the conditional object is currently needed. * @@ -60,6 +70,10 @@ public static function get_registration_action() { */ public static function is_needed() { + if ( ! Services::get( 'dependency_support' )->has_support() ) { + return false; + } + /** * Filters whether to show AMP compatible ecosystem in the admin. * diff --git a/src/Admin/OnboardingWizardSubmenuPage.php b/src/Admin/OnboardingWizardSubmenuPage.php index ba9345ac55c..dfc038c21fe 100644 --- a/src/Admin/OnboardingWizardSubmenuPage.php +++ b/src/Admin/OnboardingWizardSubmenuPage.php @@ -301,9 +301,17 @@ protected function add_preload_rest_paths() { ], '/amp/v1/scannable-urls' ), - '/wp/v2/plugins', + add_query_arg( + '_fields', + [ 'author', 'name', 'plugin', 'status', 'version' ], + '/wp/v2/plugins' + ), '/wp/v2/settings', - '/wp/v2/themes', + add_query_arg( + '_fields', + [ 'author', 'name', 'status', 'stylesheet', 'version' ], + '/wp/v2/themes' + ), '/wp/v2/users/me', ]; diff --git a/src/Admin/OptionsMenu.php b/src/Admin/OptionsMenu.php index b712fed936c..0cfd9f8de09 100644 --- a/src/Admin/OptionsMenu.php +++ b/src/Admin/OptionsMenu.php @@ -320,9 +320,17 @@ protected function add_preload_rest_paths() { [ 'url', 'amp_url', 'type', 'label', 'validation_errors', 'stale' ], '/amp/v1/scannable-urls' ), - '/wp/v2/plugins', + add_query_arg( + '_fields', + [ 'author', 'name', 'plugin', 'status', 'version' ], + '/wp/v2/plugins' + ), '/wp/v2/settings', - '/wp/v2/themes', + add_query_arg( + '_fields', + [ 'author', 'name', 'status', 'stylesheet', 'version' ], + '/wp/v2/themes' + ), '/wp/v2/users/me', ]; diff --git a/src/Admin/PluginActivationSiteScan.php b/src/Admin/PluginActivationSiteScan.php index 1216ec5886f..936e30fed32 100644 --- a/src/Admin/PluginActivationSiteScan.php +++ b/src/Admin/PluginActivationSiteScan.php @@ -13,11 +13,12 @@ use AMP_Options_Manager; use AMP_Validation_Manager; -use AmpProject\AmpWP\DevTools\UserAccess; use AmpProject\AmpWP\Infrastructure\Conditional; use AmpProject\AmpWP\Infrastructure\Delayed; +use AmpProject\AmpWP\Infrastructure\HasRequirements; use AmpProject\AmpWP\Infrastructure\Registerable; use AmpProject\AmpWP\Infrastructure\Service; +use AmpProject\AmpWP\Services; /** * Class PluginActivationSiteScan @@ -25,7 +26,7 @@ * @since 2.2 * @internal */ -final class PluginActivationSiteScan implements Conditional, Delayed, Service, Registerable { +final class PluginActivationSiteScan implements Conditional, Delayed, HasRequirements, Service, Registerable { /** * Handle for JS file. * @@ -47,6 +48,15 @@ final class PluginActivationSiteScan implements Conditional, Delayed, Service, R */ private $rest_preloader; + /** + * Get the list of service IDs required for this service to be registered. + * + * @return string[] List of required services. + */ + public static function get_requirements() { + return [ 'dependency_support' ]; + } + /** * OnboardingWizardSubmenuPage constructor. * @@ -67,6 +77,8 @@ public static function is_needed() { return ( is_admin() && + Services::get( 'dependency_support' )->has_support() + && ! is_network_admin() && 'plugins.php' === $pagenow @@ -180,7 +192,11 @@ protected function add_preload_rest_paths() { ], '/amp/v1/scannable-urls' ), - '/wp/v2/plugins', + add_query_arg( + '_fields', + [ 'author', 'name', 'plugin', 'status', 'version' ], + '/wp/v2/plugins' + ), '/wp/v2/users/me', ]; diff --git a/src/Admin/SupportLink.php b/src/Admin/SupportLink.php index 2e3d511ce45..5484fb24e41 100644 --- a/src/Admin/SupportLink.php +++ b/src/Admin/SupportLink.php @@ -38,7 +38,11 @@ public static function get_registration_action() { * @return bool Whether the conditional object is needed. */ public static function is_needed() { - return SupportScreen::has_cap(); + return ( + SupportScreen::check_core_version() + && + SupportScreen::has_cap() + ); } /** diff --git a/src/Admin/SupportScreen.php b/src/Admin/SupportScreen.php index 66cbe556247..5954d597df1 100644 --- a/src/Admin/SupportScreen.php +++ b/src/Admin/SupportScreen.php @@ -32,6 +32,13 @@ class SupportScreen implements Conditional, Delayed, Service, Registerable { */ const ASSET_HANDLE = 'amp-support'; + /** + * The minimum version of WordPress support for the "Support page". + * + * @var string + */ + const WP_MIN_VERSION = '5.2'; + /** * Injector. * @@ -97,6 +104,15 @@ public static function has_cap() { ); } + /** + * Returns whether minimum WordPress version is available for support page or not. + * + * @return bool True if current WordPress's version is greater than or equal to minimum version. + */ + public static function check_core_version() { + return version_compare( get_bloginfo( 'version' ), self::WP_MIN_VERSION, '>=' ); + } + /** * Check whether the conditional object is currently needed. * @@ -104,6 +120,8 @@ public static function has_cap() { */ public static function is_needed() { return ( + self::check_core_version() + && is_admin() && self::has_cap() diff --git a/src/AmpWpPlugin.php b/src/AmpWpPlugin.php index f9f28ab6cbe..01575d06ecd 100644 --- a/src/AmpWpPlugin.php +++ b/src/AmpWpPlugin.php @@ -20,7 +20,6 @@ use AmpProject\AmpWP\RemoteRequest\WpHttpRemoteGetRequest; use AmpProject\AmpWP\Support\SupportCliCommand; use AmpProject\AmpWP\Support\SupportRESTController; -use AmpProject\AmpWP\Validation\SavePostValidationEvent; use AmpProject\AmpWP\Validation\ScannableURLProvider; use AmpProject\AmpWP\Validation\URLValidationCron; use AmpProject\AmpWP\Validation\URLValidationProvider; @@ -118,7 +117,6 @@ final class AmpWpPlugin extends ServiceBasedPlugin { 'rest.scannable_urls_controller' => Validation\ScannableURLsRestController::class, 'rest.validation_counts_controller' => Validation\ValidationCountsRestController::class, 'sandboxing' => Sandboxing::class, - 'save_post_validation_event' => SavePostValidationEvent::class, 'server_timing' => Instrumentation\ServerTiming::class, 'site_health_integration' => Admin\SiteHealth::class, 'support' => SupportCliCommand::class, diff --git a/src/DevTools/UserAccess.php b/src/DevTools/UserAccess.php index f22b3d2f45d..76b9fd9fc3a 100644 --- a/src/DevTools/UserAccess.php +++ b/src/DevTools/UserAccess.php @@ -12,6 +12,7 @@ use AMP_Options_Manager; use AMP_Theme_Support; use AMP_Validation_Manager; +use AmpProject\AmpWP\DependencySupport; use AmpProject\AmpWP\Infrastructure\Registerable; use AmpProject\AmpWP\Infrastructure\Service; use AmpProject\AmpWP\Option; @@ -26,6 +27,18 @@ */ final class UserAccess implements Service, Registerable { + /** @var DependencySupport */ + private $dependency_support; + + /** + * Constructor. + * + * @param DependencySupport $dependency_support DependencySupport instance. + */ + public function __construct( DependencySupport $dependency_support ) { + $this->dependency_support = $dependency_support; + } + /** * User meta key enabling or disabling developer tools. * @@ -50,6 +63,14 @@ public function register() { * @return bool Whether developer tools are enabled for the user. */ public function is_user_enabled( $user = null ) { + // Note: This is somewhat of a shortcut for blocking access to the validation UI on unsupported versions of WP. + // It works because we're already using this method in many places to check if the user interface should be + // shown, and its the user interface which is particularly problematic on older versions of WP due to the + // JavaScript dependencies. + if ( ! $this->dependency_support->has_support() ) { + return false; // @codeCoverageIgnore + } + if ( null === $user ) { $user = wp_get_current_user(); } elseif ( ! $user instanceof WP_User ) { @@ -125,13 +146,29 @@ public function register_rest_field() { ); } + /** + * Determine whether the option can be modified. + * + * @param int $user_id User ID. + * @return bool Whether the option can be modified. + */ + private function can_modify_option( $user_id ) { + return ( + $this->dependency_support->has_support() + && + current_user_can( 'edit_user', $user_id ) + && + AMP_Validation_Manager::has_cap( $user_id ) + ); + } + /** * Add the developer tools checkbox to the user edit screen. * * @param WP_User $profile_user Current user being edited. */ public function print_personal_options( $profile_user ) { - if ( ! current_user_can( 'edit_user', $profile_user->ID ) || ! AMP_Validation_Manager::has_cap( $profile_user ) ) { + if ( ! $this->can_modify_option( $profile_user->ID ) ) { return; } ?> @@ -156,7 +193,7 @@ public function print_personal_options( $profile_user ) { * @return bool Whether update was successful. */ public function update_user_setting( $user_id ) { - if ( ! current_user_can( 'edit_user', $user_id ) || ! AMP_Validation_Manager::has_cap( $user_id ) ) { + if ( ! $this->can_modify_option( $user_id ) ) { return false; } $enabled = isset( $_POST[ self::USER_FIELD_DEVELOPER_TOOLS_ENABLED ] ) && rest_sanitize_boolean( wp_unslash( $_POST[ self::USER_FIELD_DEVELOPER_TOOLS_ENABLED ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Nonce handled by user-edit.php; sanitization used is sanitized. diff --git a/src/Validation/SavePostValidationEvent.php b/src/Validation/SavePostValidationEvent.php deleted file mode 100644 index 3aaa070253a..00000000000 --- a/src/Validation/SavePostValidationEvent.php +++ /dev/null @@ -1,171 +0,0 @@ -dev_tools_user_access = $dev_tools_user_access; - $this->url_validation_provider = $url_validation_provider; - } - - /** - * Callback for the cron action. - * - * @param mixed ...$args The args received with the action hook where the event was scheduled. - */ - public function process( ...$args ) { - $post_id = reset( $args ); - - if ( empty( $post_id ) || empty( get_post( $post_id ) ) ) { - return; - } - - $this->url_validation_provider->get_url_validation( - get_the_permalink( $post_id ), - get_post_type( $post_id ) - ); - } - - /** - * Get the event name. - * - * This is the "slug" of the event, not the display name. - * - * Note: the event name should be prefixed to prevent naming collisions. - * - * @return string Name of the event. - */ - protected function get_event_name() { - return self::BACKGROUND_TASK_NAME; - } - - /** - * Returns whether the event should be scheduled. - * - * @param array $args Args passed from the action hook where the event is scheduled. - * @return boolean - */ - protected function should_schedule_event( $args ) { - if ( ! is_array( $args ) || count( $args ) !== 1 ) { - return false; - } - - // Validation is performed on post save if user has dev tools on. - if ( $this->dev_tools_user_access->is_user_enabled( wp_get_current_user() ) ) { - return false; - } - - $id = reset( $args ); - if ( empty( $id ) ) { - return false; - } - - $post = get_post( $id ); - - // @todo This needs to be limited to when the status is publish because otherwise the validation request will fail to be able to access the post, as the request is not authenticated. - if ( ! $post - || - wp_is_post_revision( $post ) - || - wp_is_post_autosave( $post ) - || - 'auto-draft' === $post->post_status - || - 'trash' === $post->post_status - ) { - return false; - } - - if ( ! amp_is_post_supported( $id ) ) { - return false; - } - - return true; - } - - /** - * Gets the hook on which to schedule the event. - * - * @return string The action hook name. - */ - protected function get_action_hook() { - return 'save_post'; - } -} diff --git a/tests/e2e/specs/admin/site-scan-panel.js b/tests/e2e/specs/admin/site-scan-panel.js index 66ec2403e5c..a6de36583ca 100644 --- a/tests/e2e/specs/admin/site-scan-panel.js +++ b/tests/e2e/specs/admin/site-scan-panel.js @@ -163,7 +163,7 @@ describe( 'AMP settings screen Site Scan panel', () => { await visitAdminPage( 'admin.php', 'page=amp-options' ); await expect( page ).toMatchElement( '.site-scan-results--plugins .site-scan-results__source-slug', { text: /e2e-tests-demo-plugin/ } ); - await expect( page ).toMatchElement( '.site-scan-results--plugins .site-scan-results__source-notice', { text: /This plugin has been uninstalled since last site scan./ } ); + await expect( page ).toMatchElement( '.site-scan-results--plugins .site-scan-results__source-notice', { text: /This plugin has been uninstalled or its metadata is unavailable./ } ); // Clean up. await installLocalPlugin( 'e2e-tests-demo-plugin' ); diff --git a/tests/php/src/Admin/AmpPluginsTest.php b/tests/php/src/Admin/AmpPluginsTest.php index 057f33a9abf..ac1d032c5f0 100644 --- a/tests/php/src/Admin/AmpPluginsTest.php +++ b/tests/php/src/Admin/AmpPluginsTest.php @@ -25,20 +25,37 @@ class AmpPluginsTest extends TestCase { */ public $instance; + /** @var string */ + private $original_wp_version; + /** * Setup. * - * @inheritdoc + * @inheritDoc */ public function setUp() { parent::setUp(); - global $wp_scripts, $wp_styles; + global $wp_scripts, $wp_styles, $wp_version; $wp_scripts = null; $wp_styles = null; $this->instance = new AmpPlugins(); + + $this->original_wp_version = $wp_version; + } + + /** + * Tear down. + * + * @inheritDoc + */ + public function tearDown() { + parent::tearDown(); + + global $wp_version; + $wp_version = $this->original_wp_version; } /** @@ -134,15 +151,21 @@ public function test_get_registration_action() { * @covers ::is_needed() */ public function test_is_needed() { + global $wp_version; // Test 1: Not admin request. $this->assertFalse( AmpPlugins::is_needed() ); - // Test 2: Admin request. + // Test 2: Check with older version of WordPress. + $wp_version = '4.9'; + $this->assertFalse( AmpPlugins::is_needed() ); + + // Test 3: Admin request in supported WordPress . + $wp_version = '5.6'; set_current_screen( 'index.php' ); $this->assertTrue( AmpPlugins::is_needed() ); - // Test 3: Filter disables. + // Test 4: Filter disables. add_filter( 'amp_compatible_ecosystem_shown', static function ( $shown, $type ) { diff --git a/tests/php/src/Admin/AmpThemesTest.php b/tests/php/src/Admin/AmpThemesTest.php index 1d88eb8c1c5..ccff732743b 100644 --- a/tests/php/src/Admin/AmpThemesTest.php +++ b/tests/php/src/Admin/AmpThemesTest.php @@ -25,19 +25,37 @@ class AmpThemesTest extends TestCase { */ public $instance; + /** @var string */ + private $original_wp_version; + /** * Setup. * - * @inheritdoc + * @inheritDoc */ public function setUp() { + parent::setUp(); - global $wp_scripts, $wp_styles; + global $wp_scripts, $wp_styles, $wp_version; $wp_scripts = null; $wp_styles = null; $this->instance = new AmpThemes(); + + $this->original_wp_version = $wp_version; + } + + /** + * Tear down. + * + * @inheritDoc + */ + public function tearDown() { + parent::tearDown(); + + global $wp_version; + $wp_version = $this->original_wp_version; } /** @@ -52,18 +70,25 @@ public function test_get_registration_action() { * @covers ::is_needed() */ public function test_is_needed() { + global $wp_version; + set_current_screen( 'front' ); // Test 1: Not admin request. $this->assertFalse( is_admin() ); $this->assertFalse( AmpThemes::is_needed() ); - // Test 2: Admin request. + // Test 2: Check with older version of WordPress. + $wp_version = '4.9'; + $this->assertFalse( AmpThemes::is_needed() ); + + // Test 3: Admin request. + $wp_version = '5.6'; set_current_screen( 'index.php' ); $this->assertTrue( is_admin() ); $this->assertTrue( AmpThemes::is_needed() ); - // Test 3: Filter disables. + // Test 4: Filter disables. add_filter( 'amp_compatible_ecosystem_shown', static function ( $shown, $type ) { diff --git a/tests/php/src/Admin/OnboardingWizardSubmenuPageTest.php b/tests/php/src/Admin/OnboardingWizardSubmenuPageTest.php index 9ea51a0cef2..7d226be32e8 100644 --- a/tests/php/src/Admin/OnboardingWizardSubmenuPageTest.php +++ b/tests/php/src/Admin/OnboardingWizardSubmenuPageTest.php @@ -189,9 +189,9 @@ function ( $caps, $cap ) { '/amp/v1/options', '/amp/v1/reader-themes', '/amp/v1/scannable-urls?_fields%5B0%5D=url&_fields%5B1%5D=amp_url&_fields%5B2%5D=type&_fields%5B3%5D=label&force_standard_mode=1', - '/wp/v2/plugins', + '/wp/v2/plugins?_fields%5B0%5D=author&_fields%5B1%5D=name&_fields%5B2%5D=plugin&_fields%5B3%5D=status&_fields%5B4%5D=version', '/wp/v2/settings', - '/wp/v2/themes', + '/wp/v2/themes?_fields%5B0%5D=author&_fields%5B1%5D=name&_fields%5B2%5D=status&_fields%5B3%5D=stylesheet&_fields%5B4%5D=version', '/wp/v2/users/me', ], $this->get_private_property( $rest_preloader, 'paths' ) diff --git a/tests/php/src/Admin/OptionsMenuTest.php b/tests/php/src/Admin/OptionsMenuTest.php index 5bc891f1a53..2c55f3eea95 100644 --- a/tests/php/src/Admin/OptionsMenuTest.php +++ b/tests/php/src/Admin/OptionsMenuTest.php @@ -244,9 +244,9 @@ function ( $caps, $cap ) { '/amp/v1/options', '/amp/v1/reader-themes', '/amp/v1/scannable-urls?_fields%5B0%5D=url&_fields%5B1%5D=amp_url&_fields%5B2%5D=type&_fields%5B3%5D=label&_fields%5B4%5D=validation_errors&_fields%5B5%5D=stale', - '/wp/v2/plugins', + '/wp/v2/plugins?_fields%5B0%5D=author&_fields%5B1%5D=name&_fields%5B2%5D=plugin&_fields%5B3%5D=status&_fields%5B4%5D=version', '/wp/v2/settings', - '/wp/v2/themes', + '/wp/v2/themes?_fields%5B0%5D=author&_fields%5B1%5D=name&_fields%5B2%5D=status&_fields%5B3%5D=stylesheet&_fields%5B4%5D=version', '/wp/v2/users/me', ], $this->get_private_property( $rest_preloader, 'paths' ) diff --git a/tests/php/src/Admin/PairedBrowsingTest.php b/tests/php/src/Admin/PairedBrowsingTest.php index 5a71a04c663..94518d481ca 100644 --- a/tests/php/src/Admin/PairedBrowsingTest.php +++ b/tests/php/src/Admin/PairedBrowsingTest.php @@ -10,6 +10,7 @@ use AMP_Options_Manager; use AMP_Theme_Support; use AmpProject\AmpWP\Admin\PairedBrowsing; +use AmpProject\AmpWP\DependencySupport; use AmpProject\AmpWP\Infrastructure\Conditional; use AmpProject\AmpWP\Infrastructure\Delayed; use AmpProject\AmpWP\Infrastructure\HasRequirements; @@ -186,9 +187,13 @@ public function test_add_admin_bar_menu_item() { // Test when DevTools enabled. wp_set_current_user( self::factory()->user->create( [ 'role' => 'administrator' ] ) ); - $this->assertTrue( $this->instance->dev_tools_user_access->is_user_enabled() ); - $this->instance->add_admin_bar_menu_item( $wp_admin_bar ); - $this->assertNotEmpty( $wp_admin_bar->get_node( 'amp-paired-browsing' ) ); + if ( ( new DependencySupport() )->has_support() ) { + $this->assertTrue( $this->instance->dev_tools_user_access->is_user_enabled() ); + $this->instance->add_admin_bar_menu_item( $wp_admin_bar ); + $this->assertNotEmpty( $wp_admin_bar->get_node( 'amp-paired-browsing' ) ); + } else { + $this->assertFalse( $this->instance->dev_tools_user_access->is_user_enabled() ); + } } /** @covers ::get_paired_browsing_url() */ diff --git a/tests/php/src/Admin/PluginActivationSiteScanTest.php b/tests/php/src/Admin/PluginActivationSiteScanTest.php index 2b14ae6d840..907ac93102c 100644 --- a/tests/php/src/Admin/PluginActivationSiteScanTest.php +++ b/tests/php/src/Admin/PluginActivationSiteScanTest.php @@ -226,7 +226,7 @@ function ( $caps, $cap ) { [ '/amp/v1/options', '/amp/v1/scannable-urls?_fields%5B0%5D=url&_fields%5B1%5D=amp_url&_fields%5B2%5D=type&_fields%5B3%5D=label', - '/wp/v2/plugins', + '/wp/v2/plugins?_fields%5B0%5D=author&_fields%5B1%5D=name&_fields%5B2%5D=plugin&_fields%5B3%5D=status&_fields%5B4%5D=version', '/wp/v2/users/me', ], $this->get_private_property( $rest_preloader, 'paths' ) diff --git a/tests/php/src/Admin/SupportScreenTest.php b/tests/php/src/Admin/SupportScreenTest.php index bc21254094a..7bf730e756e 100644 --- a/tests/php/src/Admin/SupportScreenTest.php +++ b/tests/php/src/Admin/SupportScreenTest.php @@ -34,24 +34,41 @@ class SupportScreenTest extends DependencyInjectedTestCase { */ public $instance; + /** @var string */ + private $original_wp_version; + /** * Setup. * * @inheritdoc */ public function setUp() { - parent::setUp(); if ( ! class_exists( 'WP_Site_Health' ) ) { $this->markTestSkipped( 'Test requires Site Health.' ); } + global $wp_version; + $this->original_wp_version = $wp_version; + $this->instance = $this->injector->make( SupportScreen::class ); $this->add_home_url_loopback_request_mocking(); } + /** + * Tear down. + * + * @inheritDoc + */ + public function tearDown() { + parent::tearDown(); + + global $wp_version; + $wp_version = $this->original_wp_version; + } + /** @covers ::__construct() */ public function test__construct() { @@ -69,6 +86,28 @@ public function test_get_registration_action() { $this->assertEquals( 'init', SupportScreen::get_registration_action() ); } + /** + * @covers ::check_core_version() + */ + public function test_check_core_version() { + global $wp_version; + + // This will always be true by default because setUp calls markTestSkipped if WP_Site_Health doesn't exist. + $this->assertTrue( SupportScreen::check_core_version() ); + + $wp_version = '4.9'; + $this->assertFalse( SupportScreen::check_core_version() ); + + $wp_version = '5.0'; + $this->assertFalse( SupportScreen::check_core_version() ); + + $wp_version = '5.1'; + $this->assertFalse( SupportScreen::check_core_version() ); + + $wp_version = '5.2'; + $this->assertTrue( SupportScreen::check_core_version() ); + } + /** * @covers ::is_needed() * @covers ::has_cap() diff --git a/tests/php/src/DevTools/UserAccessTest.php b/tests/php/src/DevTools/UserAccessTest.php index 65dc8801329..61bc5a36f9e 100644 --- a/tests/php/src/DevTools/UserAccessTest.php +++ b/tests/php/src/DevTools/UserAccessTest.php @@ -9,9 +9,11 @@ use AMP_Options_Manager; use AMP_Theme_Support; +use AmpProject\AmpWP\DependencySupport; use AmpProject\AmpWP\DevTools\UserAccess; use AmpProject\AmpWP\Option; -use AmpProject\AmpWP\Tests\TestCase; +use AmpProject\AmpWP\Tests\DependencyInjectedTestCase; +use AmpProject\AmpWP\Tests\Helpers\PrivateAccess; use WP_Error; /** @@ -23,7 +25,9 @@ * * @coversDefaultClass \AmpProject\AmpWP\DevTools\UserAccess */ -class UserAccessTest extends TestCase { +class UserAccessTest extends DependencyInjectedTestCase { + + use PrivateAccess; /** * Test instance. @@ -35,7 +39,7 @@ class UserAccessTest extends TestCase { public function setUp() { parent::setUp(); - $this->dev_tools_user_access = new UserAccess(); + $this->dev_tools_user_access = $this->injector->make( UserAccess::class ); } /** @@ -61,12 +65,14 @@ public function test_is_user_enabled() { $admin_user = self::factory()->user->create_and_get( [ 'role' => 'administrator' ] ); $editor_user = self::factory()->user->create_and_get( [ 'role' => 'editor' ] ); - $this->assertTrue( $this->dev_tools_user_access->is_user_enabled( $admin_user ) ); - $this->assertTrue( $this->dev_tools_user_access->is_user_enabled( $admin_user->ID ) ); + $has_dependency_support = $this->get_private_property( $this->dev_tools_user_access, 'dependency_support' )->has_support(); + + $this->assertEquals( $has_dependency_support, $this->dev_tools_user_access->is_user_enabled( $admin_user ) ); + $this->assertEquals( $has_dependency_support, $this->dev_tools_user_access->is_user_enabled( $admin_user->ID ) ); $this->assertFalse( $this->dev_tools_user_access->is_user_enabled( $editor_user ) ); $this->assertFalse( $this->dev_tools_user_access->is_user_enabled( $editor_user->ID ) ); wp_set_current_user( $admin_user->ID ); - $this->assertTrue( $this->dev_tools_user_access->is_user_enabled() ); + $this->assertEquals( $has_dependency_support, $this->dev_tools_user_access->is_user_enabled() ); $this->dev_tools_user_access->set_user_enabled( $admin_user, false ); $this->assertFalse( $this->dev_tools_user_access->is_user_enabled() ); wp_set_current_user( $editor_user->ID ); @@ -159,6 +165,7 @@ public function test_register_rest_field() { /** * Tests UserAccess::print_personal_options * + * @covers ::can_modify_option * @covers ::print_personal_options */ public function test_print_personal_options() { @@ -176,12 +183,18 @@ public function test_print_personal_options() { ob_start(); $this->dev_tools_user_access->print_personal_options( $admin_user ); - $this->assertStringContainsString( 'checkbox', ob_get_clean() ); + $output = ob_get_clean(); + if ( ( new DependencySupport() )->has_support() ) { + $this->assertStringContainsString( 'checkbox', $output ); + } else { + $this->assertStringNotContainsString( 'checkbox', $output ); + } } /** * Tests UserAccess::update_user_setting * + * @covers ::can_modify_option * @covers ::update_user_setting */ public function test_update_user_setting() { @@ -195,10 +208,10 @@ public function test_update_user_setting() { wp_set_current_user( $admin_user->ID ); $this->assertFalse( $this->dev_tools_user_access->update_user_setting( $editor_user->ID ) ); - $this->assertTrue( $this->dev_tools_user_access->update_user_setting( $admin_user->ID ) ); - $this->assertTrue( $this->dev_tools_user_access->get_user_enabled( $admin_user ) ); + $this->assertEquals( ( new DependencySupport() )->has_support(), $this->dev_tools_user_access->update_user_setting( $admin_user->ID ) ); + $this->assertEquals( ( new DependencySupport() )->has_support(), $this->dev_tools_user_access->get_user_enabled( $admin_user ) ); $_POST[ UserAccess::USER_FIELD_DEVELOPER_TOOLS_ENABLED ] = null; - $this->assertTrue( $this->dev_tools_user_access->update_user_setting( $admin_user->ID ) ); + $this->assertEquals( ( new DependencySupport() )->has_support(), $this->dev_tools_user_access->update_user_setting( $admin_user->ID ) ); $this->assertFalse( $this->dev_tools_user_access->get_user_enabled( $admin_user ) ); } @@ -214,13 +227,19 @@ public function test_rest_get_dev_tools_enabled() { $this->assertFalse( $this->dev_tools_user_access->rest_get_dev_tools_enabled( [ 'id' => $user->ID ] ) ); $user->set_role( 'administrator' ); - $this->assertTrue( $this->dev_tools_user_access->rest_get_dev_tools_enabled( [ 'id' => $user->ID ] ) ); + $this->assertEquals( + ( new DependencySupport() )->has_support(), + $this->dev_tools_user_access->rest_get_dev_tools_enabled( [ 'id' => $user->ID ] ) + ); update_user_meta( $user->ID, 'amp_dev_tools_enabled', 'false' ); $this->assertFalse( $this->dev_tools_user_access->rest_get_dev_tools_enabled( [ 'id' => $user->ID ] ) ); update_user_meta( $user->ID, 'amp_dev_tools_enabled', 'true' ); - $this->assertTrue( $this->dev_tools_user_access->rest_get_dev_tools_enabled( [ 'id' => $user->ID ] ) ); + $this->assertEquals( + ( new DependencySupport() )->has_support(), + $this->dev_tools_user_access->rest_get_dev_tools_enabled( [ 'id' => $user->ID ] ) + ); } /** diff --git a/tests/php/src/Validation/SavePostValidationEventTest.php b/tests/php/src/Validation/SavePostValidationEventTest.php deleted file mode 100644 index 10f122fbc86..00000000000 --- a/tests/php/src/Validation/SavePostValidationEventTest.php +++ /dev/null @@ -1,177 +0,0 @@ -test_instance = new SavePostValidationEvent( new BackgroundTaskDeactivator(), new UserAccess(), new URLValidationProvider() ); - $this->dev_tools_user_access = new UserAccess(); - $this->add_validate_response_mocking_filter(); - } - - /** @covers ::__construct() */ - public function test__construct() { - $this->assertInstanceof( SingleScheduledBackgroundTask::class, $this->test_instance ); - $this->assertInstanceof( SavePostValidationEvent::class, $this->test_instance ); - $this->assertInstanceof( Service::class, $this->test_instance ); - $this->assertInstanceof( Registerable::class, $this->test_instance ); - $this->assertInstanceof( Conditional::class, $this->test_instance ); - } - - /** @covers ::is_needed() */ - public function test_is_needed() { - $this->assertFalse( SavePostValidationEvent::is_needed() ); - - add_filter( 'amp_temp_validation_cron_tasks_enabled', '__return_true' ); - $this->assertTrue( SavePostValidationEvent::is_needed() ); - - remove_filter( 'amp_temp_validation_cron_tasks_enabled', '__return_true' ); - } - - /** - * @covers ::register() - * @covers ::get_event_name() - * @covers ::get_action_hook_arg_count() - */ - public function test_register() { - $this->test_instance->register(); - - $this->assertEquals( 10, has_action( 'save_post', [ $this->test_instance, 'schedule_event' ] ) ); - $this->assertEquals( 10, has_action( 'amp_single_post_validate', [ $this->test_instance, 'process' ] ) ); - } - - /** - * @covers ::process() - */ - public function test_process() { - $this->test_instance->process(); - $this->assertCount( 0, $this->get_validated_urls() ); - - $post = $this->factory()->post->create_and_get( - [ - 'post_content' => '
', - ] - ); - - $this->test_instance->process( $post->ID ); - - $this->assertCount( 1, $this->get_validated_urls() ); - - $this->assertInstanceof( - URLValidationProvider::class, - $this->get_private_property( $this->test_instance, 'url_validation_provider' ) - ); - } - - /** @covers ::schedule_event() */ - public function test_schedule_event_with_no_post() { - wp_set_current_user( $this->factory()->user->create( [ 'role' => 'administrator' ] ) ); - - $event_was_scheduled = false; - $filter_cb = static function ( $event ) use ( &$event_was_scheduled ) { - $event_was_scheduled = true; - return $event; - }; - add_filter( 'schedule_event', $filter_cb ); - - $this->test_instance->schedule_event( [] ); - - $this->assertFalse( $event_was_scheduled ); - - remove_filter( 'schedule_event', $filter_cb ); - } - - /** @covers ::schedule_event() */ - public function test_schedule_event_with_post() { - wp_set_current_user( $this->factory()->user->create( [ 'role' => 'administrator' ] ) ); - $this->dev_tools_user_access->set_user_enabled( wp_get_current_user(), true ); - - $event_was_scheduled = false; - $filter_cb = static function ( $event ) use ( &$event_was_scheduled ) { - $event_was_scheduled = true; - return $event; - }; - add_filter( 'schedule_event', $filter_cb ); - - $post = $this->factory()->post->create(); - - $this->test_instance->schedule_event( $post ); - - $this->assertFalse( $event_was_scheduled ); - - wp_set_current_user( $this->factory()->user->create( [ 'role' => 'author' ] ) ); - - $this->test_instance->schedule_event( $post ); - - $this->assertTrue( $event_was_scheduled ); - - remove_filter( 'schedule_event', $filter_cb ); - } - - /** @covers ::should_schedule_event() */ - public function test_should_schedule_event() { - // No user set. - $this->assertFalse( $this->call_private_method( $this->test_instance, 'should_schedule_event', [ [] ] ) ); - - // Array not passed. - $this->assertFalse( $this->call_private_method( $this->test_instance, 'should_schedule_event', [ null ] ) ); - - // Too many args passed. - $this->assertFalse( $this->call_private_method( $this->test_instance, 'should_schedule_event', [ [ 'arg1', 'arg2' ] ] ) ); - - // User with insufficient permissions. - wp_set_current_user( $this->factory()->user->create( [ 'role' => 'subscriber' ] ) ); - $post = $this->factory()->post->create(); - $this->assertTrue( $this->call_private_method( $this->test_instance, 'should_schedule_event', [ [ $post ] ] ) ); - - // User with dev tools off. - wp_set_current_user( $this->factory()->user->create( [ 'role' => 'administrator' ] ) ); - $this->dev_tools_user_access->set_user_enabled( wp_get_current_user(), false ); - $post = $this->factory()->post->create(); - $this->assertTrue( $this->call_private_method( $this->test_instance, 'should_schedule_event', [ [ $post ] ] ) ); - - wp_set_current_user( $this->factory()->user->create( [ 'role' => 'administrator' ] ) ); - $this->dev_tools_user_access->set_user_enabled( wp_get_current_user(), true ); - $post = $this->factory()->post->create(); - $this->assertFalse( $this->call_private_method( $this->test_instance, 'should_schedule_event', [ [ $post ] ] ) ); - } - - /** @covers ::get_action_hook() */ - public function test_get_action_hook() { - $this->assertEquals( 'save_post', $this->call_private_method( $this->test_instance, 'get_action_hook' ) ); - } -} diff --git a/tests/php/src/Validation/URLValidationRESTControllerTest.php b/tests/php/src/Validation/URLValidationRESTControllerTest.php index 08f47877a9f..153c555dfca 100644 --- a/tests/php/src/Validation/URLValidationRESTControllerTest.php +++ b/tests/php/src/Validation/URLValidationRESTControllerTest.php @@ -7,10 +7,10 @@ namespace AmpProject\AmpWP\Tests\Validation; +use AmpProject\AmpWP\DependencySupport; use AmpProject\AmpWP\DevTools\UserAccess; +use AmpProject\AmpWP\Tests\DependencyInjectedTestCase; use AmpProject\AmpWP\Tests\Helpers\ValidationRequestMocking; -use AmpProject\AmpWP\Tests\TestCase; -use AmpProject\AmpWP\Validation\URLValidationProvider; use AmpProject\AmpWP\Validation\URLValidationRESTController; use WP_REST_Controller; use WP_REST_Request; @@ -22,7 +22,7 @@ * * @coversDefaultClass \AmpProject\AmpWP\Validation\URLValidationRESTController */ -class URLValidationRESTControllerTest extends TestCase { +class URLValidationRESTControllerTest extends DependencyInjectedTestCase { use ValidationRequestMocking; /** @@ -46,8 +46,8 @@ public function setUp() { parent::setUp(); do_action( 'rest_api_init' ); - $this->user_access = new UserAccess(); - $this->controller = new URLValidationRESTController( new URLValidationProvider(), $this->user_access ); + $this->user_access = $this->injector->make( UserAccess::class ); + $this->controller = $this->injector->make( URLValidationRESTController::class ); $this->add_validate_response_mocking_filter(); } @@ -78,7 +78,12 @@ public function test_create_item_permissions_check() { wp_set_current_user( self::factory()->user->create( [ 'role' => 'administrator' ] ) ); $this->user_access->set_user_enabled( wp_get_current_user(), true ); - $this->assertTrue( $this->controller->create_item_permissions_check( new WP_REST_Request( 'POST', '/amp/v1/validate-post-url/' ) ) ); + $value = $this->controller->create_item_permissions_check( new WP_REST_Request( 'POST', '/amp/v1/validate-post-url/' ) ); + if ( ( new DependencySupport() )->has_support() ) { + $this->assertTrue( $value ); + } else { + $this->assertWPError( $value ); + } } /** @covers ::is_valid_preview_nonce() */ @@ -138,7 +143,9 @@ public function get_data_for_test_validate_post_url() { ], 'post', 'administrator', - version_compare( get_bloginfo( 'version' ), '5.2', '<' ) ? 'amp_post_preview_denied' : 'rest_invalid_param', + ( new DependencySupport() )->has_support() + ? ( version_compare( get_bloginfo( 'version' ), '5.2', '<' ) ? 'amp_post_preview_denied' : 'rest_invalid_param' ) + : 'amp_rest_no_dev_tools', ], 'bad_preview2' => [ @@ -148,7 +155,7 @@ public function get_data_for_test_validate_post_url() { ], 'post', 'administrator', - 'amp_post_preview_denied', + ( new DependencySupport() )->has_support() ? 'amp_post_preview_denied' : 'amp_rest_no_dev_tools', ], 'post_id' => [ @@ -198,7 +205,11 @@ public function test_validate_post_url( $params, $post_type, $user_role, $expect $request->set_body_params( $params ); $response = rest_get_server()->dispatch( $request ); - if ( true === $expected_validity ) { + if ( ! ( new DependencySupport() )->has_support() && true === $expected_validity ) { + $this->assertTrue( $response->is_error() ); + $error = $response->as_error(); + $this->assertEquals( 'amp_rest_no_dev_tools', $error->get_error_code() ); + } elseif ( true === $expected_validity ) { $this->assertFalse( $response->is_error() ); $data = $response->get_data(); diff --git a/tests/php/src/Validation/ValidationCountsRestControllerTest.php b/tests/php/src/Validation/ValidationCountsRestControllerTest.php index 31f62cc89e1..0ba76d3ff22 100644 --- a/tests/php/src/Validation/ValidationCountsRestControllerTest.php +++ b/tests/php/src/Validation/ValidationCountsRestControllerTest.php @@ -8,6 +8,7 @@ namespace AmpProject\AmpWP\Tests\Validation; use AMP_Validated_URL_Post_Type; +use AmpProject\AmpWP\DependencySupport; use AmpProject\AmpWP\DevTools\UserAccess; use AmpProject\AmpWP\Tests\DependencyInjectedTestCase; use AmpProject\AmpWP\Validation\ValidationCountsRestController; @@ -59,7 +60,12 @@ public function test_get_items_permissions_check() { $this->assertWPError( $this->controller->get_items_permissions_check( new WP_REST_Request( 'GET', '/amp/v1/unreviewed-validation-counts' ) ) ); update_user_meta( $admin_user->ID, UserAccess::USER_FIELD_DEVELOPER_TOOLS_ENABLED, wp_json_encode( true ) ); - $this->assertTrue( $this->controller->get_items_permissions_check( new WP_REST_Request( 'GET', '/amp/v1/unreviewed-validation-counts' ) ) ); + $value = $this->controller->get_items_permissions_check( new WP_REST_Request( 'GET', '/amp/v1/unreviewed-validation-counts' ) ); + if ( ( new DependencySupport() )->has_support() ) { + $this->assertTrue( $value ); + } else { + $this->assertWPError( $value ); + } } /** @@ -76,6 +82,12 @@ public function test_get_items() { $request = new WP_REST_Request( 'GET', '/amp/v1/unreviewed-validation-counts' ); $response = rest_get_server()->dispatch( $request ); + + if ( ! ( new DependencySupport() )->has_support() ) { + $this->assertWPError( $response->as_error() ); + return; + } + $this->assertEquals( [ 'validated_urls' => 0, diff --git a/tests/php/test-amp-helper-functions.php b/tests/php/test-amp-helper-functions.php index a3bb5d494f0..b70d0881046 100644 --- a/tests/php/test-amp-helper-functions.php +++ b/tests/php/test-amp-helper-functions.php @@ -36,19 +36,29 @@ class Test_AMP_Helper_Functions extends DependencyInjectedTestCase { */ private $server_var_backup; + /** @var string */ + private $original_wp_version; + /** * Set up. + * + * @inheritDoc */ public function setUp() { parent::setUp(); $this->server_var_backup = $_SERVER; remove_theme_support( 'amp' ); + global $wp_version; + $this->original_wp_version = $wp_version; + $this->register_core_themes(); } /** - * After a test method runs, reset any state in WordPress the test method might have changed. + * Tear down. + * + * @inheritDoc */ public function tearDown() { AMP_Options_Manager::update_option( Option::THEME_SUPPORT, AMP_Theme_Support::READER_MODE_SLUG ); @@ -80,6 +90,9 @@ public function tearDown() { $this->remove_added_uploads(); } + global $wp_version; + $wp_version = $this->original_wp_version; + parent::tearDown(); } @@ -117,9 +130,21 @@ private function remove_bootstrapped_hooks() { } } - /** @covers ::amp_bootstrap_plugin() */ - public function test_amp_bootstrap_plugin() { + /** @return array */ + public function get_data_to_test_amp_bootstrap_plugin() { + return [ + '5.4' => [ '5.4', true ], + '5.5' => [ '5.5', false ], + ]; + } + + /** + * @dataProvider get_data_to_test_amp_bootstrap_plugin + * @covers ::amp_bootstrap_plugin() + */ + public function test_amp_bootstrap_plugin( $wp_version, $needs_script_loader_tag_filter ) { $this->remove_bootstrapped_hooks(); + $GLOBALS['wp_version'] = $wp_version; amp_bootstrap_plugin(); $this->assertEquals( 10, has_action( 'wp_default_scripts', 'amp_register_default_scripts' ) ); @@ -128,6 +153,15 @@ public function test_amp_bootstrap_plugin() { $this->assertEquals( 9, has_action( 'plugins_loaded', '_amp_bootstrap_customizer' ) ); $this->assertEquals( PHP_INT_MAX, has_filter( 'script_loader_tag', 'amp_filter_script_loader_tag' ) ); + + if ( $needs_script_loader_tag_filter ) { + $this->assertEquals( + defined( 'PHP_INT_MIN' ) ? PHP_INT_MIN : ~PHP_INT_MAX, // phpcs:ignore PHPCompatibility.Constants.NewConstants + has_filter( 'script_loader_tag', 'amp_ensure_id_attribute_on_script_loader_tag' ) + ); + } else { + $this->assertFalse( has_filter( 'script_loader_tag', 'amp_ensure_id_attribute_on_script_loader_tag' ) ); + } $this->assertEquals( 10, has_filter( 'style_loader_tag', 'amp_filter_font_style_loader_tag_with_crossorigin_anonymous' ) ); $this->assertEquals( 10, has_filter( 'all_plugins', 'amp_modify_plugin_description' ) ); } @@ -145,6 +179,62 @@ public function test_amp_bootstrap_plugin_amp_disabled() { } } + /** @covers ::amp_ensure_id_attribute_on_script_loader_tag() */ + public function test_amp_ensure_id_attribute_on_script_loader_tag() { + $this->assertEquals( + '', + amp_ensure_id_attribute_on_script_loader_tag( '', 'foo' ) + ); + + $this->assertEquals( + '', + amp_ensure_id_attribute_on_script_loader_tag( '', 'foo' ) + ); + + $this->assertEquals( + '', + amp_ensure_id_attribute_on_script_loader_tag( '', 'foo' ) + ); + + $this->assertEquals( + "", + amp_ensure_id_attribute_on_script_loader_tag( "", 'foo' ) + ); + + $this->assertEquals( + '', + amp_ensure_id_attribute_on_script_loader_tag( '', 'comment-reply' ) + ); + + $inline_script_before = ''; + $inline_script_after = ''; + $this->assertEquals( + $inline_script_before . '' . $inline_script_after, + amp_ensure_id_attribute_on_script_loader_tag( + $inline_script_before . '' . $inline_script_after, + 'foo' + ) + ); + + $foo_script = ''; + $this->assertEquals( + $foo_script, + amp_ensure_id_attribute_on_script_loader_tag( $foo_script, 'foo' ) + ); + + $foo_script = ''; + $this->assertEquals( + $foo_script, + amp_ensure_id_attribute_on_script_loader_tag( $foo_script, 'foo' ) + ); + + $amp_runtime_script = ''; + $this->assertEquals( + $amp_runtime_script, + amp_ensure_id_attribute_on_script_loader_tag( $amp_runtime_script, 'amp-runtime' ) + ); + } + /** @covers ::amp_init() */ public function test_amp_init_migration() { global $wp_actions; @@ -1209,7 +1299,7 @@ public function test_script_registering() { add_filter( 'script_loader_tag', static function ( $script ) { - return preg_replace( "/ id='amp-[^']+?'/", '', $script ); + return preg_replace( '/ id=(["\'])amp-.*?\1/', '', $script ); } ); diff --git a/tests/php/test-class-amp-customizer-design-settings.php b/tests/php/test-class-amp-customizer-design-settings.php index f5f80f69e0c..90f5018b340 100644 --- a/tests/php/test-class-amp-customizer-design-settings.php +++ b/tests/php/test-class-amp-customizer-design-settings.php @@ -5,13 +5,14 @@ * @package AMP */ +use AmpProject\AmpWP\DependencySupport; use AmpProject\AmpWP\Option; use AmpProject\AmpWP\Tests\TestCase; /** * Class Test_AMP_Customizer_Design_Settings * - * @covers AMP_Customizer_Design_Settings + * @coversDefaultClass \AMP_Customizer_Design_Settings */ class Test_AMP_Customizer_Design_Settings extends TestCase { @@ -20,26 +21,110 @@ public static function setUpBeforeClass() { return parent::setUpBeforeClass(); } + /** @var string */ + private $original_wp_version; + + /** + * Setup. + * + * @inheritDoc + */ + public function setUp() { + parent::setUp(); + + global $wp_version; + $this->original_wp_version = $wp_version; + } + /** - * Test is_amp_customizer_enabled(). + * Tear down. * - * @covers AMP_Customizer_Design_Settings::is_amp_customizer_enabled + * @inheritDoc + */ + public function tearDown() { + parent::tearDown(); + + global $wp_version; + $wp_version = $this->original_wp_version; + } + + /** @return array */ + public function get_data_to_test_is_amp_customizer_enabled() { + return [ + 'transitional_mode' => [ + static function () { + AMP_Options_Manager::update_option( Option::THEME_SUPPORT, AMP_Theme_Support::TRANSITIONAL_MODE_SLUG ); + }, + false, + ], + 'reader_mode' => [ + static function () { + AMP_Options_Manager::update_option( Option::THEME_SUPPORT, AMP_Theme_Support::READER_MODE_SLUG ); + }, + true, + ], + 'filter_disabled' => [ + static function () { + AMP_Options_Manager::update_option( Option::THEME_SUPPORT, AMP_Theme_Support::READER_MODE_SLUG ); + add_filter( 'amp_customizer_is_enabled', '__return_false' ); + }, + false, + ], + ]; + } + + /** + * @dataProvider get_data_to_test_is_amp_customizer_enabled + * @covers ::is_amp_customizer_enabled() + * @covers ::init() + */ + public function test_is_amp_customizer_enabled_and_init( callable $set_up, $enabled ) { + remove_all_actions( 'amp_customizer_init' ); + remove_all_filters( 'amp_customizer_get_settings' ); + + $set_up(); + $this->assertEquals( $enabled, AMP_Customizer_Design_Settings::is_amp_customizer_enabled() ); + AMP_Customizer_Design_Settings::init(); + + $this->assertEquals( $enabled ? 10 : false, has_action( 'amp_customizer_init', [ AMP_Customizer_Design_Settings::class, 'init_customizer' ] ) ); + $this->assertEquals( $enabled ? 10 : false, has_filter( 'amp_customizer_get_settings', [ AMP_Customizer_Design_Settings::class, 'append_settings' ] ) ); + + } + + /** @return array */ + public function get_data_to_test_init_customized() { + return [ + 'has_dependency_support' => [ true ], + 'not_has_dependency_support' => [ false ], + ]; + } + + /** + * @dataProvider get_data_to_test_init_customized + * @covers ::init_customizer() */ - public function test_is_amp_customizer_enabled() { - AMP_Options_Manager::update_option( Option::THEME_SUPPORT, 'foo' ); - $this->assertEquals( false, AMP_Customizer_Design_Settings::is_amp_customizer_enabled() ); + public function test_init_customizer( $has_dependency_support ) { + remove_all_actions( 'amp_customizer_register_settings' ); + remove_all_actions( 'amp_customizer_register_ui' ); + remove_all_actions( 'amp_customizer_enqueue_preview_scripts' ); - AMP_Options_Manager::update_option( Option::THEME_SUPPORT, AMP_Theme_Support::READER_MODE_SLUG ); - $this->assertEquals( true, AMP_Customizer_Design_Settings::is_amp_customizer_enabled() ); + if ( $has_dependency_support ) { + $GLOBALS['wp_version'] = '5.6'; + } else { + $GLOBALS['wp_version'] = '5.5'; + } + $has_dependency_support = ( new DependencySupport() )->has_support(); // To account for Gutenberg being active. - add_filter( 'amp_customizer_is_enabled', '__return_false' ); - $this->assertEquals( false, AMP_Customizer_Design_Settings::is_amp_customizer_enabled() ); + AMP_Customizer_Design_Settings::init_customizer(); + $this->assertEquals( $has_dependency_support ? 10 : false, has_action( 'amp_customizer_register_settings', [ AMP_Customizer_Design_Settings::class, 'register_customizer_settings' ] ) ); + $this->assertEquals( $has_dependency_support ? 10 : false, has_action( 'amp_customizer_register_ui', [ AMP_Customizer_Design_Settings::class, 'register_customizer_ui' ] ) ); + $this->assertEquals( $has_dependency_support ? 10 : false, has_action( 'amp_customizer_enqueue_preview_scripts', [ AMP_Customizer_Design_Settings::class, 'enqueue_customizer_preview_scripts' ] ) ); } /** * Test register_customizer_settings(). * - * @covers AMP_Customizer_Design_Settings::register_customizer_settings + * @covers ::register_customizer_settings() */ public function test_register_customizer_settings() { $wp_customize = new WP_Customize_Manager(); @@ -58,7 +143,7 @@ public function test_register_customizer_settings() { /** * Test register_customizer_ui(). * - * @covers AMP_Customizer_Design_Settings::register_customizer_ui + * @covers ::register_customizer_ui() */ public function test_register_customizer_ui() { $wp_customize = new WP_Customize_Manager(); @@ -98,7 +183,7 @@ public function get_color_schemes() { /** * Test sanitize_color_scheme(). * - * @covers AMP_Customizer_Design_Settings::sanitize_color_scheme + * @covers ::sanitize_color_scheme() * @dataProvider get_color_schemes * * @param string $color_scheme Color scheme. diff --git a/tests/php/test-class-amp-theme-support.php b/tests/php/test-class-amp-theme-support.php index d9097a8f86c..f6e819fd0cc 100644 --- a/tests/php/test-class-amp-theme-support.php +++ b/tests/php/test-class-amp-theme-support.php @@ -1759,11 +1759,11 @@ function ( $dom, $effective_sandboxing_level ) { foreach ( $ordered_contains as $ordered_contain ) { if ( '#' === substr( $ordered_contain, 0, 1 ) ) { $this->assertEquals( 1, preg_match( $ordered_contain, $sanitized_html, $matches, PREG_OFFSET_CAPTURE ), "Failed to find: $ordered_contain" ); - $this->assertGreaterThan( $last_position, $matches[0][1], "'$ordered_contain' is not after '$prev_ordered_contain'" ); + $this->assertGreaterThan( $last_position, $matches[0][1], "'$ordered_contain' is not after '$prev_ordered_contain' in:\n$sanitized_html" ); $last_position = $matches[0][1]; } else { $this_position = strpos( $sanitized_html, $ordered_contain ); - $this->assertNotFalse( $this_position, "Failed to find: $ordered_contain" ); + $this->assertNotFalse( $this_position, "Failed to find: $ordered_contain in:\n$sanitized_html" ); $this->assertGreaterThan( $last_position, (int) $this_position, "'$ordered_contain' is not after '$prev_ordered_contain'" ); $last_position = $this_position; } @@ -2088,7 +2088,7 @@ private function get_original_html() { add_filter( 'script_loader_tag', static function ( $script ) { - return preg_replace( "/ id='amp-[^']+?'/", '', $script ); + return preg_replace( '/ id=(["\'])amp-.*?\1/', '', $script ); } ); diff --git a/tests/php/validation/test-class-amp-validated-url-post-type.php b/tests/php/validation/test-class-amp-validated-url-post-type.php index 7e937b244a1..0c281720446 100644 --- a/tests/php/validation/test-class-amp-validated-url-post-type.php +++ b/tests/php/validation/test-class-amp-validated-url-post-type.php @@ -6,6 +6,7 @@ */ use AmpProject\AmpWP\Admin\ReaderThemes; +use AmpProject\AmpWP\DependencySupport; use AmpProject\AmpWP\DevTools\UserAccess; use AmpProject\AmpWP\Option; use AmpProject\AmpWP\Services; @@ -58,16 +59,23 @@ public function test_register() { AMP_Validated_URL_Post_Type::register(); $amp_post_type = get_post_type_object( AMP_Validated_URL_Post_Type::POST_TYPE_SLUG ); - $this->assertStringContainsString( AMP_Validated_URL_Post_Type::POST_TYPE_SLUG, get_post_types() ); + $this->assertContains( AMP_Validated_URL_Post_Type::POST_TYPE_SLUG, get_post_types() ); $this->assertEquals( [], get_all_post_type_supports( AMP_Validated_URL_Post_Type::POST_TYPE_SLUG ) ); $this->assertEquals( AMP_Validated_URL_Post_Type::POST_TYPE_SLUG, $amp_post_type->name ); $this->assertEquals( 'AMP Validated URLs', $amp_post_type->label ); $this->assertEquals( false, $amp_post_type->public ); $this->assertTrue( $amp_post_type->show_ui ); - $this->assertEquals( AMP_Options_Manager::OPTION_NAME, $amp_post_type->show_in_menu ); - $this->assertTrue( $amp_post_type->show_in_admin_bar ); + if ( ( new DependencySupport() )->has_support() ) { + $this->assertEquals( AMP_Options_Manager::OPTION_NAME, $amp_post_type->show_in_menu ); + } else { + $this->assertFalse( $amp_post_type->show_in_menu ); + } + $this->assertEquals( ( new DependencySupport() )->has_support(), $amp_post_type->show_in_admin_bar ); $this->assertStringNotContainsString( AMP_Validated_URL_Post_Type::REMAINING_ERRORS, wp_removable_query_args() ); - $this->assertEquals( 10, has_action( 'admin_menu', [ self::TESTED_CLASS, 'update_validated_url_menu_item' ] ) ); + $this->assertEquals( + ( new DependencySupport() )->has_support() ? 10 : false, + has_action( 'admin_menu', [ self::TESTED_CLASS, 'update_validated_url_menu_item' ] ) + ); // Make sure that add_admin_hooks() gets called. set_current_screen( 'index.php' ); diff --git a/tests/php/validation/test-class-amp-validation-error-taxonomy.php b/tests/php/validation/test-class-amp-validation-error-taxonomy.php index 5d09a57420f..2e4c5d6e2b5 100644 --- a/tests/php/validation/test-class-amp-validation-error-taxonomy.php +++ b/tests/php/validation/test-class-amp-validation-error-taxonomy.php @@ -6,6 +6,7 @@ */ use AmpProject\AmpWP\DevTools\UserAccess; +use AmpProject\AmpWP\DependencySupport; use AmpProject\AmpWP\Option; use AmpProject\AmpWP\Services; use AmpProject\AmpWP\Tests\Helpers\HandleValidation; @@ -58,7 +59,7 @@ public function test_register() { $this->assertFalse( $taxonomy_object->show_tagcloud ); $this->assertFalse( $taxonomy_object->show_in_quick_edit ); $this->assertFalse( $taxonomy_object->hierarchical ); - $this->assertTrue( $taxonomy_object->show_in_menu ); + $this->assertEquals( ( new DependencySupport() )->has_support(), $taxonomy_object->show_in_menu ); $this->assertFalse( $taxonomy_object->meta_box_cb ); $this->assertEquals( 'AMP Validation Error Index', $taxonomy_object->label ); $this->assertEquals( 'do_not_allow', $taxonomy_object->cap->assign_terms ); @@ -565,7 +566,10 @@ public function test_add_admin_hooks() { $this->assertEquals( 10, has_filter( 'terms_clauses', [ self::TESTED_CLASS, 'filter_terms_clauses_for_description_search' ] ) ); $this->assertEquals( 10, has_action( 'admin_notices', [ self::TESTED_CLASS, 'add_admin_notices' ] ) ); $this->assertEquals( PHP_INT_MAX, has_filter( AMP_Validation_Error_Taxonomy::TAXONOMY_SLUG . '_row_actions', [ self::TESTED_CLASS, 'filter_tag_row_actions' ] ) ); - $this->assertEquals( 10, has_action( 'admin_menu', [ self::TESTED_CLASS, 'add_admin_menu_validation_error_item' ] ) ); + $this->assertEquals( + ( new DependencySupport() )->has_support() ? 10 : false, + has_action( 'admin_menu', [ self::TESTED_CLASS, 'add_admin_menu_validation_error_item' ] ) + ); $this->assertEquals( 10, has_filter( 'manage_' . AMP_Validation_Error_Taxonomy::TAXONOMY_SLUG . '_custom_column', [ self::TESTED_CLASS, 'filter_manage_custom_columns' ] ) ); $this->assertEquals( 10, has_filter( 'manage_' . AMP_Validated_URL_Post_Type::POST_TYPE_SLUG . '_sortable_columns', [ self::TESTED_CLASS, 'add_single_post_sortable_columns' ] ) ); $this->assertEquals( 10, has_filter( 'posts_where', [ self::TESTED_CLASS, 'filter_posts_where_for_validation_error_status' ] ) ); diff --git a/tests/php/validation/test-class-amp-validation-manager.php b/tests/php/validation/test-class-amp-validation-manager.php index bf8edb5ff34..6178dc22e24 100644 --- a/tests/php/validation/test-class-amp-validation-manager.php +++ b/tests/php/validation/test-class-amp-validation-manager.php @@ -7,6 +7,7 @@ // phpcs:disable Generic.Formatting.MultipleStatementAlignment.NotSameWarning +use AmpProject\AmpWP\DependencySupport; use AmpProject\AmpWP\DevTools\UserAccess; use AmpProject\AmpWP\Dom\Options; use AmpProject\AmpWP\Option; @@ -438,11 +439,22 @@ public function test_is_sanitization_auto_accepted() { * @covers AMP_Validation_Manager::add_admin_bar_menu_items() */ public function test_add_admin_bar_menu_items() { + require_once ABSPATH . WPINC . '/class-wp-admin-bar.php'; + + if ( ! ( new DependencySupport() )->has_support() ) { + wp_set_current_user( self::factory()->user->create( [ 'role' => 'administrator' ] ) ); + AMP_Options_Manager::update_option( Option::THEME_SUPPORT, AMP_Theme_Support::STANDARD_MODE_SLUG ); + $admin_bar = new WP_Admin_Bar(); + AMP_Validation_Manager::add_admin_bar_menu_items( $admin_bar ); + $this->assertNull( $admin_bar->get_node( 'amp' ) ); + $this->assertNull( $admin_bar->get_node( 'amp-view' ) ); + return; + } + $this->accept_sanitization_by_default( false ); // No admin bar item when user lacks capability. $this->go_to( home_url( '/' ) ); - require_once ABSPATH . WPINC . '/class-wp-admin-bar.php'; $this->assertFalse( is_admin() ); $this->assertFalse( AMP_Validation_Manager::has_cap() ); $admin_bar = new WP_Admin_Bar(); @@ -490,20 +502,28 @@ public function test_add_admin_bar_menu_items() { $admin_bar = new WP_Admin_Bar(); AMP_Validation_Manager::add_admin_bar_menu_items( $admin_bar ); $node = $admin_bar->get_node( 'amp' ); - $this->assertIsObject( $node ); + if ( ( new DependencySupport() )->has_support() ) { + $this->assertIsObject( $node ); + } else { + $this->assertNull( $node ); + } // Admin bar item available in paired mode. AMP_Options_Manager::update_option( Option::THEME_SUPPORT, AMP_Theme_Support::TRANSITIONAL_MODE_SLUG ); $admin_bar = new WP_Admin_Bar(); AMP_Validation_Manager::add_admin_bar_menu_items( $admin_bar ); $root_node = $admin_bar->get_node( 'amp' ); - $this->assertIsObject( $root_node ); - $this->assertEqualSets( [ QueryVar::AMP ], array_keys( $this->get_url_query_vars( $root_node->href ) ) ); - - $view_item = $admin_bar->get_node( 'amp-view' ); - $this->assertIsObject( $view_item ); - $this->assertEqualSets( [ QueryVar::AMP ], array_keys( $this->get_url_query_vars( $view_item->href ) ) ); - $this->assertIsObject( $admin_bar->get_node( 'amp-validity' ) ); + if ( ( new DependencySupport() )->has_support() ) { + $this->assertIsObject( $root_node ); + $this->assertEqualSets( [ QueryVar::AMP ], array_keys( $this->get_url_query_vars( $root_node->href ) ) ); + + $view_item = $admin_bar->get_node( 'amp-view' ); + $this->assertIsObject( $view_item ); + $this->assertEqualSets( [ QueryVar::AMP ], array_keys( $this->get_url_query_vars( $view_item->href ) ) ); + $this->assertIsObject( $admin_bar->get_node( 'amp-validity' ) ); + } else { + $this->assertNull( $root_node ); + } // Lastly, confirm that the settings item is added if the user is an admin. wp_set_current_user( 0 ); @@ -2393,6 +2413,10 @@ function () { * @covers \AMP_Validation_Manager::add_admin_bar_menu_items() */ public function test_finalize_validation() { + if ( ! ( new DependencySupport() )->has_support() ) { + $this->markTestSkipped( 'Test requires newer version of WP.' ); + } + self::set_capability(); require_once ABSPATH . WPINC . '/class-wp-admin-bar.php'; show_admin_bar( true ); @@ -2838,6 +2862,12 @@ public function test_enqueue_block_validation() { $this->setup_environment( true, true ); $service->set_user_enabled( wp_get_current_user()->ID, true ); AMP_Validation_Manager::enqueue_block_validation(); + + if ( ! ( new DependencySupport() )->has_support() ) { + $this->assertFalse( wp_script_is( $slug, 'enqueued' ) ); + return; + } + $this->assertTrue( wp_script_is( $slug, 'enqueued' ) ); $script = wp_scripts()->registered[ $slug ];