diff --git a/changelog.txt b/changelog.txt index b24b8294744d6..193fe8dfe70f6 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,22 @@ == Changelog == += 17.5.1 = + +## Changelog + +### Bug Fixes + +- (Preferences)(hotfix)(17.5) Hotfix for missing preferences in the `core` scope([58031](https://github.com/WordPress/gutenberg/pull/58031)) + +## Contributors + +The following contributors merged PRs in this release: + +@youknowriad @fullofcaffeine + + + + = 17.5.0 = ## Changelog diff --git a/docs/getting-started/fundamentals/block-wrapper.md b/docs/getting-started/fundamentals/block-wrapper.md index 1f2404eca9b03..cf588cf33cf6f 100644 --- a/docs/getting-started/fundamentals/block-wrapper.md +++ b/docs/getting-started/fundamentals/block-wrapper.md @@ -2,7 +2,7 @@ Each block's markup is wrapped by a container HTML tag that needs to have the proper attributes to fully work in the Block Editor and to reflect the proper block's style settings when rendered in the Block Editor and the front end. As developers, we have full control over the block's markup, and WordPress provides the tools to add the attributes that need to exist on the wrapper to our block's markup. -Ensuring proper attributes to the block wrapper is especially important when using custom styling or features like `supports`. +Ensuring proper attributes to the block wrapper is especially important when using custom styling or features like `supports`.
The use of supports generates a set of properties that need to be manually added to the wrapping element of the block so they're properly stored as part of the block data. @@ -10,8 +10,8 @@ The use of supports generates a set of properties that need to be m A block can have three sets of markup defined, each one of them with a specific target and purpose: -- The one for the **Block Editor**, defined through a `edit` React component passed to [`registerBlockType`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/#registerblocktype) when registering the block in the client. -- The one used to **save the block in the DB**, defined through a `save` function passed to `registerBlockType` when registering the block in the client. +- The one for the **Block Editor**, defined through a `edit` React component passed to [`registerBlockType`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/#registerblocktype) when registering the block in the client. +- The one used to **save the block in the DB**, defined through a `save` function passed to `registerBlockType` when registering the block in the client. - This markup will be returned to the front end on request if no dynamic render has been defined for the block. - The one used to **dynamically render the markup of the block** returned to the front end on request, defined through the `render_callback` on [`register_block_type`](https://developer.wordpress.org/reference/functions/register_block_type/) or the [`render`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/#render) PHP file in `block.json` - If defined, this server-side generated markup will be returned to the front end, ignoring the markup stored in DB. @@ -21,13 +21,13 @@ For the [`edit` React component and the `save` function](https://developer.wordp ## The Edit component's markup -The [`useBlockProps()`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops) hook available on the [`@wordpress/block-editor`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor) allows passing the required attributes for the Block Editor to the `edit` block's outer wrapper. +The [`useBlockProps()`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops) hook available on the [`@wordpress/block-editor`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor) allows passing the required attributes for the Block Editor to the `edit` block's outer wrapper. Among other things, the `useBlockProps()` hook takes care of including in this wrapper: -- An `id` for the block's markup -- Some accesibility and `data-` attributes +- An `id` for the block's markup +- Some accessibility and `data-` attributes - Classes and inline styles reflecting custom settings, which include by default: - - The `wp-block` class + - The `wp-block` class - A class that contains the name of the block with its namespace For example, for the following piece of code of a block's registration in the client... @@ -43,18 +43,18 @@ _(see the [code above](https://github.com/WordPress/block-development-examples/b ...the markup of the block in the Block Editor could look like this: ```html -

Hello World - Block Editor

@@ -87,16 +87,16 @@ _(see the [code above](https://github.com/WordPress/block-development-examples/b

Hello World – Frontend

``` -Any additional classes and attributes for the `save` function of the block should be passed as an argument of `useBlockProps.save()` (see [example](https://github.com/WordPress/block-development-examples/blob/trunk/plugins/stylesheets-79a4c3/src/save.js)). +Any additional classes and attributes for the `save` function of the block should be passed as an argument of `useBlockProps.save()` (see [example](https://github.com/WordPress/block-development-examples/blob/trunk/plugins/stylesheets-79a4c3/src/save.js)). When you add `supports` for any feature, the proper classes get added to the object returned by the `useBlockProps.save()` hook. ```html

Hello World

``` @@ -105,10 +105,10 @@ _(check the [example](https://github.com/WordPress/block-development-examples/tr ## The server-side render markup -Any markup in the server-side render definition for the block can use the [`get_block_wrapper_attributes()`](https://developer.wordpress.org/reference/functions/get_block_wrapper_attributes/) function to generate the string of attributes required to reflect the block settings (see [example](https://github.com/WordPress/block-development-examples/blob/f68640f42d993f0866d1879f67c73910285ca114/plugins/block-dynamic-rendering-64756b/src/render.php#L11)). +Any markup in the server-side render definition for the block can use the [`get_block_wrapper_attributes()`](https://developer.wordpress.org/reference/functions/get_block_wrapper_attributes/) function to generate the string of attributes required to reflect the block settings (see [example](https://github.com/WordPress/block-development-examples/blob/f68640f42d993f0866d1879f67c73910285ca114/plugins/block-dynamic-rendering-64756b/src/render.php#L11)). ```php

>

-``` \ No newline at end of file +``` diff --git a/docs/how-to-guides/block-tutorial/extending-the-query-loop-block.md b/docs/how-to-guides/block-tutorial/extending-the-query-loop-block.md index 9be4f3a993d20..d3628d991f872 100644 --- a/docs/how-to-guides/block-tutorial/extending-the-query-loop-block.md +++ b/docs/how-to-guides/block-tutorial/extending-the-query-loop-block.md @@ -208,13 +208,13 @@ export const withBookQueryControls = ( BlockEdit ) => ( props ) => { // function to handle that. return isMyBooksVariation( props ) ? ( <> - + { /** Our custom component */ } ) : ( - + ); }; diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index bee68530eeb23..ab6bb52b6b3b2 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -42,7 +42,7 @@ Create and save content to reuse across your site. Update the pattern, and the c - **Name:** core/block - **Category:** reusable - **Supports:** ~~customClassName~~, ~~html~~, ~~inserter~~, ~~renaming~~ -- **Attributes:** ref +- **Attributes:** overrides, ref ## Button diff --git a/docs/reference-guides/filters/block-filters.md b/docs/reference-guides/filters/block-filters.md index 4c7e3df7cec12..35a041052889c 100644 --- a/docs/reference-guides/filters/block-filters.md +++ b/docs/reference-guides/filters/block-filters.md @@ -19,11 +19,11 @@ _Example_: ```php { return ( props ) => { return ( <> - + My custom control @@ -352,14 +352,14 @@ On the server, you can filter the list of blocks shown in the inserter using the post ) ) { return array( 'core/paragraph', 'core/heading' ); } return $allowed_block_types; } -add_filter( 'allowed_block_types_all', 'filter_allowed_block_types_when_post_provided', 10, 2 ); +add_filter( 'allowed_block_types_all', 'wpdocs_filter_allowed_block_types_when_post_provided', 10, 2 ); ``` ## Managing block categories @@ -374,7 +374,7 @@ It is possible to filter the list of default block categories using the `block_c post ) ) { array_push( $block_categories, @@ -388,7 +388,7 @@ function filter_block_categories_when_post_provided( $block_categories, $editor_ return $block_categories; } -add_filter( 'block_categories_all', 'filter_block_categories_when_post_provided', 10, 2 ); +add_filter( 'block_categories_all', 'wpdocs_filter_block_categories_when_post_provided', 10, 2 ); ``` ### `wp.blocks.updateCategory` diff --git a/docs/reference-guides/filters/editor-filters.md b/docs/reference-guides/filters/editor-filters.md index 59f6d7ef8213f..943e161a1df49 100644 --- a/docs/reference-guides/filters/editor-filters.md +++ b/docs/reference-guides/filters/editor-filters.md @@ -84,14 +84,14 @@ _Example:_ post ) ) { $editor_settings['maxUploadFileSize'] = 12345; } return $editor_settings; } -add_filter( 'block_editor_settings_all', 'filter_block_editor_settings_when_post_provided', 10, 2 ); +add_filter( 'block_editor_settings_all', 'wpdocs_filter_block_editor_settings_when_post_provided', 10, 2 ); ``` #### `block_editor_rest_api_preload_paths` @@ -104,14 +104,14 @@ _Example:_ post ) ) { array_push( $preload_paths, array( '/wp/v2/blocks', 'OPTIONS' ) ); } return $preload_paths; } -add_filter( 'block_editor_rest_api_preload_paths', 'filter_block_editor_rest_api_preload_paths_when_post_provided', 10, 2 ); +add_filter( 'block_editor_rest_api_preload_paths', 'wpdocs_filter_block_editor_rest_api_preload_paths_when_post_provided', 10, 2 ); ``` ### Available default editor settings diff --git a/docs/reference-guides/filters/global-styles-filters.md b/docs/reference-guides/filters/global-styles-filters.md index 7d3b6be95768b..59bbbfcd5921d 100644 --- a/docs/reference-guides/filters/global-styles-filters.md +++ b/docs/reference-guides/filters/global-styles-filters.md @@ -14,7 +14,7 @@ _Example:_ This is how to pass a new color palette for the theme and disable the text color UI: ```php -function filter_theme_json_theme( $theme_json ){ +function wpdocs_filter_theme_json_theme( $theme_json ){ $new_data = array( 'version' => 2, 'settings' => array( @@ -38,5 +38,5 @@ function filter_theme_json_theme( $theme_json ){ return $theme_json->update_with( $new_data ); } -add_filter( 'wp_theme_json_data_theme', 'filter_theme_json_theme' ); +add_filter( 'wp_theme_json_data_theme', 'wpdocs_filter_theme_json_theme' ); ``` diff --git a/docs/reference-guides/filters/parser-filters.md b/docs/reference-guides/filters/parser-filters.md index 3acfb2489182d..7adc68cc0bf7e 100644 --- a/docs/reference-guides/filters/parser-filters.md +++ b/docs/reference-guides/filters/parser-filters.md @@ -26,11 +26,11 @@ class EmptyParser { } } -function my_plugin_select_empty_parser( $prev_parser_class ) { +function wpdocs_select_empty_parser( $prev_parser_class ) { return 'EmptyParser'; } -add_filter( 'block_parser_class', 'my_plugin_select_empty_parser', 10, 1 ); +add_filter( 'block_parser_class', 'wpdocs_select_empty_parser', 10, 1 ); ``` > **Note**: At the present time it's not possible to replace the client-side parser. diff --git a/gutenberg.php b/gutenberg.php index febd63e0be030..e3ef3d1612722 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.3 * Requires PHP: 7.0 - * Version: 17.5.0 + * Version: 17.5.1 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/lib/block-supports/pattern.php b/lib/block-supports/pattern.php deleted file mode 100644 index 0c5868c1fea0c..0000000000000 --- a/lib/block-supports/pattern.php +++ /dev/null @@ -1,46 +0,0 @@ - array( 'content' ), - 'core/heading' => array( 'content' ), - 'core/image' => array( 'url', 'title', 'alt' ), - 'core/button' => array( 'url', 'text' ), - ); - $pattern_support = array_key_exists( $block_type->name, $allowed_blocks ); - - if ( $pattern_support ) { - if ( ! $block_type->uses_context ) { - $block_type->uses_context = array(); - } - - if ( ! in_array( 'pattern/overrides', $block_type->uses_context, true ) ) { - $block_type->uses_context[] = 'pattern/overrides'; - } - } - } - - // Register the block support. - WP_Block_Supports::get_instance()->register( - 'pattern', - array( - 'register_attribute' => 'gutenberg_register_pattern_support', - ) - ); -} diff --git a/lib/blocks.php b/lib/blocks.php index d5283afeb7f99..e1d4622a0f23d 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -440,27 +440,6 @@ function gutenberg_legacy_wp_block_post_meta( $value, $object_id, $meta_key, $si add_filter( 'default_post_metadata', 'gutenberg_legacy_wp_block_post_meta', 10, 4 ); -/** - * Registers the metadata block attribute for all block types. - * - * @param array $args Array of arguments for registering a block type. - * @return array $args - */ -function gutenberg_register_metadata_attribute( $args ) { - // Setup attributes if needed. - if ( ! isset( $args['attributes'] ) || ! is_array( $args['attributes'] ) ) { - $args['attributes'] = array(); - } - - if ( ! array_key_exists( 'metadata', $args['attributes'] ) ) { - $args['attributes']['metadata'] = array( - 'type' => 'object', - ); - } - - return $args; -} -add_filter( 'register_block_type_args', 'gutenberg_register_metadata_attribute' ); /** * Strips all HTML from the content of footnotes, and sanitizes the ID. diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index a063ab34d9069..f4266a7ef66dd 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -1010,7 +1010,7 @@ protected static function get_blocks_metadata() { if ( $duotone_support ) { $root_selector = wp_get_block_css_selector( $block_type ); - $duotone_selector = WP_Theme_JSON_Gutenberg::scope_selector( $root_selector, $duotone_support ); + $duotone_selector = static::scope_selector( $root_selector, $duotone_support ); } } @@ -1185,7 +1185,7 @@ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets' $setting_nodes[ $root_settings_key ]['selector'] = $options['root_selector']; } if ( false !== $root_style_key ) { - $setting_nodes[ $root_style_key ]['selector'] = $options['root_selector']; + $style_nodes[ $root_style_key ]['selector'] = $options['root_selector']; } } diff --git a/lib/compat/wordpress-6.5/block-patterns.php b/lib/compat/wordpress-6.5/block-patterns.php index f43acda2a1035..cce97cb19c690 100644 --- a/lib/compat/wordpress-6.5/block-patterns.php +++ b/lib/compat/wordpress-6.5/block-patterns.php @@ -49,7 +49,7 @@ function gutenberg_register_taxonomy_patterns() { 'singular_name' => _x( 'Pattern Category', 'taxonomy singular name' ), 'add_new_item' => __( 'Add New Category' ), 'add_or_remove_items' => __( 'Add or remove pattern categories' ), - 'back_to_items' => __( '← Go to pattern categories' ), + 'back_to_items' => __( '← Go to Pattern Categories' ), 'choose_from_most_used' => __( 'Choose from the most used pattern categories' ), 'edit_item' => __( 'Edit Pattern Category' ), 'item_link' => __( 'Pattern Category Link' ), diff --git a/lib/compat/wordpress-6.5/blocks.php b/lib/compat/wordpress-6.5/blocks.php index 0cbd48d50eefc..0ec7d14e0f46a 100644 --- a/lib/compat/wordpress-6.5/blocks.php +++ b/lib/compat/wordpress-6.5/blocks.php @@ -101,3 +101,26 @@ function gutenberg_process_block_bindings( $block_content, $block, $block_instan } add_filter( 'render_block', 'gutenberg_process_block_bindings', 20, 3 ); + + +/** + * Registers the metadata block attribute for all block types. + * + * @param array $args Array of arguments for registering a block type. + * @return array $args + */ +function gutenberg_register_metadata_attribute( $args ) { + // Setup attributes if needed. + if ( ! isset( $args['attributes'] ) || ! is_array( $args['attributes'] ) ) { + $args['attributes'] = array(); + } + + if ( ! array_key_exists( 'metadata', $args['attributes'] ) ) { + $args['attributes']['metadata'] = array( + 'type' => 'object', + ); + } + + return $args; +} +add_filter( 'register_block_type_args', 'gutenberg_register_metadata_attribute' ); diff --git a/lib/experimental/fonts-api/bc-layer/class-gutenberg-fonts-api-bc-layer.php b/lib/experimental/fonts-api/bc-layer/class-gutenberg-fonts-api-bc-layer.php deleted file mode 100644 index 8c85976987523..0000000000000 --- a/lib/experimental/fonts-api/bc-layer/class-gutenberg-fonts-api-bc-layer.php +++ /dev/null @@ -1,96 +0,0 @@ -variation_property_defaults = apply_filters( 'wp_webfont_variation_defaults', $this->variation_property_defaults ); - - /** - * Fires when the WP_Webfonts instance is initialized. - * - * @since X.X.X - * - * @param WP_Web_Fonts $wp_webfonts WP_Web_Fonts instance (passed by reference). - */ - do_action_ref_array( 'wp_default_webfonts', array( &$this ) ); - } - - /** - * Get the list of registered providers. - * - * @since X.X.X - * - * @return array $providers { - * An associative array of registered providers, keyed by their unique ID. - * - * @type string $provider_id => array { - * An associate array of provider's class name and fonts. - * - * @type string $class_name Fully qualified name of the provider's class. - * @type string[] $fonts An array of enqueued font handles for this provider. - * } - * } - */ - public function get_providers() { - return $this->providers; - } - - /** - * Register a provider. - * - * @since X.X.X - * - * @param string $provider_id The provider's unique ID. - * @param string $class_name The provider class name. - * @return bool True if successfully registered, else false. - */ - public function register_provider( $provider_id, $class_name ) { - if ( empty( $provider_id ) || empty( $class_name ) || ! class_exists( $class_name ) ) { - return false; - } - - $this->providers[ $provider_id ] = array( - 'class' => $class_name, - 'fonts' => array(), - ); - return true; - } - - /** - * Get the list of all registered font family handles. - * - * @since X.X.X - * - * @return string[] - */ - public function get_registered_font_families() { - $font_families = array(); - foreach ( $this->registered as $handle => $obj ) { - if ( $obj->extra['is_font_family'] ) { - $font_families[] = $handle; - } - } - return $font_families; - } - - /** - * Get the list of all registered font families and their variations. - * - * @since X.X.X - * - * @return string[] - */ - public function get_registered() { - return array_keys( $this->registered ); - } - - /** - * Get the list of enqueued font families and their variations. - * - * @since X.X.X - * - * @return array[] - */ - public function get_enqueued() { - return $this->queue; - } - - /** - * Registers a font family. - * - * @since X.X.X - * - * @param string $font_family Font family name to register. - * @return string|null Font family handle when registration successes. Null on failure. - */ - public function add_font_family( $font_family ) { - $font_family_handle = WP_Fonts_Utils::convert_font_family_into_handle( $font_family ); - if ( ! $font_family_handle ) { - return null; - } - - if ( isset( $this->registered[ $font_family_handle ] ) ) { - return $font_family_handle; - } - - $registered = $this->add( $font_family_handle, false ); - if ( ! $registered ) { - return null; - } - - $this->add_data( $font_family_handle, 'font-properties', array( 'font-family' => $font_family ) ); - $this->add_data( $font_family_handle, 'is_font_family', true ); - - return $font_family_handle; - } - - /** - * Removes a font family and all registered variations. - * - * @since X.X.X - * - * @param string $font_family_handle The font family to remove. - */ - public function remove_font_family( $font_family_handle ) { - if ( ! isset( $this->registered[ $font_family_handle ] ) ) { - return; - } - - $variations = $this->registered[ $font_family_handle ]->deps; - - foreach ( $variations as $variation ) { - $this->remove( $variation ); - } - - $this->remove( $font_family_handle ); - } - - /** - * Add a variation to an existing family or register family if none exists. - * - * @since X.X.X - * - * @param string $font_family_handle The font family's handle for this variation. - * @param array $variation An array of variation properties to add. - * @param string $variation_handle Optional. The variation's handle. When none is provided, the - * handle will be dynamically generated. - * Default empty string. - * @return string|null Variation handle on success. Else null. - */ - public function add_variation( $font_family_handle, array $variation, $variation_handle = '' ) { - if ( ! WP_Fonts_Utils::is_defined( $font_family_handle ) ) { - trigger_error( 'Font family handle must be a non-empty string.' ); - return null; - } - - // When there is a variation handle, check it. - if ( '' !== $variation_handle && ! WP_Fonts_Utils::is_defined( $variation_handle ) ) { - trigger_error( 'Variant handle must be a non-empty string.' ); - return null; - } - - // Register the font family when it does not yet exist. - if ( ! isset( $this->registered[ $font_family_handle ] ) ) { - if ( ! $this->add_font_family( $font_family_handle ) ) { - return null; - } - } - - $variation = $this->validate_variation( $variation ); - - // Variation validation failed. - if ( ! $variation ) { - return null; - } - - // When there's no variation handle, attempt to create one. - if ( '' === $variation_handle ) { - $variation_handle = WP_Fonts_Utils::convert_variation_into_handle( $font_family_handle, $variation ); - if ( is_null( $variation_handle ) ) { - return null; - } - } - - // Bail out if the variant is already registered. - if ( $this->is_variation_registered( $font_family_handle, $variation_handle ) ) { - return $variation_handle; - } - - $variation_src = array_key_exists( 'src', $variation ) ? $variation['src'] : false; - $result = $this->add( $variation_handle, $variation_src ); - - // Bail out if the registration failed. - if ( ! $result ) { - return null; - } - - $this->add_data( $variation_handle, 'font-properties', $variation ); - $this->add_data( $variation_handle, 'is_font_family', false ); - - // Add the font variation as a dependency to the registered font family. - $this->add_dependency( $font_family_handle, $variation_handle ); - - $this->providers[ $variation['provider'] ]['fonts'][] = $variation_handle; - - return $variation_handle; - } - - /** - * Removes a variation. - * - * @since X.X.X - * - * @param string $font_family_handle The font family for this variation. - * @param string $variation_handle The variation's handle to remove. - */ - public function remove_variation( $font_family_handle, $variation_handle ) { - if ( isset( $this->registered[ $variation_handle ] ) ) { - $this->remove( $variation_handle ); - } - - if ( ! $this->is_variation_registered( $font_family_handle, $variation_handle ) ) { - return; - } - - // Remove the variation as a dependency from its font family. - $this->registered[ $font_family_handle ]->deps = array_values( - array_diff( - $this->registered[ $font_family_handle ]->deps, - array( $variation_handle ) - ) - ); - } - - /** - * Checks if the variation is registered. - * - * @since X.X.X - * - * @param string $font_family_handle The font family's handle for this variation. - * @param string $variation_handle Variation's handle. - * @return bool True when registered to the given font family. Else false. - */ - private function is_variation_registered( $font_family_handle, $variation_handle ) { - if ( ! isset( $this->registered[ $font_family_handle ] ) ) { - return false; - } - - return in_array( $variation_handle, $this->registered[ $font_family_handle ]->deps, true ); - } - - /** - * Adds a variation as a dependency to the given font family. - * - * @since X.X.X - * - * @param string $font_family_handle The font family's handle for this variation. - * @param string $variation_handle The variation's handle. - */ - private function add_dependency( $font_family_handle, $variation_handle ) { - $this->registered[ $font_family_handle ]->deps[] = $variation_handle; - } - - /** - * Validates and sanitizes a variation. - * - * @since X.X.X - * - * @param array $variation Variation properties to add. - * @return false|array Validated variation on success. Else, false. - */ - private function validate_variation( $variation ) { - $variation = wp_parse_args( $variation, $this->variation_property_defaults ); - - // Check the font-family. - if ( empty( $variation['font-family'] ) || ! is_string( $variation['font-family'] ) ) { - trigger_error( 'Webfont font-family must be a non-empty string.' ); - return false; - } - - // Local fonts need a "src". - if ( 'local' === $variation['provider'] ) { - // Make sure that local fonts have 'src' defined. - if ( empty( $variation['src'] ) || ( ! is_string( $variation['src'] ) && ! is_array( $variation['src'] ) ) ) { - trigger_error( 'Webfont src must be a non-empty string or an array of strings.' ); - return false; - } - } elseif ( ! isset( $this->providers[ $variation['provider'] ] ) ) { - trigger_error( sprintf( 'The provider "%s" is not registered', $variation['provider'] ) ); - return false; - } elseif ( ! class_exists( $this->providers[ $variation['provider'] ]['class'] ) ) { - trigger_error( sprintf( 'The provider class "%s" does not exist', $variation['provider'] ) ); - return false; - } - - // Validate the 'src' property. - if ( ! empty( $variation['src'] ) ) { - foreach ( (array) $variation['src'] as $src ) { - if ( empty( $src ) || ! is_string( $src ) ) { - trigger_error( 'Each webfont src must be a non-empty string.' ); - return false; - } - } - } - - // Check the font-weight. - if ( ! is_string( $variation['font-weight'] ) && ! is_int( $variation['font-weight'] ) ) { - trigger_error( 'Webfont font-weight must be a properly formatted string or integer.' ); - return false; - } - - // Check the font-display. - if ( ! in_array( $variation['font-display'], array( 'auto', 'block', 'fallback', 'swap', 'optional' ), true ) ) { - $variation['font-display'] = 'fallback'; - } - - $valid_props = array( - 'ascent-override', - 'descent-override', - 'font-display', - 'font-family', - 'font-stretch', - 'font-style', - 'font-weight', - 'font-variant', - 'font-feature-settings', - 'font-variation-settings', - 'line-gap-override', - 'size-adjust', - 'src', - 'unicode-range', - - // Exceptions. - 'provider', - ); - - foreach ( $variation as $prop => $value ) { - if ( ! in_array( $prop, $valid_props, true ) ) { - unset( $variation[ $prop ] ); - } - } - - return $variation; - } - - /** - * Processes the items and dependencies. - * - * Processes the items passed to it or the queue, and their dependencies. - * - * @since X.X.X - * - * @param string|string[]|bool $handles Optional. Items to be processed: queue (false), - * single item (string), or multiple items (array of strings). - * Default false. - * @param int|false $group Optional. Group level: level (int), no group (false). - * - * @return array|string[] Array of web font handles that have been processed. - * An empty array if none were processed. - */ - public function do_items( $handles = false, $group = false ) { - $handles = $this->prepare_handles_for_printing( $handles ); - - if ( empty( $handles ) ) { - return $this->done; - } - - $this->all_deps( $handles ); - if ( empty( $this->to_do ) ) { - return $this->done; - } - - $this->to_do_keyed_handles = array_flip( $this->to_do ); - - foreach ( $this->get_providers() as $provider_id => $provider ) { - // Alert and skip if the provider class does not exist. - if ( ! class_exists( $provider['class'] ) ) { - /* translators: %s is the provider name. */ - trigger_error( - sprintf( - 'Class "%s" not found for "%s" web font provider', - $provider['class'], - $provider_id - ) - ); - continue; - } - - $this->do_item( $provider_id, $group ); - } - - $this->process_font_families_after_printing( $handles ); - - return $this->done; - } - - /** - * Prepares the given handles for printing. - * - * @since X.X.X - * - * @param string|string[]|bool $handles Optional. Handles to prepare. - * Default false. - * @return array Array of handles. - */ - private function prepare_handles_for_printing( $handles = false ) { - if ( false !== $handles ) { - $handles = $this->validate_handles( $handles ); - // Bail out when invalid. - if ( empty( $handles ) ) { - return array(); - } - } - - // Use the enqueued queue. - if ( empty( $handles ) ) { - if ( empty( $this->queue ) ) { - return array(); - } - $handles = $this->queue; - } - - return $handles; - } - - /** - * Validates handle(s) to ensure each is a non-empty string. - * - * @since X.X.X - * - * @param string|string[] $handles Handles to prepare. - * @return string[]|null Array of handles on success. Else null. - */ - private function validate_handles( $handles ) { - // Validate each element is a non-empty string handle. - $handles = array_filter( (array) $handles, array( WP_Fonts_Utils::class, 'is_defined' ) ); - - if ( empty( $handles ) ) { - trigger_error( 'Handles must be a non-empty string or array of non-empty strings' ); - return null; - } - - return $handles; - } - - /** - * Invokes each provider to process and print its styles. - * - * @since X.X.X - * - * @see WP_Dependencies::do_item() - * - * @param string $provider_id The provider to process. - * @param int|false $group Not used. - * @return bool - */ - public function do_item( $provider_id, $group = false ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable - // Bail out if the provider is not registered. - if ( ! isset( $this->providers[ $provider_id ] ) ) { - return false; - } - - $font_handles = $this->get_enqueued_fonts_for_provider( $provider_id ); - if ( empty( $font_handles ) ) { - return false; - } - - $properties_by_font = $this->get_font_properties_for_provider( $font_handles ); - if ( empty( $properties_by_font ) ) { - return false; - } - - // Invoke provider to print its styles. - $provider = $this->get_provider_instance( $provider_id ); - $provider->set_fonts( $properties_by_font ); - $provider->print_styles(); - - // Clean up. - $this->update_queues_for_printed_fonts( $font_handles ); - - return true; - } - - /** - * Retrieves a list of enqueued web font variations for a provider. - * - * @since X.X.X - * - * @param string $provider_id The provider to process. - * @return array[] Webfonts organized by providers. - */ - private function get_enqueued_fonts_for_provider( $provider_id ) { - $providers = $this->get_providers(); - - if ( empty( $providers[ $provider_id ] ) ) { - return array(); - } - - return array_intersect( - $providers[ $provider_id ]['fonts'], - $this->to_do - ); - } - - /** - * Gets a list of font properties for each of the given font handles. - * - * @since X.X.X - * - * @param array $font_handles Font handles to get properties. - * @return array A list of fonts with each font's properties. - */ - private function get_font_properties_for_provider( array $font_handles ) { - $font_properties = array(); - - foreach ( $font_handles as $font_handle ) { - $properties = $this->get_data( $font_handle, 'font-properties' ); - if ( ! $properties ) { - continue; - } - $font_properties[ $font_handle ] = $properties; - } - - return $font_properties; - } - - /** - * Gets the instance of the provider from the WP_Webfonts::$provider_instance store. - * - * @since X.X.X - * - * @param string $provider_id The provider to get. - * @return object Instance of the provider. - */ - private function get_provider_instance( $provider_id ) { - if ( ! isset( $this->provider_instances[ $provider_id ] ) ) { - $this->provider_instances[ $provider_id ] = new $this->providers[ $provider_id ]['class'](); - } - return $this->provider_instances[ $provider_id ]; - } - - /** - * Update queues for the given printed fonts. - * - * @since X.X.X - * - * @param array $font_handles Font handles to get properties. - */ - private function update_queues_for_printed_fonts( array $font_handles ) { - foreach ( $font_handles as $font_handle ) { - $this->set_as_done( $font_handle ); - $this->remove_from_to_do_queues( $font_handle ); - } - } - - /** - * Processes the font families after printing the variations. - * - * For each queued font family: - * - * a. if any of their variations were printed, the font family is added to the `done` list. - * b. removes each from the to_do queues. - * - * @since X.X.X - * - * @param array $handles Handles to process. - */ - private function process_font_families_after_printing( array $handles ) { - foreach ( $handles as $handle ) { - if ( - ! $this->get_data( $handle, 'is_font_family' ) || - ! isset( $this->to_do_keyed_handles[ $handle ] ) - ) { - continue; - } - $font_family = $this->registered[ $handle ]; - - // Add the font family to `done` list if any of its variations were printed. - if ( ! empty( $font_family->deps ) ) { - $processed = array_intersect( $font_family->deps, $this->done ); - if ( ! empty( $processed ) ) { - $this->set_as_done( $handle ); - } - } - - $this->remove_from_to_do_queues( $handle ); - } - } - - /** - * Removes the handle from the `to_do` and `to_do_keyed_handles` lists. - * - * @since X.X.X - * - * @param string $handle Handle to remove. - */ - private function remove_from_to_do_queues( $handle ) { - unset( - $this->to_do[ $this->to_do_keyed_handles[ $handle ] ], - $this->to_do_keyed_handles[ $handle ] - ); - } - - /** - * Sets the given handle to done by adding it to the `done` list. - * - * @since X.X.X - * - * @param string $handle Handle to set as done. - */ - private function set_as_done( $handle ) { - if ( ! is_array( $this->done ) ) { - $this->done = array(); - } - $this->done[] = $handle; - } - - /** - * Converts the font family and its variations into theme.json structural format. - * - * @since X.X.X - * - * @param string $font_family_handle Font family to convert. - * @return array Webfonts in theme.json structural format. - */ - public function to_theme_json( $font_family_handle ) { - if ( ! isset( $this->registered[ $font_family_handle ] ) ) { - return array(); - } - - $font_family_name = $this->registered[ $font_family_handle ]->extra['font-properties']['font-family']; - $theme_json_format = array( - 'fontFamily' => str_contains( $font_family_name, ' ' ) ? "'{$font_family_name}'" : $font_family_name, - 'name' => $font_family_name, - 'slug' => $font_family_handle, - 'fontFace' => array(), - ); - - foreach ( $this->registered[ $font_family_handle ]->deps as $variation_handle ) { - if ( ! isset( $this->registered[ $variation_handle ] ) ) { - continue; - } - - $variation_obj = $this->registered[ $variation_handle ]; - $variation_properties = array( 'origin' => 'gutenberg_wp_fonts_api' ); - foreach ( $variation_obj->extra['font-properties'] as $property_name => $property_value ) { - $property_in_camelcase = lcfirst( str_replace( '-', '', ucwords( $property_name, '-' ) ) ); - $variation_properties[ $property_in_camelcase ] = $property_value; - } - $theme_json_format['fontFace'][ $variation_obj->handle ] = $variation_properties; - } - - return $theme_json_format; - } -} diff --git a/lib/experimental/fonts-api/bc-layer/class-wp-webfonts-provider-local.php b/lib/experimental/fonts-api/bc-layer/class-wp-webfonts-provider-local.php deleted file mode 100644 index b6fd5d78a1435..0000000000000 --- a/lib/experimental/fonts-api/bc-layer/class-wp-webfonts-provider-local.php +++ /dev/null @@ -1,284 +0,0 @@ -style_tag_atts = array( 'type' => 'text/css' ); - } - } - - /** - * Gets the `@font-face` CSS styles for locally-hosted font files. - * - * This method does the following processing tasks: - * 1. Orchestrates an optimized `src` (with format) for browser support. - * 2. Generates the `@font-face` for all its webfonts. - * - * For example, when given these webfonts: - * - * array( - * 'source-serif-pro.normal.200 900' => array( - * 'provider' => 'local', - * 'font_family' => 'Source Serif Pro', - * 'font_weight' => '200 900', - * 'font_style' => 'normal', - * 'src' => 'https://example.com/wp-content/themes/twentytwentytwo/assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2' ), - * ), - * 'source-serif-pro.italic.400 900' => array( - * 'provider' => 'local', - * 'font_family' => 'Source Serif Pro', - * 'font_weight' => '200 900', - * 'font_style' => 'italic', - * 'src' => 'https://example.com/wp-content/themes/twentytwentytwo/assets/fonts/source-serif-pro/SourceSerif4Variable-Italic.ttf.woff2' ), - * ), - * ) - * - * - * the following `@font-face` styles are generated and returned: - * - * - * @font-face{ - * font-family:"Source Serif Pro"; - * font-style:normal; - * font-weight:200 900; - * font-stretch:normal; - * src:local("Source Serif Pro"), url('/assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2') format('woff2'); - * } - * @font-face{ - * font-family:"Source Serif Pro"; - * font-style:italic; - * font-weight:200 900; - * font-stretch:normal; - * src:local("Source Serif Pro"), url('/assets/fonts/source-serif-pro/SourceSerif4Variable-Italic.ttf.woff2') format('woff2'); - * } - * - * - * @since X.X.X - * - * @return string The `@font-face` CSS. - */ - public function get_css() { - $css = ''; - - foreach ( $this->webfonts as $webfont ) { - // Order the webfont's `src` items to optimize for browser support. - $webfont = $this->order_src( $webfont ); - - // Build the @font-face CSS for this webfont. - $css .= '@font-face{' . $this->build_font_face_css( $webfont ) . '}'; - } - - return $css; - } - - /** - * Order `src` items to optimize for browser support. - * - * @since 6.0.0 - * - * @param array $webfont Webfont to process. - * @return array - */ - private function order_src( array $webfont ) { - if ( ! is_array( $webfont['src'] ) ) { - $webfont['src'] = (array) $webfont['src']; - } - - $src = array(); - $src_ordered = array(); - - foreach ( $webfont['src'] as $url ) { - // Add data URIs first. - if ( str_starts_with( trim( $url ), 'data:' ) ) { - $src_ordered[] = array( - 'url' => $url, - 'format' => 'data', - ); - continue; - } - $format = pathinfo( $url, PATHINFO_EXTENSION ); - $src[ $format ] = $url; - } - - // Add woff2. - if ( ! empty( $src['woff2'] ) ) { - $src_ordered[] = array( - 'url' => $src['woff2'], - 'format' => 'woff2', - ); - } - - // Add woff. - if ( ! empty( $src['woff'] ) ) { - $src_ordered[] = array( - 'url' => $src['woff'], - 'format' => 'woff', - ); - } - - // Add ttf. - if ( ! empty( $src['ttf'] ) ) { - $src_ordered[] = array( - 'url' => $src['ttf'], - 'format' => 'truetype', - ); - } - - // Add eot. - if ( ! empty( $src['eot'] ) ) { - $src_ordered[] = array( - 'url' => $src['eot'], - 'format' => 'embedded-opentype', - ); - } - - // Add otf. - if ( ! empty( $src['otf'] ) ) { - $src_ordered[] = array( - 'url' => $src['otf'], - 'format' => 'opentype', - ); - } - $webfont['src'] = $src_ordered; - - return $webfont; - } - - /** - * Builds the font-family's CSS. - * - * @since 6.0.0 - * - * @param array $webfont Webfont to process. - * @return string This font-family's CSS. - */ - private function build_font_face_css( array $webfont ) { - $css = ''; - - // Wrap font-family in quotes if it contains spaces - // and is not already wrapped in quotes. - if ( - str_contains( $webfont['font-family'], ' ' ) && - ! str_contains( $webfont['font-family'], '"' ) && - ! str_contains( $webfont['font-family'], "'" ) - ) { - $webfont['font-family'] = '"' . $webfont['font-family'] . '"'; - } - - foreach ( $webfont as $key => $value ) { - - // Skip "provider", since it's for internal API use, - // and not a valid CSS property. - if ( 'provider' === $key ) { - continue; - } - - // Compile the "src" parameter. - if ( 'src' === $key ) { - $value = $this->compile_src( $webfont['font-family'], $value ); - } - - // If font-variation-settings is an array, convert it to a string. - if ( 'font-variation-settings' === $key && is_array( $value ) ) { - $value = $this->compile_variations( $value ); - } - - if ( ! empty( $value ) ) { - $css .= "$key:$value;"; - } - } - - return $css; - } - - /** - * Compiles the `src` into valid CSS. - * - * @since 6.0.0 - * - * @param string $font_family Font family. - * @param array $value Value to process. - * @return string The CSS. - */ - private function compile_src( $font_family, array $value ) { - $src = "local($font_family)"; - - foreach ( $value as $item ) { - - if ( str_starts_with( $item['url'], get_site_url() ) ) { - $item['url'] = wp_make_link_relative( $item['url'] ); - } - - $src .= ( 'data' === $item['format'] ) - ? ", url({$item['url']})" - : ", url('{$item['url']}') format('{$item['format']}')"; - } - return $src; - } - - /** - * Compiles the font variation settings. - * - * @since 6.0.0 - * - * @param array $font_variation_settings Array of font variation settings. - * @return string The CSS. - */ - private function compile_variations( array $font_variation_settings ) { - $variations = ''; - - foreach ( $font_variation_settings as $key => $value ) { - $variations .= "$key $value"; - } - - return $variations; - } -} diff --git a/lib/experimental/fonts-api/bc-layer/class-wp-webfonts-provider.php b/lib/experimental/fonts-api/bc-layer/class-wp-webfonts-provider.php deleted file mode 100644 index 5b7f5ece335b1..0000000000000 --- a/lib/experimental/fonts-api/bc-layer/class-wp-webfonts-provider.php +++ /dev/null @@ -1,66 +0,0 @@ -webfonts = $this->fonts; - } - - /** - * This method is here to wire WP_Fonts_Provider::do_item() to this - * deprecated class to ensure the fonts get set. - * - * @param array[] $fonts Fonts to be processed. - */ - public function set_fonts( array $fonts ) { - parent::set_fonts( $fonts ); - $this->webfonts = $this->fonts; - } -} diff --git a/lib/experimental/fonts-api/bc-layer/class-wp-webfonts-utils.php b/lib/experimental/fonts-api/bc-layer/class-wp-webfonts-utils.php deleted file mode 100644 index d0242acf9a2b6..0000000000000 --- a/lib/experimental/fonts-api/bc-layer/class-wp-webfonts-utils.php +++ /dev/null @@ -1,85 +0,0 @@ -wp_fonts = ! empty( $wp_fonts ) ? $wp_fonts : wp_fonts(); - } - - /** - * Gets the font slug. - * - * @since X.X.X - * @deprecated Use WP_Fonts_Utils::convert_font_family_into_handle() or WP_Fonts_Utils::get_font_family_from_variation(). - * - * @param array|string $to_convert The value to convert into a slug. Expected as the web font's array - * or a font-family as a string. - * @return string|false The font slug on success, or false if the font-family cannot be determined. - */ - public static function get_font_slug( $to_convert ) { - $message = is_array( $to_convert ) - ? 'Use WP_Fonts_Utils::get_font_family_from_variation() to get the font family from an array and then WP_Fonts_Utils::convert_font_family_into_handle() to convert the font-family name into a handle' - : 'Use WP_Fonts_Utils::convert_font_family_into_handle() to convert the font-family name into a handle'; - _deprecated_function( __METHOD__, 'GB 14.9.1', $message ); - - if ( empty( $to_convert ) ) { - return false; - } - - $font_family_name = is_array( $to_convert ) - ? WP_Fonts_Utils::get_font_family_from_variation( $to_convert ) - : $to_convert; - - $slug = false; - if ( ! empty( $font_family_name ) ) { - $slug = WP_Fonts_Utils::convert_font_family_into_handle( $font_family_name ); - } - - return $slug; - } - - /** - * Initializes the API. - * - * @since 6.0.0 - * @deprecated GB 14.9.1 Use wp_fonts(). - */ - public static function init() { - _deprecated_function( __METHOD__, 'GB 14.9.1', 'wp_fonts()' ); - } - - /** - * Get the list of all registered font family handles. - * - * @since X.X.X - * @deprecated GB 15.8.0 Use wp_fonts()->get_registered_font_families(). - * - * @return string[] - */ - public function get_registered_font_families() { - _deprecated_function( __METHOD__, 'GB 15.8.0', 'wp_fonts()->get_registered_font_families()' ); - - return $this->wp_fonts->get_registered_font_families(); - } - - /** - * Gets the list of registered fonts. - * - * @since 6.0.0 - * @deprecated 14.9.1 Use wp_fonts()->get_registered(). - * - * @return array[] - */ - public function get_registered_webfonts() { - _deprecated_function( __METHOD__, '14.9.1', 'wp_fonts()->get_registered()' ); - - return $this->_get_registered_webfonts(); - } - - /** - * Gets the list of enqueued fonts. - * - * @since 6.0.0 - * @deprecated GB 14.9.1 Use wp_fonts()->get_enqueued(). - * - * @return array[] - */ - public function get_enqueued_webfonts() { - _deprecated_function( __METHOD__, 'GB 14.9.1', 'wp_fonts()->get_enqueued()' ); - - return $this->wp_fonts->queue; - } - - /** - * Gets the list of all fonts. - * - * @since 6.0.0 - * @deprecated GB 14.9.1 Use wp_fonts()->get_registered(). - * - * @return array[] - */ - public function get_all_webfonts() { - _deprecated_function( __METHOD__, 'GB 14.9.1', 'wp_fonts()->get_registered()' ); - - return $this->_get_registered_webfonts(); - } - - /** - * Registers a webfont. - * - * @since 6.0.0 - * @deprecated GB 14.9.1 Use wp_register_fonts(). - * - * @param array $webfont Web font to register. - * @param string $font_family_handle Optional. Font family handle for the given variation. - * Default empty string. - * @param string $variation_handle Optional. Handle for the variation to register. - * @param bool $silence_deprecation Optional. Silences the deprecation notice. For internal use. - * @return string|false The font family slug if successfully registered, else false. - */ - public function register_webfont( array $webfont, $font_family_handle = '', $variation_handle = '', $silence_deprecation = false ) { - if ( ! $silence_deprecation ) { - _deprecated_function( __METHOD__, 'GB 14.9.1', 'wp_register_fonts()' ); - } - - // Bail out if no variation passed as there's not to register. - if ( empty( $webfont ) ) { - return false; - } - - // Restructure definition: keyed by font-family and array of variations. - $font = array( $webfont ); - if ( WP_Fonts_Utils::is_defined( $font_family_handle ) ) { - $font = array( $font_family_handle => $font ); - } else { - $font = Gutenberg_Fonts_API_BC_Layer::migrate_deprecated_structure( $font, true ); - $font_family_handle = array_key_first( $font ); - } - - if ( empty( $font ) || empty( $font_family_handle ) ) { - return false; - } - - // If the variation handle was passed, add it as variation key. - if ( WP_Fonts_Utils::is_defined( $variation_handle ) ) { - $font[ $font_family_handle ] = array( $variation_handle => $font[ $font_family_handle ][0] ); - } - - // Register with the Fonts API. - $handle = wp_register_fonts( $font ); - if ( empty( $handle ) ) { - return false; - } - return array_pop( $handle ); - } - - /** - * Enqueue a font-family that has been already registered. - * - * @since 6.0.0 - * @deprecated GB 14.9.1 Use wp_enqueue_fonts(). - * - * @param string $font_family_name The font family name to be enqueued. - * @return bool True if successfully enqueued, else false. - */ - public function enqueue_webfont( $font_family_name ) { - _deprecated_function( __METHOD__, 'GB 14.9.1', 'wp_enqueue_fonts()' ); - - wp_enqueue_fonts( array( $font_family_name ) ); - return true; - } - - /** - * Gets the registered webfonts in the original web font property structure keyed by each handle. - * - * @return array[] - */ - private function _get_registered_webfonts() { - $font_families = array(); - $registered = array(); - - // Find the registered font families. - foreach ( $this->wp_fonts->registered as $handle => $obj ) { - if ( ! $obj->extra['is_font_family'] ) { - continue; - } - - if ( ! isset( $registered[ $handle ] ) ) { - $registered[ $handle ] = array(); - } - - $font_families[ $handle ] = $obj->deps; - } - - // Build the return array structure. - foreach ( $font_families as $font_family_handle => $variations ) { - foreach ( $variations as $variation_handle ) { - $variation_obj = $this->wp_fonts->registered[ $variation_handle ]; - - $registered[ $font_family_handle ][ $variation_handle ] = $variation_obj->extra['font-properties']; - } - } - - return $registered; - } -} diff --git a/lib/experimental/fonts-api/bc-layer/webfonts-deprecations.php b/lib/experimental/fonts-api/bc-layer/webfonts-deprecations.php deleted file mode 100644 index 7a3a7bd013eea..0000000000000 --- a/lib/experimental/fonts-api/bc-layer/webfonts-deprecations.php +++ /dev/null @@ -1,260 +0,0 @@ - array[] $variations { - * An array of web font variations for this font-family. - * Each variation has the following structure. - * - * @type array $variation { - * @type string $provider The provider ID. Default 'local'. - * @type string $font-style The font-style property. Default 'normal'. - * @type string $font-weight The font-weight property. Default '400'. - * @type string $font-display The font-display property. Default 'fallback'. - * } - * } - * } - * @return string[] Array of registered font family handles. - */ - function wp_register_webfonts( array $webfonts ) { - _deprecated_function( __FUNCTION__, 'GB 15.1', 'wp_register_fonts()' ); - - $webfonts = Gutenberg_Fonts_API_BC_Layer::migrate_deprecated_structure( $webfonts ); - - return wp_register_fonts( $webfonts ); - } -} - -if ( ! function_exists( 'wp_register_webfont' ) ) { - /** - * Registers a single webfont. - * - * Example of how to register Source Serif Pro font with font-weight range of 200-900: - * - * If the font file is contained within the theme: - * - * - * wp_register_webfont( - * array( - * 'provider' => 'local', - * 'font-family' => 'Source Serif Pro', - * 'font-weight' => '200 900', - * 'font-style' => 'normal', - * 'src' => get_theme_file_uri( 'assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2' ), - * ) - * ); - * - * - * @since 6.0.0 - * @deprecated 14.9.1 Use wp_register_fonts(). - * - * @param array $webfont Webfont to be registered. - * @return string|false The font family slug if successfully registered, else false. - */ - function wp_register_webfont( array $webfont ) { - _deprecated_function( __FUNCTION__, '14.9.1', 'wp_register_fonts()' ); - - return wp_fonts()->register_webfont( $webfont, '', '', false ); - } -} - -if ( ! function_exists( 'wp_enqueue_webfonts' ) ) { - /** - * Enqueues one or more font family and all of its variations. - * - * @since X.X.X - * @since GB 15.1 Use wp_enqueue_fonts() ihstead. - * - * @param string[] $font_families Font family(ies) to enqueue. - */ - function wp_enqueue_webfonts( array $font_families ) { - _deprecated_function( __FUNCTION__, 'GB 15.1', 'wp_enqueue_fonts()' ); - - wp_enqueue_fonts( $font_families ); - } -} - -if ( ! function_exists( 'wp_enqueue_webfont' ) ) { - /** - * Enqueue a single font family that has been registered beforehand. - * - * Example of how to enqueue Source Serif Pro font: - * - * - * wp_enqueue_webfont( 'Source Serif Pro' ); - * - * - * Font families should be enqueued from the `init` hook or later. - * - * @since 6.0.0 - * @deprecated GB 14.9.1 Use wp_enqueue_fonts() instead. - * - * @param string $font_family_name The font family name to be enqueued. - * @return bool True if successfully enqueued, else false. - */ - function wp_enqueue_webfont( $font_family_name ) { - _deprecated_function( __FUNCTION__, 'GB 14.9.1', 'wp_enqueue_fonts()' ); - - wp_enqueue_fonts( array( $font_family_name ) ); - return true; - } -} - -if ( ! function_exists( 'wp_enqueue_webfont_variations' ) ) { - /** - * Enqueues a specific set of web font variations. - * - * @since X.X.X - * @deprecated GB 15.1 Use wp_enqueue_font_variations() instead. - * - * @param string|string[] $variation_handles Variation handle (string) or handles (array of strings). - */ - function wp_enqueue_webfont_variations( $variation_handles ) { - _deprecated_function( __FUNCTION__, 'GB 15.1', 'wp_enqueue_font_variations()' ); - - wp_enqueue_font_variations( $variation_handles ); - } -} - -if ( ! function_exists( 'wp_deregister_webfont_variation' ) ) { - /** - * Deregisters a font variation. - * - * @since GB 14.9.1 - * @deprecated GB 15.1 Use wp_deregister_font_variation() instead. - * - * @param string $font_family_handle The font family for this variation. - * @param string $variation_handle The variation's handle to remove. - */ - function wp_deregister_webfont_variation( $font_family_handle, $variation_handle ) { - _deprecated_function( __FUNCTION__, 'GB 15.1', 'wp_deregister_font_variation()' ); - - wp_deregister_font_variation( $font_family_handle, $variation_handle ); - } -} - -if ( ! function_exists( 'wp_get_webfont_providers' ) ) { - /** - * Gets all registered providers. - * - * Return an array of providers, each keyed by their unique - * ID (i.e. the `$id` property in the provider's object) with - * an instance of the provider (object): - * ID => provider instance - * - * Each provider contains the business logic for how to - * process its specific font service (i.e. local or remote) - * and how to generate the `@font-face` styles for its service. - * - * @since X.X.X - * @deprecated GB 14.9.1 Use wp_fonts()->get_providers(). - * - * @return string[] All registered providers, each keyed by their unique ID. - */ - function wp_get_webfont_providers() { - _deprecated_function( __FUNCTION__, '14.9.1', 'wp_fonts()->get_providers()' ); - - $providers = array(); - foreach ( wp_fonts()->get_providers() as $id => $config ) { - $providers[ $id ] = $config['class']; - } - - return $providers; - } -} - -if ( ! function_exists( 'wp_register_webfont_provider' ) ) { - /** - * Registers a custom font service provider. - * - * A webfont provider contains the business logic for how to - * interact with a remote font service and how to generate - * the `@font-face` styles for that remote service. - * - * How to register a custom font service provider: - * 1. Load its class file into memory before registration. - * 2. Pass the class' name to this function. - * - * For example, for a class named `My_Custom_Font_Service_Provider`: - * ``` - * wp_register_webfont_provider( My_Custom_Font_Service_Provider::class ); - * ``` - * - * @since X.X.X - * @deprecated GB 15.1 Use wp_register_font_provider() instead. - * - * @param string $name The provider's name. - * @param string $classname The provider's class name. - * The class should be a child of `WP_Webfonts_Provider`. - * See {@see WP_Webfonts_Provider}. - * - * @return bool True if successfully registered, else false. - */ - function wp_register_webfont_provider( $name, $classname ) { - _deprecated_function( __FUNCTION__, 'GB 15.1', 'wp_register_font_provider' ); - - return wp_register_font_provider( $name, $classname ); - } -} - -if ( ! function_exists( 'wp_print_webfonts' ) ) { - /** - * Invokes each provider to process and print its styles. - * - * @since GB 14.9.1 - * @deprecated GB 15.1 Use wp_print_fonts() instead. - * - * @param string|string[]|false $handles Optional. Items to be processed: queue (false), - * single item (string), or multiple items (array of strings). - * Default false. - * @return array|string[] Array of web font handles that have been processed. - * An empty array if none were processed. - */ - function wp_print_webfonts( $handles = false ) { - _deprecated_function( __FUNCTION__, 'GB 15.1', 'wp_print_fonts' ); - - return wp_print_fonts( $handles ); - } -} diff --git a/lib/experimental/fonts-api/class-wp-fonts-provider-local.php b/lib/experimental/fonts-api/class-wp-fonts-provider-local.php deleted file mode 100644 index 019861a9ae191..0000000000000 --- a/lib/experimental/fonts-api/class-wp-fonts-provider-local.php +++ /dev/null @@ -1,236 +0,0 @@ -style_tag_atts = array( 'type' => 'text/css' ); - } - } - - /** - * Gets the `@font-face` CSS styles for locally-hosted font files. - * - * This method does the following processing tasks: - * 1. Orchestrates an optimized `src` (with format) for browser support. - * 2. Generates the `@font-face` for all its fonts. - * - * @since X.X.X - * - * @return string The `@font-face` CSS. - */ - public function get_css() { - $css = ''; - - foreach ( $this->fonts as $font ) { - // Order the font's `src` items to optimize for browser support. - $font = $this->order_src( $font ); - - // Build the @font-face CSS for this font. - $css .= '@font-face{' . $this->build_font_face_css( $font ) . '}'; - } - - return $css; - } - - /** - * Order `src` items to optimize for browser support. - * - * @since X.X.X - * - * @param array $font Font to process. - * @return array - */ - private function order_src( array $font ) { - if ( ! is_array( $font['src'] ) ) { - $font['src'] = (array) $font['src']; - } - - $src = array(); - $src_ordered = array(); - - foreach ( $font['src'] as $url ) { - // Add data URIs first. - if ( str_starts_with( trim( $url ), 'data:' ) ) { - $src_ordered[] = array( - 'url' => $url, - 'format' => 'data', - ); - continue; - } - $format = pathinfo( $url, PATHINFO_EXTENSION ); - $src[ $format ] = $url; - } - - // Add woff2. - if ( ! empty( $src['woff2'] ) ) { - $src_ordered[] = array( - 'url' => $src['woff2'], - 'format' => 'woff2', - ); - } - - // Add woff. - if ( ! empty( $src['woff'] ) ) { - $src_ordered[] = array( - 'url' => $src['woff'], - 'format' => 'woff', - ); - } - - // Add ttf. - if ( ! empty( $src['ttf'] ) ) { - $src_ordered[] = array( - 'url' => $src['ttf'], - 'format' => 'truetype', - ); - } - - // Add eot. - if ( ! empty( $src['eot'] ) ) { - $src_ordered[] = array( - 'url' => $src['eot'], - 'format' => 'embedded-opentype', - ); - } - - // Add otf. - if ( ! empty( $src['otf'] ) ) { - $src_ordered[] = array( - 'url' => $src['otf'], - 'format' => 'opentype', - ); - } - $font['src'] = $src_ordered; - - return $font; - } - - /** - * Builds the font-family's CSS. - * - * @since X.X.X - * - * @param array $font Font to process. - * @return string This font-family's CSS. - */ - private function build_font_face_css( array $font ) { - $css = ''; - - // Wrap font-family in quotes if it contains spaces - // and is not already wrapped in quotes. - if ( - str_contains( $font['font-family'], ' ' ) && - ! str_contains( $font['font-family'], '"' ) && - ! str_contains( $font['font-family'], "'" ) - ) { - $font['font-family'] = '"' . $font['font-family'] . '"'; - } - - foreach ( $font as $key => $value ) { - - // Skip "provider", since it's for internal API use, - // and not a valid CSS property. - if ( 'provider' === $key ) { - continue; - } - - // Compile the "src" parameter. - if ( 'src' === $key ) { - $value = $this->compile_src( $value ); - } - - // If font-variation-settings is an array, convert it to a string. - if ( 'font-variation-settings' === $key && is_array( $value ) ) { - $value = $this->compile_variations( $value ); - } - - if ( ! empty( $value ) ) { - $css .= "$key:$value;"; - } - } - - return $css; - } - - /** - * Compiles the `src` into valid CSS. - * - * @since X.X.X - * - * @param array $value Value to process. - * @return string The CSS. - */ - private function compile_src( array $value ) { - $src = ''; - - foreach ( $value as $item ) { - $src .= ( 'data' === $item['format'] ) - ? ", url({$item['url']})" - : ", url('{$item['url']}') format('{$item['format']}')"; - } - - $src = ltrim( $src, ', ' ); - return $src; - } - - /** - * Compiles the font variation settings. - * - * @since X.X.X - * - * @param array $font_variation_settings Array of font variation settings. - * @return string The CSS. - */ - private function compile_variations( array $font_variation_settings ) { - $variations = ''; - - foreach ( $font_variation_settings as $key => $value ) { - $variations .= "$key $value"; - } - - return $variations; - } -} diff --git a/lib/experimental/fonts-api/class-wp-fonts-provider.php b/lib/experimental/fonts-api/class-wp-fonts-provider.php deleted file mode 100644 index b59c59d6b8938..0000000000000 --- a/lib/experimental/fonts-api/class-wp-fonts-provider.php +++ /dev/null @@ -1,129 +0,0 @@ -fonts = $fonts; - } - - /** - * Prints the generated styles. - * - * @since X.X.X - */ - public function print_styles() { - printf( - $this->get_style_element(), - $this->get_css() - ); - } - - /** - * Gets the `@font-face` CSS for the provider's fonts. - * - * This method is where the provider does it processing to build the - * needed `@font-face` CSS for all of its fonts. Specifics of how - * this processing is done is contained in each provider. - * - * @since X.X.X - * - * @return string The `@font-face` CSS. - */ - abstract public function get_css(); - - /** - * Gets the `\n"; - } - - /** - * Gets the defined \n", - $font_faces['merriweather-200-900-normal'] - ), - ), - 'print Source Serif Pro for local provider' => array( - 'setup' => array( - 'provider' => array( 'local' => $providers['local'] ), - 'provider_handles' => array( 'local' => $local_font_handles ), - 'registered' => $local_fonts, - 'enqueued' => array( 'source-serif-pro' ), - ), - 'expected_done' => array( 'source-serif-pro', 'Source Serif Pro-300-normal', 'Source Serif Pro-900-italic' ), - 'expected_output' => sprintf( - "\n", - $font_faces['Source Serif Pro-300-normal'], - $font_faces['Source Serif Pro-900-italic'] - ), - ), - 'print all fonts for local provider' => array( - 'setup' => array( - 'provider' => array( 'local' => $providers['local'] ), - 'provider_handles' => array( 'local' => $local_font_handles ), - 'registered' => $local_fonts, - 'enqueued' => array( 'merriweather', 'source-serif-pro' ), - ), - 'expected_done' => array( - 'merriweather', - 'merriweather-200-900-normal', - 'source-serif-pro', - 'Source Serif Pro-300-normal', - 'Source Serif Pro-900-italic', - ), - 'expected_output' => sprintf( - "\n", - $font_faces['merriweather-200-900-normal'], - $font_faces['Source Serif Pro-300-normal'], - $font_faces['Source Serif Pro-900-italic'] - ), - ), - - // All providers registered with multiple fonts. - - 'print font1 when all providers registered' => array( - 'setup' => array_merge( $setup_all, array( 'enqueued' => array( 'font1' ) ) ), - 'expected_done' => array( 'font1', 'font1-300-normal', 'font1-300-italic', 'font1-900-normal' ), - 'expected_output' => sprintf( - '%s; %s; %s\n', - $font_faces['font1-300-normal'], - $font_faces['font1-300-italic'], - $font_faces['font1-900-normal'] - ), - ), - 'print all mock fonts when all providers registered' => array( - 'setup' => array_merge( $setup_all, array( 'enqueued' => array( 'font1', 'font2', 'font3' ) ) ), - 'expected_done' => array( - 'font1', - 'font1-300-normal', - 'font1-300-italic', - 'font1-900-normal', - 'font2', - 'font2-200-900-normal', - 'font2-200-900-italic', - 'font3', - 'font3-bold-normal', - ), - 'expected_output' => sprintf( - '%s; %s; %s; %s; %s; %s\n', - $font_faces['font1-300-normal'], - $font_faces['font1-300-italic'], - $font_faces['font1-900-normal'], - $font_faces['font2-200-900-normal'], - $font_faces['font2-200-900-italic'], - $font_faces['font3-bold-normal'] - ), - ), - 'print merriweather when all providers registered' => array( - 'setup' => array_merge( $setup_all, array( 'enqueued' => array( 'merriweather' ) ) ), - 'expected_done' => array( 'merriweather', 'merriweather-200-900-normal' ), - 'expected_output' => sprintf( - "\n", - $font_faces['merriweather-200-900-normal'] - ), - ), - 'print all local fonts when all providers registered' => array( - 'setup' => array_merge( $setup_all, array( 'enqueued' => array( 'merriweather', 'source-serif-pro' ) ) ), - 'expected_done' => array( - 'merriweather', - 'merriweather-200-900-normal', - 'source-serif-pro', - 'Source Serif Pro-300-normal', - 'Source Serif Pro-900-italic', - ), - 'expected_output' => sprintf( - "\n", - $font_faces['merriweather-200-900-normal'], - $font_faces['Source Serif Pro-300-normal'], - $font_faces['Source Serif Pro-900-italic'] - ), - ), - - 'print all fonts for all providers' => array( - 'setup' => array_merge( $setup_all, array( 'enqueued' => $all_variation_handles ) ), - 'expected_done' => $all_variation_handles, - 'expected_output' => - sprintf( - "\n", - $font_faces['merriweather-200-900-normal'], - $font_faces['Source Serif Pro-300-normal'], - $font_faces['Source Serif Pro-900-italic'] - ) . - sprintf( - '%s; %s; %s; %s; %s; %s\n', - $font_faces['font1-300-normal'], - $font_faces['font1-300-italic'], - $font_faces['font1-900-normal'], - $font_faces['font2-200-900-normal'], - $font_faces['font2-200-900-italic'], - $font_faces['font3-bold-normal'] - ), - ), - - // Specific variations enqueued. - // Validates that only these specific variations print once. - - 'specific variation: 1 local' => array( - 'setup' => array_merge( $setup_all, array( 'enqueued' => array( 'merriweather-200-900-normal' ) ) ), - 'expected_done' => array( 'merriweather-200-900-normal' ), - 'expected_output' => sprintf( - "\n", - $font_faces['merriweather-200-900-normal'] - ), - ), - 'specific variation: 1 local from different font families' => array( - 'setup' => array_merge( $setup_all, array( 'enqueued' => array( 'merriweather-200-900-normal', 'Source Serif Pro-900-italic' ) ) ), - 'expected_done' => array( 'merriweather-200-900-normal', 'Source Serif Pro-900-italic' ), - 'expected_output' => sprintf( - "\n", - $font_faces['merriweather-200-900-normal'], - $font_faces['Source Serif Pro-900-italic'] - ), - ), - 'specific variation: 1 local and 1 mock' => array( - 'setup' => array_merge( $setup_all, array( 'enqueued' => array( 'merriweather-200-900-normal', 'font2-200-900-normal' ) ) ), - 'expected_done' => array( 'merriweather-200-900-normal', 'font2-200-900-normal' ), - 'expected_output' => sprintf( - "\n" . - '%s\n', - $font_faces['merriweather-200-900-normal'], - $font_faces['font2-200-900-normal'] - ), - ), - 'specific variation: 1 mock and 1 local' => array( - 'setup' => array_merge( $setup_all, array( 'enqueued' => array( 'font2-200-900-normal', 'Source Serif Pro-300-normal' ) ) ), - 'expected_done' => array( 'font2-200-900-normal', 'Source Serif Pro-300-normal' ), - 'expected_output' => sprintf( - "\n" . - '%s\n', - $font_faces['Source Serif Pro-300-normal'], - $font_faces['font2-200-900-normal'] - ), - ), - ); - } - - protected function get_data_registry() { - return array( - 'lato' => array(), - 'merriweather' => array( - 'merriweather-200-900-normal' => array( - 'font-family' => 'Merriweather', - 'font-weight' => '200 900', - 'font-stretch' => 'normal', - 'src' => 'https://example.com/assets/fonts/merriweather.ttf.woff2', - ), - ), - 'Source Serif Pro' => array( - 'Source Serif Pro-300-normal' => array( - 'provider' => 'local', - 'font-family' => 'Source Serif Pro', - 'font-style' => 'normal', - 'font-weight' => '300', - 'font-stretch' => 'normal', - 'src' => 'https://example.com/assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2', - 'font-display' => 'fallback', - ), - 'Source Serif Pro-900-italic' => array( - 'provider' => 'local', - 'font-family' => 'Source Serif Pro', - 'font-style' => 'italic', - 'font-weight' => '900', - 'font-stretch' => 'normal', - 'src' => 'https://example.com/assets/fonts/source-serif-pro/SourceSerif4Variable-Italic.ttf.woff2', - 'font-display' => 'fallback', - ), - ), - 'my-font' => array( - 'my-font-300-normal' => array( - 'font-family' => 'My Font', - 'font-weight' => '300', - 'src' => 'https://example.com/assets/fonts/my-font.ttf.woff2', - ), - 'my-font-300-italic' => array( - 'font-family' => 'My Font', - 'font-weight' => '300', - 'font-style' => 'italic', - 'src' => 'https://example.com/assets/fonts/my-font.ttf.woff2', - ), - 'my-font-900-normal' => array( - 'font-family' => 'My Font', - 'font-weight' => '900', - 'src' => 'https://example.com/assets/fonts/my-font.ttf.woff2', - ), - ), - ); - } - - /** - * Gets the provider definitions. - * - * @since X.X.X - * - * @param string $provider_id Optional. Provider ID to get. Default empty string. - * @return array - */ - protected function get_provider_definitions( $provider_id = '' ) { - $providers = array( - 'mock' => array( - 'id' => 'mock', - 'class' => Mock_Provider::class, - ), - 'local' => array( - 'id' => 'local', - 'class' => WP_Fonts_Provider_Local::class, - ), - ); - - if ( '' === $provider_id ) { - return $providers; - } - - if ( isset( $providers[ $provider_id ] ) ) { - return $providers[ $provider_id ]; - } - - return array( - 'id' => $provider_id, - 'class' => '', - ); - } - - /** - * Gets font definitions for both local and mock providers. - * - * @since X.X.X - * - * @return array|string[][][] - */ - protected function get_registered_fonts() { - return array_merge( - $this->get_registered_local_fonts(), - $this->get_registered_mock_fonts() - ); - } - - /** - * Returns an array of font-face styles that matches the font definitions - * in get_registered_local_fonts() and get_registered_mock_fonts(). - * - * @since X.X.X - * - * @return string[] - */ - protected function get_registered_fonts_css() { - return array( - 'merriweather-200-900-normal' => << << << 'font1-300-normal', - 'font1-300-italic' => 'font1-300-italic', - 'font1-900-normal' => 'font1-900-normal', - 'font2-200-900-normal' => 'font2-200-900-normal', - 'font2-200-900-italic' => 'font2-200-900-italic', - 'font3-bold-normal' => 'font3-bold-normal', - ); - } - - /** - * Gets font definitions for local provider. - * - * @since X.X.X - * - * @return string[][][] - */ - protected function get_registered_local_fonts() { - return array( - 'lato' => array(), - 'merriweather' => array( - 'merriweather-200-900-normal' => array( - 'provider' => 'local', - 'font-family' => 'Merriweather', - 'font-style' => 'normal', - 'font-weight' => '200 900', - 'font-display' => 'fallback', - 'font-stretch' => 'normal', - 'src' => 'https://example.com/assets/fonts/merriweather.ttf.woff2', - ), - ), - 'Source Serif Pro' => array( - 'Source Serif Pro-300-normal' => array( - 'provider' => 'local', - 'font-family' => 'Source Serif Pro', - 'font-style' => 'normal', - 'font-weight' => '300', - 'font-display' => 'fallback', - 'font-stretch' => 'normal', - 'src' => 'https://example.com/assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2', - 'font-display' => 'fallback', - ), - 'Source Serif Pro-900-italic' => array( - 'provider' => 'local', - 'font-family' => 'Source Serif Pro', - 'font-style' => 'italic', - 'font-weight' => '900', - 'font-display' => 'fallback', - 'font-stretch' => 'normal', - 'src' => 'https://example.com/assets/fonts/source-serif-pro/SourceSerif4Variable-Italic.ttf.woff2', - 'font-display' => 'fallback', - ), - ), - ); - } - - /** - * Gets font definitions for mock provider. - * - * @since X.X.X - * - * @return string[][][] - */ - protected function get_registered_mock_fonts() { - return array( - 'font1' => array( - 'font1-300-normal' => array( - 'provider' => 'mock', - 'font-family' => 'Font 1', - 'font-weight' => '300', - 'font-style' => 'normal', - 'font-display' => 'fallback', - ), - 'font1-300-italic' => array( - 'provider' => 'mock', - 'font-family' => 'Font 1', - 'font-weight' => '300', - 'font-style' => 'italic', - 'font-display' => 'fallback', - ), - 'font1-900-normal' => array( - 'provider' => 'mock', - 'font-family' => 'Font 1', - 'font-weight' => '900', - 'font-style' => 'normal', - 'font-display' => 'fallback', - ), - ), - 'font2' => array( - 'font2-200-900-normal' => array( - 'provider' => 'mock', - 'font-family' => 'Font 2', - 'font-weight' => '200 900', - 'font-style' => 'normal', - 'font-display' => 'fallback', - ), - 'font2-200-900-italic' => array( - 'provider' => 'mock', - 'font-family' => 'Font 2', - 'font-weight' => '200 900', - 'font-style' => 'italic', - 'font-display' => 'fallback', - ), - ), - 'font3' => array( - 'font3-bold-normal' => array( - 'provider' => 'mock', - 'font-family' => 'Font 3', - 'font-weight' => 'bold', - 'font-style' => 'normal', - 'font-display' => 'fallback', - 'font-stretch' => 'normal', - ), - ), - ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_print_user_selected_fonts() { - $global_styles = $this->get_mock_user_selected_fonts_global_styles(); - $font_faces = $this->get_registered_fonts_css(); - - return array( - 'print font1' => array( - 'global_styles' => $global_styles['font1'], - 'expected_done' => array( - 'font1-300-normal', - 'font1-300-italic', - 'font1-900-normal', - 'font1', - ), - 'expected_output' => sprintf( - '%s; %s; %s\n', - $font_faces['font1-300-normal'], - $font_faces['font1-300-italic'], - $font_faces['font1-900-normal'] - ), - ), - 'print font2' => array( - 'global_styles' => $global_styles['font2'], - 'expected_done' => array( 'font2-200-900-normal', 'font2-200-900-italic', 'font2' ), - 'expected_output' => sprintf( - '%s; %s\n', - $font_faces['font2-200-900-normal'], - $font_faces['font2-200-900-italic'] - ), - ), - 'print font3' => array( - 'global_styles' => $global_styles['font3'], - 'expected_done' => array( 'font3', 'font3-bold-normal' ), - 'expected_output' => sprintf( - '%s\n', - $font_faces['font3-bold-normal'] - ), - ), - 'print all fonts' => array( - 'global_styles' => $global_styles['all'], - 'expected_done' => array( - 'font1-300-normal', - 'font1-300-italic', - 'font1-900-normal', - 'font1', - 'font2-200-900-normal', - 'font2-200-900-italic', - 'font2', - 'font3-bold-normal', - 'font3', - ), - 'expected_output' => sprintf( - '%s; %s; %s; %s; %s; %s\n', - $font_faces['font1-300-normal'], - $font_faces['font1-300-italic'], - $font_faces['font1-900-normal'], - $font_faces['font2-200-900-normal'], - $font_faces['font2-200-900-italic'], - $font_faces['font3-bold-normal'] - ), - ), - 'print all valid fonts' => array( - 'global_styles' => $global_styles['all with invalid element'], - 'expected_done' => array( - 'font1-300-normal', - 'font1-300-italic', - 'font1-900-normal', - 'font1', - 'font2-200-900-normal', - 'font2-200-900-italic', - 'font2', - 'font3-bold-normal', - 'font3', - ), - 'expected_output' => sprintf( - '%s; %s; %s; %s; %s; %s\n', - $font_faces['font1-300-normal'], - $font_faces['font1-300-italic'], - $font_faces['font1-900-normal'], - $font_faces['font2-200-900-normal'], - $font_faces['font2-200-900-italic'], - $font_faces['font3-bold-normal'] - ), - ), - ); - } - - /** - * Gets user-selected fonts for global styles for the mock provider. - * - * @since X.X.X - * - * @return array - */ - protected function get_mock_user_selected_fonts_global_styles() { - return array( - 'font1' => array( - 'elements' => array( - 'heading' => array( - 'typography' => array( - 'fontFamily' => 'var:preset|font-family|font1', - 'fontStyle' => 'normal', - 'fontWeight' => '300', - ), - ), - 'caption' => array( - 'typography' => array( - 'fontFamily' => 'var:preset|font-family|font1', - 'fontStyle' => 'italic', - 'fontWeight' => '300', - ), - ), - ), - 'typography' => array( - 'fontFamily' => 'var:preset|font-family|font1', - 'fontStyle' => 'normal', - 'fontWeight' => '900', - ), - ), - 'font2' => array( - 'elements' => array( - 'heading' => array( - 'typography' => array( - 'fontFamily' => 'var:preset|font-family|font2', - 'fontStyle' => 'normal', - 'fontWeight' => '200-900', - ), - ), - 'button' => array( - 'typography' => array( - 'fontFamily' => 'var:preset|font-family|font2', - 'fontStyle' => 'italic', - 'fontWeight' => '200-900', - ), - ), - ), - ), - 'font3' => array( - 'typography' => array( - 'fontFamily' => 'var:preset|font-family|font3', - 'fontStyle' => 'normal', - 'fontWeight' => 'bold', - ), - ), - 'all' => array( - 'elements' => array( - 'link' => array( - 'typography' => array( - 'fontFamily' => 'var:preset|font-family|font1', - 'fontStyle' => 'italic', - 'fontWeight' => '300', - ), - ), - 'heading' => array( - 'typography' => array( - 'fontFamily' => 'var:preset|font-family|font1', - 'fontStyle' => 'normal', - 'fontWeight' => '900', - ), - ), - 'caption' => array( - 'typography' => array( - 'fontFamily' => 'var:preset|font-family|font1', - 'fontStyle' => 'italic', - 'fontWeight' => '300', - ), - ), - 'button' => array( - 'typography' => array( - 'fontFamily' => 'var:preset|font-family|font2', - 'fontStyle' => 'normal', - 'fontWeight' => '200-900', - ), - ), - ), - 'typography' => array( - 'fontFamily' => 'var:preset|font-family|font3', - 'fontStyle' => 'normal', - 'fontWeight' => 'bold', - ), - ), - 'all with invalid element' => array( - 'elements' => array( - 'link' => array( - 'typography' => array( - 'fontFamily' => 'var:preset|font-family|font1', - 'fontStyle' => 'italic', - 'fontWeight' => '300', - ), - ), - 'heading' => array( - 'typography' => array( - 'fontFamily' => 'var:preset|font-family|font1', - 'fontStyle' => 'normal', - 'fontWeight' => '900', - ), - ), - 'caption' => array( - 'typography' => array( - 'fontFamily' => 'var:preset|font-family|font1', - 'fontStyle' => 'italic', - 'fontWeight' => '300', - ), - ), - 'button' => array( - 'typography' => array( - 'fontFamily' => 'var:preset|font-family|font2', - 'fontStyle' => 'normal', - 'fontWeight' => '200-900', - ), - ), - 'invalid' => array( - 'typography' => array( - 'fontFamily' => 'var:preset|font-family|font2', - 'fontStyle' => 'italic', - 'fontWeight' => '200-900', - ), - ), - ), - 'typography' => array( - 'fontFamily' => 'var:preset|font-family|font3', - 'fontStyle' => 'normal', - 'fontWeight' => 'bold', - ), - ), - ); - } -} diff --git a/phpunit/tests/fonts-api/wpDeregisterFontFamily.php b/phpunit/tests/fonts-api/wpDeregisterFontFamily.php deleted file mode 100644 index 59db2e2abc826..0000000000000 --- a/phpunit/tests/fonts-api/wpDeregisterFontFamily.php +++ /dev/null @@ -1,74 +0,0 @@ -set_up_mock( 'remove_font_family' ); - $mock->expects( $this->once() ) - ->method( 'remove_font_family' ) - ->with( - $this->identicalTo( $font_family_handle ) - ); - - wp_deregister_font_family( $font_family_handle ); - } - - /** - * Integration test for enqueuing before registering a font family and all of its variations. - * - * @dataProvider data_font_family_handles - * - * @param string $font_family Font family to test. - */ - public function test_should_deregister_before_registration( $font_family ) { - wp_deregister_font_family( $font_family ); - - $this->assertIsArray( $this->get_registered(), 'Registration queue should be an array' ); - $this->assertEmpty( $this->get_registered(), 'Registration queue should be empty after deregistering' ); - } - - /** - * Integration test for deregistering a font family and all of its variations. - * - * @dataProvider data_one_to_many_font_families_and_zero_to_many_variations - * - * @param string $font_family Font family to test. - * @param array $inputs Font family(ies) and variations to pre-register. - * @param array $registered_handles Expected handles after registering. - * @param array $expected Array of expected handles. - */ - public function test_deregister_after_registration( $font_family, array $inputs, array $registered_handles, array $expected ) { - foreach ( $inputs as $handle => $variations ) { - $this->setup_register( $handle, $variations ); - } - // Test the before state, just to make sure. - $this->assertSame( $registered_handles, $this->get_registered_handles(), 'Font family and variations should be registered before deregistering' ); - - wp_deregister_font_family( $font_family ); - - // Test after deregistering. - $this->assertIsArray( $this->get_registered_handles(), 'Registration queue should be an array' ); - $this->assertSame( $expected, $this->get_registered_handles(), 'Registration queue should match after deregistering' ); - } -} diff --git a/phpunit/tests/fonts-api/wpDeregisterFontVariation.php b/phpunit/tests/fonts-api/wpDeregisterFontVariation.php deleted file mode 100644 index 78b4bf51f758a..0000000000000 --- a/phpunit/tests/fonts-api/wpDeregisterFontVariation.php +++ /dev/null @@ -1,298 +0,0 @@ -wp_fonts = wp_fonts(); - $this->fonts_to_register = $this->get_registered_local_fonts(); - } - - /** - * Sets up the unit test by mocking the WP_Dependencies object using stdClass and - * registering each font family directly to the WP_Webfonts::$registered property - * and its variations to the mocked $deps property. - */ - private function setup_unit_test() { - $this->setup_registration_mocks( $this->fonts_to_register, $this->wp_fonts ); - } - - /** - * Sets up the integration test by properly registering each font family and its variations - * by using the WP_Webfonts::add() and WP_Webfonts::add_variation() methods. - */ - private function setup_integration_test() { - foreach ( $this->fonts_to_register as $font_family_handle => $variations ) { - $this->setup_register( $font_family_handle, $variations, $this->wp_fonts ); - } - } - - /** - * Testing the test setup to ensure it works. - * - * @dataProvider data_remove_variations - * - * @param string $font_family_handle Font family for the variation. - * @param string $variation_handle Variation handle to remove. - */ - public function test_mocked_setup( $font_family_handle, $variation_handle ) { - $this->setup_unit_test(); - - $this->assertArrayHasKey( $variation_handle, $this->wp_fonts->registered, 'Variation should be in the registered queue before removal' ); - $this->assertContains( $variation_handle, $this->wp_fonts->registered[ $font_family_handle ]->deps, 'Variation should be in its font family deps before removal' ); - } - - /** - * Unit test for deregistering a font-family's variation using mock of WP_Webfonts. - * - * @dataProvider data_remove_variations - * - * @param string $font_family_handle Font family to test. - * @param string $variation_handle Variation's handle to test. - */ - public function test_should_deregister_when_mocked( $font_family_handle, $variation_handle ) { - $mock = $this->set_up_mock( 'remove_variation' ); - $mock->expects( $this->once() ) - ->method( 'remove_variation' ) - ->with( - $this->identicalTo( $font_family_handle, $variation_handle ) - ); - - wp_deregister_font_variation( $font_family_handle, $variation_handle ); - } - - /** - * Unit test. - * - * @dataProvider data_should_do_nothing - * - * @param string $font_family Font family name. - * @param string $font_family_handle Font family handle. - * @param string $variation_handle Variation handle to remove. - */ - public function test_unit_should_do_nothing_when_variation_and_font_family_not_registered( $font_family, $font_family_handle, $variation_handle ) { - // Set up the test. - unset( $this->fonts_to_register[ $font_family ] ); - $this->setup_unit_test(); - $registered_queue = $this->wp_fonts->registered; - - // Run the tests. - wp_deregister_font_variation( $font_family_handle, $variation_handle ); - $this->assertArrayNotHasKey( $font_family_handle, $this->wp_fonts->registered, 'Font family should not be registered' ); - $this->assertArrayNotHasKey( $variation_handle, $this->wp_fonts->registered, 'Variant should not be registered' ); - $this->assertSame( $registered_queue, $this->wp_fonts->registered, 'Registered queue should not have changed' ); - } - - /** - * Integration test. - * - * @dataProvider data_should_do_nothing - * - * @param string $font_family Font family name. - * @param string $font_family_handle Font family handle. - * @param string $variation_handle Variation handle to remove. - */ - public function test_should_do_nothing_when_variation_and_font_family_not_registered( $font_family, $font_family_handle, $variation_handle ) { - // Set up the test. - unset( $this->fonts_to_register[ $font_family ] ); - $this->setup_integration_test(); - $registered_queue = $this->wp_fonts->get_registered(); - - // Run the tests. - wp_deregister_font_variation( $font_family_handle, $variation_handle ); - $this->assertArrayNotHasKey( $font_family_handle, $this->wp_fonts->registered, 'Font family should not be registered' ); - $this->assertArrayNotHasKey( $variation_handle, $this->wp_fonts->registered, 'Variant should not be registered' ); - $this->assertSameSets( $registered_queue, $this->wp_fonts->get_registered(), 'Registered queue should not have changed' ); - } - - /** - * Data provider for testing removal of variations. - * - * @return array - */ - public function data_should_do_nothing() { - return array( - 'Font with 1 variation' => array( - 'font_family' => 'merriweather', - 'font_family_handle' => 'merriweather', - 'variation_handle' => 'merriweather-200-900-normal', - ), - 'Font with multiple variations' => array( - 'font_family' => 'Source Serif Pro', - 'font_family_handle' => 'source-serif-pro', - 'variation_handle' => 'Source Serif Pro-300-normal', - ), - ); - } - - /** - * Unit test. - * - * @dataProvider data_remove_variations - * - * @param string $font_family_handle Font family for the variation. - * @param string $variation_handle Variation handle to remove. - * @param array $expected Expected results. - */ - public function test_unit_should_only_remove_from_font_family_deps_when_variation_not_in_queue( $font_family_handle, $variation_handle, $expected ) { - // Set up the test. - $this->setup_unit_test(); - $this->setup_remove_variation_from_registered( $variation_handle ); - - // Run the tests. - wp_deregister_font_variation( $font_family_handle, $variation_handle ); - $this->assertArrayNotHasKey( $variation_handle, $this->wp_fonts->registered, 'Variant should not be registered' ); - $this->assertNotContains( $variation_handle, $this->wp_fonts->registered[ $font_family_handle ]->deps, 'Variation should not be its font family deps' ); - $this->assertSameSets( $expected['font_family_deps'], array_values( $this->wp_fonts->registered[ $font_family_handle ]->deps ), 'Only the tested variation handle should be removed from font family deps' ); - } - - /** - * Integration test. - * - * @dataProvider data_remove_variations - * - * @param string $font_family_handle Font family for the variation. - * @param string $variation_handle Variation handle to remove. - * @param array $expected Expected results. - */ - public function test_should_only_remove_from_font_family_deps_when_variation_not_in_queue( $font_family_handle, $variation_handle, $expected ) { - // Set up the test. - $this->setup_integration_test(); - $this->setup_remove_variation_from_registered( $variation_handle ); - - // Run the tests. - wp_deregister_font_variation( $font_family_handle, $variation_handle ); - $this->assertArrayNotHasKey( $variation_handle, $this->wp_fonts->registered, 'Variant should not be registered' ); - $this->assertNotContains( $variation_handle, $this->wp_fonts->registered[ $font_family_handle ]->deps, 'Variation should not be its font family deps' ); - $this->assertSameSets( $expected['font_family_deps'], array_values( $this->wp_fonts->registered[ $font_family_handle ]->deps ), 'Only the tested variation handle should be removed from font family deps' ); - } - - /** - * Unit test. - * - * @dataProvider data_remove_variations - * - * @param string $font_family_handle Font family for the variation. - * @param string $variation_handle Variation handle to remove. - * @param array $expected Expected results. - */ - public function test_unit_should_remove_variation_from_registered_queue_though_font_family_not_registered( $font_family_handle, $variation_handle, $expected ) { - // Set up the test. - $this->setup_unit_test(); - $this->setup_remove_from_font_family_deps( $font_family_handle, $variation_handle ); - - $this->assertArrayNotHasKey( $variation_handle, array_flip( $this->wp_fonts->registered[ $font_family_handle ]->deps ), 'Variation should not be in its font family deps before removal' ); - - wp_deregister_font_variation( $font_family_handle, $variation_handle ); - - $this->assertNotContains( $variation_handle, $this->wp_fonts->registered[ $font_family_handle ]->deps, 'Variation should not be its font family deps' ); - $this->assertSameSets( $expected['font_family_deps'], array_values( $this->wp_fonts->registered[ $font_family_handle ]->deps ), 'Only the tested variation handle should be removed from font family deps' ); - } - - /** - * Integration test. - * - * @dataProvider data_remove_variations - * - * @param string $font_family_handle Font family for the variation. - * @param string $variation_handle Variation handle to remove. - * @param array $expected Expected results. - */ - public function test_should_remove_variation_from_registered_queue_though_font_family_not_registered( $font_family_handle, $variation_handle, $expected ) { - // Set up the test. - $this->setup_integration_test(); - $this->setup_remove_from_font_family_deps( $font_family_handle, $variation_handle ); - - $this->assertArrayNotHasKey( $variation_handle, array_flip( $this->wp_fonts->registered[ $font_family_handle ]->deps ), 'Variation should not be in its font family deps before removal' ); - - wp_deregister_font_variation( $font_family_handle, $variation_handle ); - - $this->assertNotContains( $variation_handle, $this->wp_fonts->registered[ $font_family_handle ]->deps, 'Variation should not be its font family deps' ); - $this->assertSameSets( $expected['font_family_deps'], array_values( $this->wp_fonts->registered[ $font_family_handle ]->deps ), 'Only the tested variation handle should be removed from font family deps' ); - } - - /** - * Unit test. - * - * @dataProvider data_remove_variations - * - * @param string $font_family_handle Font family for the variation. - * @param string $variation_handle Variation handle to remove. - * @param array $expected Expected results. - */ - public function test_unit_should_remove_variation_from_queue_and_font_family_deps( $font_family_handle, $variation_handle, $expected ) { - // Set up the test. - $this->setup_unit_test(); - - $this->assertArrayHasKey( $variation_handle, array_flip( $this->wp_fonts->registered[ $font_family_handle ]->deps ), 'Variation should be in its font family deps before removal' ); - - wp_deregister_font_variation( $font_family_handle, $variation_handle ); - - $this->assertArrayNotHasKey( $variation_handle, $this->wp_fonts->registered, 'Variation should be not be in registered queue' ); - $this->assertNotContains( $variation_handle, $this->wp_fonts->registered[ $font_family_handle ]->deps, 'Variation should not be its font family deps' ); - $this->assertSameSets( $expected['font_family_deps'], array_values( $this->wp_fonts->registered[ $font_family_handle ]->deps ), 'Only the tested variation handle should be removed from font family deps' ); - } - - /** - * Integration test. - * - * @dataProvider data_remove_variations - * - * @param string $font_family_handle Font family for the variation. - * @param string $variation_handle Variation handle to remove. - * @param array $expected Expected results. - */ - public function test_should_remove_variation_from_queue_and_font_family_deps( $font_family_handle, $variation_handle, $expected ) { - // Set up the test. - $this->setup_integration_test(); - - $this->assertArrayHasKey( $variation_handle, array_flip( $this->wp_fonts->registered[ $font_family_handle ]->deps ), 'Variation should be in its font family deps before removal' ); - - wp_deregister_font_variation( $font_family_handle, $variation_handle ); - - $this->assertArrayNotHasKey( $variation_handle, $this->wp_fonts->registered, 'Variation should be not be in registered queue' ); - $this->assertNotContains( $variation_handle, $this->wp_fonts->registered[ $font_family_handle ]->deps, 'Variation should not be its font family deps' ); - $this->assertSameSets( $expected['font_family_deps'], array_values( $this->wp_fonts->registered[ $font_family_handle ]->deps ), 'Only the tested variation handle should be removed from font family deps' ); - } - - /** - * Remove the variation handle from the font family's deps. - * - * @param string $font_family_handle Font family. - * @param string $variation_handle The variation handle to remove. - */ - private function setup_remove_from_font_family_deps( $font_family_handle, $variation_handle ) { - foreach ( $this->wp_fonts->registered[ $font_family_handle ]->deps as $index => $vhandle ) { - if ( $variation_handle !== $vhandle ) { - continue; - } - unset( $this->wp_fonts->registered[ $font_family_handle ]->deps[ $index ] ); - break; - } - } - - /** - * Removes the variation from the WP_Webfonts::$registered queue. - * - * @param string $variation_handle The variation handle to remove. - */ - private function setup_remove_variation_from_registered( $variation_handle ) { - unset( $this->wp_fonts->registered[ $variation_handle ] ); - } -} diff --git a/phpunit/tests/fonts-api/wpEnqueueFontVariations.php b/phpunit/tests/fonts-api/wpEnqueueFontVariations.php deleted file mode 100644 index 6e026d99f5889..0000000000000 --- a/phpunit/tests/fonts-api/wpEnqueueFontVariations.php +++ /dev/null @@ -1,82 +0,0 @@ -set_up_mock( 'enqueue' ); - $mock->expects( $this->once() ) - ->method( 'enqueue' ) - ->with( - $this->identicalTo( $handles ) - ); - - wp_enqueue_font_variations( $handles ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_variation_handles() { - return array( - '1 variation handle' => array( 'merriweather-200-900-normal' ), - 'multiple same font family handles' => array( array( 'Source Serif Pro-300-normal', 'Source Serif Pro-900-italic' ) ), - 'handles from different font families' => array( array( 'merriweather-200-900-normal', 'Source Serif Pro-900-italic' ) ), - ); - } - - /** - * Integration test for enqueuing one or more specific variations. - * - * @dataProvider data_enqueue_variations - * - * @param string|string[] $handles Variation handles to test. - * @param array $expected Expected queue. - */ - public function test_should_enqueue_after_registration( $handles, array $expected ) { - foreach ( $this->get_data_registry() as $handle => $variations ) { - $this->setup_register( $handle, $variations ); - } - - wp_enqueue_font_variations( $handles ); - $this->assertEmpty( $this->get_queued_before_register(), '"queued_before_register" queue should be empty' ); - $this->assertSame( $expected, $this->get_enqueued_handles(), 'Queue should contain the given handles' ); - } - - /** - * Integration test for enqueuing before registering one or more specific variations. - * - * @dataProvider data_enqueue_variations - * - * @param string|string[] $handles Variation handles to test. - * @param array $not_used Not used. - * @param array $expected Expected "queued_before_register" queue. - */ - public function test_should_enqueue_before_registration( $handles, array $not_used, array $expected ) { - wp_enqueue_font_variations( $handles ); - - $this->assertSame( $expected, $this->get_queued_before_register(), '"queued_before_register" queue should contain the given handles' ); - $this->assertEmpty( $this->get_enqueued_handles(), 'Queue should be empty' ); - } -} diff --git a/phpunit/tests/fonts-api/wpEnqueueFonts.php b/phpunit/tests/fonts-api/wpEnqueueFonts.php deleted file mode 100644 index c00fb0f2dfdae..0000000000000 --- a/phpunit/tests/fonts-api/wpEnqueueFonts.php +++ /dev/null @@ -1,122 +0,0 @@ -set_up_mock( 'enqueue' ); - $mock->expects( $this->once() ) - ->method( 'enqueue' ) - ->with( - $this->identicalTo( $expected_handles ) - ); - - wp_enqueue_fonts( $font_families ); - } - - /** - * Integration test for enqueuing a font family and all of its variations. - * - * @dataProvider data_should_enqueue - * - * @param string[] $font_families Font families to test. - * @param string[] $expected_handles Expected handles passed to WP_Fonts::enqueue(). - */ - public function test_should_enqueue_after_registration( $font_families, $expected_handles ) { - // Register the font-families. - foreach ( $this->get_data_registry() as $handle => $variations ) { - $this->setup_register( $handle, $variations ); - } - - wp_enqueue_fonts( $font_families ); - - $this->assertEmpty( $this->get_queued_before_register(), '"queued_before_register" queue should be empty' ); - $this->assertSame( $expected_handles, $this->get_enqueued_handles(), 'Queue should contain the given font family(ies)' ); - } - - /** - * Integration test for enqueuing before registering a font family and all of its variations. - * - * @dataProvider data_should_enqueue - * - * @param string[] $font_families Font families to test. - * @param string[] $expected_handles Expected handles passed to WP_Fonts::enqueue(). - */ - public function test_should_enqueue_before_registration( $font_families, $expected_handles ) { - wp_enqueue_fonts( $font_families ); - - // Set up what "queued_before_register" queue should be. - $expected = array(); - foreach ( $expected_handles as $handle ) { - $expected[ $handle ] = null; - } - $this->assertSame( $expected, $this->get_queued_before_register(), '"queued_before_register" queue should contain the given font family(ies)' ); - $this->assertEmpty( $this->get_enqueued_handles(), 'Queue should be empty' ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_should_enqueue() { - return array( - '1: single word handle' => array( - 'font_families' => array( 'lato' ), - 'expected_handles' => array( 'lato' ), - ), - '1: multiple word handle' => array( - 'font_families' => array( 'source-serif-pro' ), - 'expected_handles' => array( 'source-serif-pro' ), - ), - '1: single word name' => array( - 'font_families' => array( 'Merriweather' ), - 'expected_handles' => array( 'merriweather' ), - ), - '1: multiple word name' => array( - 'font_families' => array( 'My Font' ), - 'expected_handles' => array( 'my-font' ), - ), - '>1: single word handle' => array( - 'font_families' => array( 'lato', 'merriweather' ), - 'expected_handles' => array( 'lato', 'merriweather' ), - ), - '>1: multiple word handle' => array( - 'font_families' => array( 'source-serif-pro', 'my-font' ), - 'expected_handles' => array( 'source-serif-pro', 'my-font' ), - ), - '>1: single word name' => array( - 'font_families' => array( 'Lato', 'Merriweather' ), - 'expected_handles' => array( 'lato', 'merriweather' ), - ), - '>1: multiple word name' => array( - 'font_families' => array( 'My Font', 'Source Serif Pro' ), - 'expected_handles' => array( 'my-font', 'source-serif-pro' ), - ), - '>1: mixture of word handles and names' => array( - 'font_families' => array( 'Source Serif Pro', 'Merriweather', 'my-font', 'Lato' ), - 'expected_handles' => array( 'source-serif-pro', 'merriweather', 'my-font', 'lato' ), - ), - ); - } -} diff --git a/phpunit/tests/fonts-api/wpFonts.php b/phpunit/tests/fonts-api/wpFonts.php deleted file mode 100644 index 3b33e58edf299..0000000000000 --- a/phpunit/tests/fonts-api/wpFonts.php +++ /dev/null @@ -1,38 +0,0 @@ -assertInstanceOf( WP_Fonts::class, wp_fonts() ); - } - - public function test_global_set() { - global $wp_fonts; - $this->assertNull( $wp_fonts ); - $instance = wp_fonts(); - $this->assertInstanceOf( WP_Fonts::class, $wp_fonts ); - $this->assertSame( $instance, $wp_fonts ); - } - - public function test_local_provider_is_automatically_registered() { - $expected = array( - 'local' => array( - 'class' => 'WP_Fonts_Provider_Local', - 'fonts' => array(), - ), - ); - $this->assertSame( $expected, wp_fonts()->get_providers() ); - } -} diff --git a/phpunit/tests/fonts-api/wpFonts/add.php b/phpunit/tests/fonts-api/wpFonts/add.php deleted file mode 100644 index 85d3d98c0f355..0000000000000 --- a/phpunit/tests/fonts-api/wpFonts/add.php +++ /dev/null @@ -1,44 +0,0 @@ -assertTrue( $wp_fonts->add( $handle, false ), 'Registering a handle should return true' ); - $this->assertCount( 1, $wp_fonts->registered ); - $this->assertArrayHasKey( $handle, $wp_fonts->registered, 'Font family handle should be in the registry after registration' ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_handles() { - return array( - 'name: multiple' => array( 'Source Serif Pro' ), - 'handle: multiple' => array( 'source-serif-pro' ), - 'name: single' => array( 'Merriweather' ), - 'handle: single' => array( 'merriweather' ), - 'handle: variation' => array( 'my-custom-font-200-900-normal' ), - ); - } -} diff --git a/phpunit/tests/fonts-api/wpFonts/addFontFamily.php b/phpunit/tests/fonts-api/wpFonts/addFontFamily.php deleted file mode 100644 index 69b6bccf5ae35..0000000000000 --- a/phpunit/tests/fonts-api/wpFonts/addFontFamily.php +++ /dev/null @@ -1,65 +0,0 @@ -add_font_family( $font_family ); - - $this->assertSame( $expected, $font_family_handle, 'Registering a font-family should return its handle' ); - $this->assertCount( 1, $wp_fonts->registered ); - $this->assertArrayHasKey( $font_family_handle, $wp_fonts->registered, 'Font family handle should be in the registry after registration' ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_handles() { - return array( - 'name: multiple' => array( - 'font_family' => 'Source Serif Pro', - 'expected' => 'source-serif-pro', - ), - 'handle: multiple' => array( - 'font_family' => 'source-serif-pro', - 'expected' => 'source-serif-pro', - ), - 'name: single' => array( - 'font_family' => 'Merriweather', - 'expected' => 'merriweather', - ), - 'handle: single' => array( - 'font_family' => 'merriweather', - 'expected' => 'merriweather', - ), - 'handle: variation' => array( - 'font_family' => 'my-custom-font-200-900-normal', - 'expected' => 'my-custom-font-200-900-normal', - ), - 'name: multiple font-families' => array( - 'font_family' => 'Source Serif Pro, Merriweather', - 'expected' => 'source-serif-pro', - ), - ); - } -} diff --git a/phpunit/tests/fonts-api/wpFonts/addVariation.php b/phpunit/tests/fonts-api/wpFonts/addVariation.php deleted file mode 100644 index 5b6d93bcc99fe..0000000000000 --- a/phpunit/tests/fonts-api/wpFonts/addVariation.php +++ /dev/null @@ -1,149 +0,0 @@ -add( $font_family_handle, false ); - - $variation_handle = $wp_fonts->add_variation( $font_family_handle, $variation, $variation_handle ); - $this->assertSame( $expected, $variation_handle, 'Registering a variation should return its handle' ); - $this->assertArrayHasKey( $variation_handle, $wp_fonts->registered, 'Variation handle should be in the registry after registration' ); - $this->assertSame( array( $expected ), $this->get_variations( $font_family_handle, $wp_fonts ), 'Variation should be registered to font family' ); - } - - /** - * @dataProvider data_valid_variation - * - * @param string|bool $expected Expected results. - * @param string $font_family_handle The font family's handle for this variation. - * @param array $variation An array of variation properties to add. - * @param string $variation_handle Optional. The variation's handle. - */ - public function test_should_not_reregister_font_family( $expected, $font_family_handle, array $variation, $variation_handle = '' ) { - $wp_fonts = new WP_Fonts(); - $wp_fonts->add( $font_family_handle, false ); - - $variation_handle = $wp_fonts->add_variation( $font_family_handle, $variation, $variation_handle ); - - // Font family should appear only once in the registered queue. - $expected = array( $font_family_handle, $variation_handle ); - $this->assertSame( $expected, array_keys( $wp_fonts->registered ), 'Font family should not be re-registered after registering a variation' ); - } - - /** - * @dataProvider data_valid_variation - * - * @param string|bool $expected Expected results. - * @param string $font_family_handle The font family's handle for this variation. - * @param array $variation An array of variation properties to add. - * @param string $variation_handle Optional. The variation's handle. - */ - public function test_should_not_reregister_variation( $expected, $font_family_handle, array $variation, $variation_handle = '' ) { - $wp_fonts = new WP_Fonts(); - $wp_fonts->add( $font_family_handle, false ); - - // Set up the test. - $variation_handle = $wp_fonts->add_variation( $font_family_handle, $variation, $variation_handle ); - - // Run the test. - $variant_handle_on_reregister = $wp_fonts->add_variation( $font_family_handle, $variation, $variation_handle ); - $this->assertSame( $expected, $variant_handle_on_reregister, 'Variation should be registered to font family' ); - $this->assertSame( $variation_handle, $variant_handle_on_reregister, 'Variation should return the previously registered variant handle' ); - $this->assertSame( array( $variation_handle ), $this->get_variations( $font_family_handle, $wp_fonts ), 'Variation should only be registered once' ); - - $this->assertCount( 2, $wp_fonts->registered ); - $this->assertArrayHasKey( $variation_handle, $wp_fonts->registered, 'Variation handle should be in the registry after registration' ); - } - - /** - * @dataProvider data_valid_variation - * - * @param string|bool $expected Expected results. - * @param string $font_family_handle The font family's handle for this variation. - * @param array $variation An array of variation properties to add. - * @param string $variation_handle Optional. The variation's handle. - */ - public function test_should_register_font_family_and_variation( $expected, $font_family_handle, array $variation, $variation_handle = '' ) { - $wp_fonts = new WP_Fonts(); - - $variation_handle = $wp_fonts->add_variation( $font_family_handle, $variation, $variation_handle ); - $this->assertSame( $expected, $variation_handle, 'Variation should return its registered handle' ); - - // Extra checks to ensure both are registered. - $this->assertCount( 2, $wp_fonts->registered ); - $this->assertArrayHasKey( $font_family_handle, $wp_fonts->registered, 'Font family handle should be in the registry after registration' ); - $this->assertArrayHasKey( $variation_handle, $wp_fonts->registered, 'Variation handle should be in the registry after registration' ); - $this->assertSame( array( $variation_handle ), $this->get_variations( $font_family_handle, $wp_fonts ), 'Variation should be registered to the font family' ); - } - - /** - * @dataProvider data_font_family_handle_undefined - * - * @param string $font_family_handle The font family's handle for this variation. - * @param array $variation An array of variation properties to add. - */ - public function test_should_not_register_font_family_or_variant( $font_family_handle, array $variation ) { - $this->expectNotice(); - $this->expectNoticeMessage( 'Font family handle must be a non-empty string.' ); - - $wp_fonts = new WP_Fonts(); - $wp_fonts->add_variation( $font_family_handle, $variation ); - - $this->assertEmpty( $wp_fonts->registered, 'Registered queue should be empty' ); - $this->assertEmpty( $this->get_variations( $font_family_handle, $wp_fonts ), 'Variation should not be registered to the font family' ); - } - - /** - * @dataProvider data_font_family_undefined_in_variation - * @dataProviders data_unable_determine_variation_handle - * - * @param string $font_family_handle The font family's handle for this variation. - * @param array $variation An array of variation properties to add. - * @param string $expected_message Expected notice message. - */ - public function test_should_not_register_variation_when_font_family_not_defined( $font_family_handle, array $variation, $expected_message ) { - $this->expectNotice(); - $this->expectNoticeMessage( $expected_message ); - - $wp_fonts = new WP_Fonts(); - $this->assertNull( $wp_fonts->add_variation( $font_family_handle, $variation ) ); - } - - /** - * @dataProvider data_unable_determine_variation_handle - * - * @param string $font_family_handle The font family's handle for this variation. - * @param array $variation An array of variation properties to add. - */ - public function test_should_register_font_family_when_variant_fails_to_register( $font_family_handle, array $variation ) { - $this->expectNotice(); - $this->expectNoticeMessage( 'Variant handle could not be determined as font-weight and/or font-style are require' ); - - $wp_fonts = new WP_Fonts(); - $wp_fonts->add_variation( $font_family_handle, $variation ); - - $this->assertCount( 1, $wp_fonts->registered ); - $this->assertArrayHasKey( $font_family_handle, $wp_fonts->registered ); - } -} diff --git a/phpunit/tests/fonts-api/wpFonts/dequeue.php b/phpunit/tests/fonts-api/wpFonts/dequeue.php deleted file mode 100644 index 6cd11dc55b937..0000000000000 --- a/phpunit/tests/fonts-api/wpFonts/dequeue.php +++ /dev/null @@ -1,72 +0,0 @@ -dequeue( $handles ); - $this->assertEmpty( $this->get_queued_before_register( $wp_fonts ), 'Prequeue should be empty' ); - $this->assertEmpty( $wp_fonts->queue, 'Queue should be empty' ); - } - - /** - * Integration test for dequeuing from queue. It first registers and then enqueues before dequeuing. - * - * @dataProvider data_enqueue - * @dataProvider data_enqueue_variations - * - * @param string|string[] $handles Handles to test. - */ - public function test_should_dequeue_from_queue( $handles ) { - $wp_fonts = new WP_Fonts(); - - // Register and enqueue. - foreach ( $this->get_data_registry() as $handle => $variations ) { - $this->setup_register( $handle, $variations, $wp_fonts ); - } - $wp_fonts->enqueue( $handles ); - - // To make sure the handles are in the queue before dequeuing. - $this->assertNotEmpty( $wp_fonts->queue, 'Queue not be empty before dequeueing' ); - - // Run the test. - $wp_fonts->dequeue( $handles ); - $this->assertEmpty( $wp_fonts->queue, 'Queue should be empty after dequeueing' ); - } - - /** - * Integration test for dequeuing from prequeue. It enqueues first. - * - * @dataProvider data_enqueue - * @dataProvider data_enqueue_variations - * - * @param string|string[] $handles Handles to test. - */ - public function test_should_dequeue_from_prequeue( $handles ) { - $wp_fonts = new WP_Fonts(); - $wp_fonts->enqueue( $handles ); - $this->assertNotEmpty( $this->get_queued_before_register( $wp_fonts ), 'Prequeue not be empty before dequeueing' ); - - $wp_fonts->dequeue( $handles ); - $this->assertEmpty( $this->get_queued_before_register( $wp_fonts ), 'Prequeue should be empty after dequeueing' ); - } -} diff --git a/phpunit/tests/fonts-api/wpFonts/doItem.php b/phpunit/tests/fonts-api/wpFonts/doItem.php deleted file mode 100644 index a92bd244d1f2a..0000000000000 --- a/phpunit/tests/fonts-api/wpFonts/doItem.php +++ /dev/null @@ -1,336 +0,0 @@ -wp_fonts = new WP_Fonts(); - } - - public function test_should_return_false_when_provider_not_registered() { - $this->assertFalse( $this->wp_fonts->do_item( 'provider_not_registered' ) ); - } - - /** - * @dataProvider data_provider_definitions - * - * @param array $provider Provider to mock. - */ - public function test_should_return_false_when_no_fonts_enqueued_for_provider( array $provider ) { - $this->setup_provider_property_mock( $this->wp_fonts, $provider ); - $this->assertFalse( $this->wp_fonts->do_item( $provider['id'] ) ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_provider_definitions() { - $providers = $this->get_provider_definitions(); - - return array( - 'mock' => array( $providers['mock'] ), - 'local' => array( $providers['local'] ), - ); - } - - /** - * Test the test set up to ensure the `Tests_Fonts_WpFonts_DoItem_::setup_provider_property_mock()` - * method works as expected. - */ - public function test_mocking_providers_property() { - $font_handles = array( 'font1', 'font2', 'font3' ); - $expected = array( - 'mock' => array( - 'class' => Mock_Provider::class, - 'fonts' => $font_handles, - ), - ); - - $this->setup_provider_property_mock( $this->wp_fonts, $this->get_provider_definitions( 'mock' ), $font_handles ); - $actual = $this->property['WP_Fonts::$providers']->getValue( $this->wp_fonts ); - $this->assertSame( $expected, $actual ); - } - - /** - * Test the private method WP_Fonts::get_enqueued_fonts_for_provider(). - * - * Why? This test validates the right fonts are returned for use within - * WP_Fonts::do_item(). - * - * @dataProvider data_get_enqueued_fonts_for_provider - * - * @param array $font_handles Array of handles for the provider. - * @param array $to_do Handles to set for the WP_Fonts::$to_do property. - * @param array $expected Expected result. - */ - public function test_get_enqueued_fonts_for_provider( $font_handles, $to_do, $expected ) { - // Set up the `to_do` property. - $this->wp_fonts->to_do = $to_do; - - // Open the method's visibility for testing. - $get_enqueued_fonts_for_provider = $this->get_reflection_method( 'get_enqueued_fonts_for_provider' ); - - // Mock the WP_Fonts::$property to set up the test. - $this->setup_provider_property_mock( $this->wp_fonts, $this->get_provider_definitions( 'mock' ), $font_handles ); - - $actual = $get_enqueued_fonts_for_provider->invoke( $this->wp_fonts, 'mock' ); - $this->assertSameSets( $expected, $actual ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_get_enqueued_fonts_for_provider() { - return array( - 'to_do queue is empty' => array( - 'font_handles ' => array( 'font1', 'font2', 'font3' ), - 'to_do' => array(), - 'expected' => array(), - ), - 'fonts not in to_do queue' => array( - 'font_handles ' => array( 'font1', 'font2', 'font3' ), - 'to_do' => array( 'font12', 'font13' ), - 'expected' => array(), - ), - '2 of the provider fonts in to_do queue' => array( - 'font_handles ' => array( 'font11', 'font12', 'font13' ), - 'to_do' => array( 'font11', 'font13' ), - 'expected' => array( 'font11', 'font13' ), - ), - 'do all of the provider fonts' => array( - 'font_handles ' => array( 'font21', 'font22', 'font23' ), - 'to_do' => array( 'font21', 'font22', 'font23' ), - 'expected' => array( 'font21', 'font22', 'font23' ), - ), - ); - } - - /** - * Test the private method WP_Fonts::get_font_properties_for_provider(). - * - * Why? This test validates the right font properties are returned for use within - * WP_Fonts::do_item(). - * - * @dataProvider data_get_font_properties_for_provider - * - * @param array $font_handles Web fonts for testing. - * @param array $expected Expected result. - */ - public function test_get_font_properties_for_provider( $font_handles, $expected ) { - // Set up the fonts for WP_Dependencies:get_data(). - $fonts = $this->get_registered_fonts(); - // Set all variations to 'mock' provider. - - // Mock the WP_Fonts::$property to set up the test. - $this->setup_provider_property_mock( $this->wp_fonts, $this->get_provider_definitions( 'mock' ), $font_handles ); - $this->setup_registration_mocks( $fonts, $this->wp_fonts ); - - // Open the method's visibility for testing. - $method = $this->get_reflection_method( 'get_font_properties_for_provider' ); - - $actual = $method->invoke( $this->wp_fonts, $font_handles ); - $this->assertSame( $expected, $actual ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_get_font_properties_for_provider() { - $fonts = $this->get_registered_fonts(); - - return array( - 'handles not registered' => array( - 'font_handles' => array( 'font-not-registered1', 'font-not-registered2', 'font-not-registered3' ), - 'expected' => array(), - ), - 'registered and non-registered handles' => array( - 'font_handles' => array( 'Source Serif Pro-300-normal', 'not-registered-handle', 'Source Serif Pro-900-italic' ), - 'expected' => array( - 'Source Serif Pro-300-normal' => $fonts['Source Serif Pro']['Source Serif Pro-300-normal'], - 'Source Serif Pro-900-italic' => $fonts['Source Serif Pro']['Source Serif Pro-900-italic'], - ), - ), - 'font-family handles, ie no "font-properties" extra data' => array( - 'font_handles' => array( 'font1', 'font2', 'merriweather' ), - 'expected' => array(), - ), - ); - } - - /** - * @dataProvider data_print_enqueued_fonts - * - * @param array $provider Define provider. - * @param array $fonts Fonts to register and enqueue. - * @param array $expected Expected results. - */ - public function test_should_trigger_provider_when_mocked( array $provider, array $fonts, array $expected ) { - $this->setup_print_deps( $provider, $fonts ); - - $provider_mock = $this->setup_object_mock( array( 'set_fonts', 'print_styles' ), $provider['class'] ); - - // Test the provider's methods are invoked. - $provider_mock->expects( $this->once() )->method( 'set_fonts' )->with( $this->identicalTo( $expected['set_fonts'] ) ); - $provider_mock->expects( $this->once() )->method( 'print_styles' ); - - // Set up the WP_Fonts::$provider_instances property. - $provider_instances = $this->get_reflection_property( 'provider_instances' ); - $provider_instances->setValue( $this->wp_fonts, array( $provider['id'] => $provider_mock ) ); - - // Test the method successfully processes the provider. - $this->expectOutputString( '' ); - $this->assertTrue( $this->wp_fonts->do_item( $provider['id'] ), 'WP_Fonts::do_item() should return true' ); - } - - /** - * Integration test. - * - * @dataProvider data_print_enqueued_fonts - * - * @param array $provider Define provider. - * @param array $fonts Fonts to register and enqueue. - * @param array $expected Expected results. - */ - public function test_should_print( array $provider, array $fonts, array $expected ) { - $this->setup_print_deps( $provider, $fonts ); - - // Test the method successfully processes the provider. - $this->expectOutputString( $expected['printed_output'] ); - $this->assertTrue( $this->wp_fonts->do_item( $provider['id'] ), 'WP_Fonts::do_item() should return true' ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_print_enqueued_fonts() { - $mock = $this->get_registered_mock_fonts(); - $local = $this->get_registered_local_fonts(); - $font_faces = $this->get_registered_fonts_css(); - - return array( - 'mock' => array( - 'provider' => $this->get_provider_definitions( 'mock' ), - 'fonts' => $mock, - 'expected' => array( - 'set_fonts' => array_merge( $mock['font1'], $mock['font2'], $mock['font3'] ), - 'printed_output' => sprintf( - '%s; %s; %s; %s; %s; %s\n', - $font_faces['font1-300-normal'], - $font_faces['font1-300-italic'], - $font_faces['font1-900-normal'], - $font_faces['font2-200-900-normal'], - $font_faces['font2-200-900-italic'], - $font_faces['font3-bold-normal'] - ), - ), - ), - 'local' => array( - 'provider' => $this->get_provider_definitions( 'local' ), - 'fonts' => $local, - 'expected' => array( - 'set_fonts' => array_merge( $local['merriweather'], $local['Source Serif Pro'] ), - 'printed_output' => sprintf( - "\n", - $font_faces['merriweather-200-900-normal'], - $font_faces['Source Serif Pro-300-normal'], - $font_faces['Source Serif Pro-900-italic'] - ), - ), - ), - ); - } - - /** - * Integration test. - * - * @dataProvider data_not_print_enqueued_fonts - * - * @param array $provider Define provider. - * @param array $fonts Fonts to register and enqueue. - * @param array $expected Not used. - * @param array $to_do_queue Value to set in the WP_Fonts::$to_do queue. - */ - public function test_should_not_print_when_to_do_queue_empty( array $provider, array $fonts, $expected, $to_do_queue ) { - $this->setup_print_deps( $provider, $fonts, $to_do_queue ); - - // Test the method successfully processes the provider. - $this->expectOutputString( '' ); - $this->assertFalse( $this->wp_fonts->do_item( $provider['id'] ), 'WP_Fonts::do_item() should return false' ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_not_print_enqueued_fonts() { - $mock = $this->get_registered_mock_fonts(); - $local = $this->get_registered_local_fonts(); - - return array( - 'mock provider when to_do queue is empty' => array( - 'provider' => $this->get_provider_definitions( 'mock' ), - 'fonts' => $mock, - 'expected' => array(), - 'to_do_queue' => array(), - ), - 'local provider when to_do queue is empty' => array( - 'provider' => $this->get_provider_definitions( 'local' ), - 'fonts' => $local, - 'expected' => array(), - 'to_do_queue' => array(), - ), - 'fonts not in to_do queue' => array( - 'provider' => $this->get_provider_definitions( 'mock' ), - 'fonts' => $mock, - 'expected' => array(), - 'to_do_queue' => array(), - ), - ); - } - - /** - * Sets up the print dependencies. - * - * @param array $provider Provider id and class. - * @param array $fonts Fonts to register and enqueue. - * @param array|null $to_do_queue Set the WP_Fonts:$to_do queue. - */ - private function setup_print_deps( $provider, $fonts, $to_do_queue = null ) { - // Set up the fonts for WP_Dependencies:get_data(). - $mocks = $this->setup_registration_mocks( $fonts, $this->wp_fonts ); - $handles = array_keys( $mocks ); - $this->setup_provider_property_mock( $this->wp_fonts, $provider, $handles ); - - // Set up the `WP_Fonts::$to_do` and `WP_Fonts::$to_do_keyed_handles` properties. - if ( null === $to_do_queue ) { - $to_do_queue = $handles; - } - - $this->wp_fonts->to_do = $to_do_queue; - $to_do_keyed_handles = $this->get_reflection_property( 'to_do_keyed_handles' ); - $to_do_keyed_handles->setValue( $this->wp_fonts, array_flip( $to_do_queue ) ); - } -} diff --git a/phpunit/tests/fonts-api/wpFonts/doItems.php b/phpunit/tests/fonts-api/wpFonts/doItems.php deleted file mode 100644 index 8a29e7463406a..0000000000000 --- a/phpunit/tests/fonts-api/wpFonts/doItems.php +++ /dev/null @@ -1,196 +0,0 @@ -wp_fonts = new WP_Fonts(); - } - - public function test_should_not_process_when_no_providers_registered() { - $this->setup_deps( array( 'enqueued' => 'font1' ) ); - - $done = $this->wp_fonts->do_items(); - - $this->assertSame( array(), $done, 'WP_Fonts::do_items() should return an empty array' ); - $this->assertSame( array(), $this->wp_fonts->to_do, 'WP_Fonts::$to_do should be an empty array' ); - } - - /** - * @dataProvider data_invalid_handles - * - * @param mixed $handles Handles to test. - */ - public function test_should_throw_notice_when_invalid_handles( $handles ) { - $this->expectNotice(); - $this->expectNoticeMessage( 'Handles must be a non-empty string or array of non-empty strings' ); - - $this->wp_fonts->do_items( $handles ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_invalid_handles() { - return array( - 'null' => array( null ), - 'empty array' => array( array() ), - 'empty string' => array( '' ), - 'array of empty strings' => array( array( '', '' ) ), - 'array of mixed falsey values' => array( array( '', false, null, array() ) ), - ); - } - - public function test_should_throw_notice_when_provider_class_not_found() { - $this->expectNotice(); - $this->expectNoticeMessage( 'Class "Provider_Does_Not_Exist" not found for "doesnotexist" font provider' ); - - $setup = array( - 'provider' => array( - 'doesnotexist' => array( - 'id' => 'doesnotexist', - 'class' => 'Provider_Does_Not_Exist', - ), - ), - 'provider_handles' => array( 'doesnotexist' => array( 'font1' ) ), - 'registered' => array( - 'doesnotexist' => array( - 'font1' => array( - 'font1-300-normal' => array( - 'provider' => 'doesnotexist', - 'font-weight' => '300', - 'font-style' => 'normal', - 'font-display' => 'fallback', - ), - ), - ), - ), - 'enqueued' => array( 'font1', 'font1-300-normal' ), - ); - $this->setup_deps( $setup ); - - $this->wp_fonts->do_items(); - } - - /** - * @dataProvider data_print_enqueued - * - * @param array $setup Test set up information for provider, fonts, and enqueued. - * @param array $expected_done Expected array of printed handles. - * @param string $expected_output Expected printed output. - */ - public function test_should_print_mocked_enqueued( $setup, $expected_done, $expected_output ) { - $this->setup_deps( $setup ); - - $this->expectOutputString( $expected_output ); - $actual_done = $this->wp_fonts->do_items(); - $this->assertSameSets( $expected_done, $actual_done, 'Printed handles should match' ); - } - - /** - * Integration test that registers providers and fonts and then enqueues before - * testing the printing functionality. - * - * @dataProvider data_print_enqueued - * - * @param array $setup Test set up information for provider, fonts, and enqueued. - * @param array $expected_done Expected array of printed handles. - * @param string $expected_output Expected printed output. - */ - public function test_should_print_enqueued( $setup, $expected_done, $expected_output ) { - $this->setup_integrated_deps( $setup ); - - $this->expectOutputString( $expected_output, 'Printed @font-face styles should match' ); - $actual_done = $this->wp_fonts->do_items(); - $this->assertSameSets( $expected_done, $actual_done, 'Printed handles should match' ); - } - - /** - * Integration test to validate printing given handles. Rather than mocking internal functionality, - * it registers providers and fonts but does not enqueue. - * - * @dataProvider data_print_enqueued - * - * @param array $setup Test set up information for provider, fonts, and enqueued. - * @param array $expected_done Expected array of printed handles. - * @param string $expected_output Expected printed output. - */ - public function test_should_print_handles_when_not_enqueued( $setup, $expected_done, $expected_output ) { - $this->setup_integrated_deps( $setup, false ); - // Do not enqueue. Instead, pass the handles to WP_Fonts::do_items(). - $handles = $setup['enqueued']; - $this->assertEmpty( $this->wp_fonts->queue, 'No fonts should be enqueued' ); - - $this->expectOutputString( $expected_output ); - $actual_done = $this->wp_fonts->do_items( $handles ); - $this->assertSameSets( $expected_done, $actual_done, 'Printed handles should match' ); - } - - /** - * Sets up the dependencies for the mocked test. - * - * @param array $setup Dependencies to set up. - */ - private function setup_deps( array $setup ) { - $setup = array_merge( - array( - 'provider' => array(), - 'provider_handles' => array(), - 'registered' => array(), - 'enqueued' => array(), - ), - $setup - ); - - if ( ! empty( $setup['provider'] ) ) { - foreach ( $setup['provider'] as $provider_id => $provider ) { - $this->setup_provider_property_mock( $this->wp_fonts, $provider, $setup['provider_handles'][ $provider_id ] ); - } - } - - if ( ! empty( $setup['registered'] ) ) { - $this->setup_registration_mocks( $setup['registered'], $this->wp_fonts ); - } - - if ( ! empty( $setup['enqueued'] ) ) { - $queue = $this->get_reflection_property( 'queue' ); - $queue->setValue( $this->wp_fonts, $setup['enqueued'] ); - } - } - - /** - * Sets up the dependencies for integration test. - * - * @param array $setup Dependencies to set up. - * @param bool $enqueue Whether to enqueue. Default true. - */ - private function setup_integrated_deps( array $setup, $enqueue = true ) { - foreach ( $setup['provider'] as $provider ) { - $this->wp_fonts->register_provider( $provider['id'], $provider['class'] ); - } - foreach ( $setup['registered'] as $handle => $variations ) { - $this->setup_register( $handle, $variations, $this->wp_fonts ); - } - - if ( $enqueue ) { - $this->wp_fonts->enqueue( $setup['enqueued'] ); - } - } -} diff --git a/phpunit/tests/fonts-api/wpFonts/enqueue.php b/phpunit/tests/fonts-api/wpFonts/enqueue.php deleted file mode 100644 index 09c14676c7ae0..0000000000000 --- a/phpunit/tests/fonts-api/wpFonts/enqueue.php +++ /dev/null @@ -1,53 +0,0 @@ -enqueue( $handles ); - - $this->assertSame( $expected, $this->get_queued_before_register( $wp_fonts ), 'Handles should be added to before registered queue' ); - $this->assertEmpty( $wp_fonts->queue, 'Handles should not be added to the enqueue queue when not registered' ); - } - - /** - * Integration test for enqueuing (a) a font family and all of its variations or (b) specific variations. - * - * @dataProvider data_enqueue - * @dataProviders data_enqueue_variations - * - * @param string|string[] $handles Handles to test. - * @param array $expected Expected queue. - */ - public function test_should_enqueue_when_registered( $handles, array $expected ) { - $wp_fonts = new WP_Fonts(); - foreach ( $this->get_data_registry() as $font_family => $variations ) { - $this->setup_register( $font_family, $variations, $wp_fonts ); - } - - $wp_fonts->enqueue( $handles ); - - $this->assertEmpty( $this->get_queued_before_register( $wp_fonts ), '"queued_before_register" queue should be empty' ); - $this->assertSame( $expected, $wp_fonts->queue, 'Queue should contain the given handles' ); - } -} diff --git a/phpunit/tests/fonts-api/wpFonts/getEnqueued.php b/phpunit/tests/fonts-api/wpFonts/getEnqueued.php deleted file mode 100644 index bacb8a31aa650..0000000000000 --- a/phpunit/tests/fonts-api/wpFonts/getEnqueued.php +++ /dev/null @@ -1,57 +0,0 @@ -assertEmpty( $wp_fonts->get_enqueued() ); - } - - /** - * Unit test for when font families are enqueued. - * - * @dataProvider data_enqueue - * - * @param string|string[] $not_used Not used. - * @param array $expected Expected queue. - */ - public function test_should_return_queue_when_property_has_font_families( $not_used, array $expected ) { - $wp_fonts = new WP_Fonts(); - $wp_fonts->queue = $expected; - - $this->assertSame( $expected, $wp_fonts->get_enqueued() ); - } - - /** - * Full integration test that registers and enqueues the queue - * is properly wired for "get_enqueued()". - * - * @dataProvider data_enqueue - * - * @param string|string[] $font_family Font family to test. - * @param array $expected Expected queue. - */ - public function test_should_return_queue_when_font_families_registered_and_enqueued( $font_family, array $expected ) { - $wp_fonts = new WP_Fonts(); - - // Register and enqueue. - foreach ( $this->get_data_registry() as $handle => $variations ) { - $this->setup_register( $handle, $variations, $wp_fonts ); - } - $wp_fonts->enqueue( $font_family ); - - $this->assertSame( $expected, $wp_fonts->get_enqueued() ); - } -} diff --git a/phpunit/tests/fonts-api/wpFonts/getProviders.php b/phpunit/tests/fonts-api/wpFonts/getProviders.php deleted file mode 100644 index 410adaace286a..0000000000000 --- a/phpunit/tests/fonts-api/wpFonts/getProviders.php +++ /dev/null @@ -1,62 +0,0 @@ -wp_fonts = new WP_Fonts(); - - $this->providers_property = new ReflectionProperty( WP_Fonts::class, 'providers' ); - $this->providers_property->setAccessible( true ); - } - - public function test_should_be_empty() { - $actual = $this->wp_fonts->get_providers(); - $this->assertIsArray( $actual, 'Should return an empty array' ); - $this->assertEmpty( $actual, 'Should return an empty array when no providers are registered' ); - } - - /** - * @dataProvider data_get_providers - * - * @param array $providers Array of providers to test. - * @param array $expected Expected results. - */ - public function test_get_providers( array $providers, array $expected ) { - $this->setup_providers( $providers ); - $this->assertSame( $expected, $this->wp_fonts->get_providers() ); - } - - /** - * Sets up the given providers and stores them in the `WP_Fonts::providers` property. - * - * @param array $providers Array of providers to set up. - */ - private function setup_providers( array $providers ) { - $data = array(); - - foreach ( $providers as $provider_id => $class ) { - $data[ $provider_id ] = array( - 'class' => $class, - 'fonts' => array(), - ); - } - - $this->providers_property->setValue( $this->wp_fonts, $data ); - } -} diff --git a/phpunit/tests/fonts-api/wpFonts/getRegistered.php b/phpunit/tests/fonts-api/wpFonts/getRegistered.php deleted file mode 100644 index 7dc116f587539..0000000000000 --- a/phpunit/tests/fonts-api/wpFonts/getRegistered.php +++ /dev/null @@ -1,90 +0,0 @@ -assertEmpty( $wp_fonts->get_registered() ); - } - - /** - * Unit test for when font families are enqueued. - * - * @dataProvider data_get_registered - * - * @param array $inputs Font family(ies) and variations to register. - */ - public function test_should_return_queue_when_mocking_registered_property( array $inputs ) { - $wp_fonts = new WP_Fonts(); - $mocks = $this->setup_registration_mocks( $inputs, $wp_fonts ); - $expected = array_keys( $mocks ); - - $this->assertSame( $expected, $wp_fonts->get_registered() ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_get_registered() { - return array( - 'no variations' => array( - 'inputs' => array( - 'lato' => array(), - ), - ), - 'with 1 variation' => array( - 'inputs' => array( - 'Source Serif Pro' => array( 'variation-1' ), - ), - ), - 'with 2 variations' => array( - 'inputs' => array( - 'my-cool-font' => array( 'cool-1', 'cool-2' ), - ), - ), - 'when multiple font families registered' => array( - 'inputs' => array( - 'font-family-1' => array( 'variation-11', 'variation-12' ), - 'font-family-2' => array( 'variation-21', 'variation-22' ), - 'font-family-3' => array( 'variation-31', 'variation-32' ), - ), - ), - ); - } - - /** - * Full integration test that registers varying number of font families and variations - * to validate if "get_registered()" internals is property wired to the registered queue. - * - * @dataProvider data_one_to_many_font_families_and_zero_to_many_variations - * - * @param string $font_family Not used. - * @param array $inputs Font family(ies) and variations to register. - * @param array $expected Expected results. - */ - public function test_should_return_queue_when_items_are_registered( $font_family, array $inputs, array $expected ) { - $wp_fonts = new WP_Fonts(); - - // Register before testing. - foreach ( $inputs as $handle => $variations ) { - $this->setup_register( $handle, $variations, $wp_fonts ); - } - - $this->assertSame( $expected, $wp_fonts->get_registered() ); - } -} diff --git a/phpunit/tests/fonts-api/wpFonts/query.php b/phpunit/tests/fonts-api/wpFonts/query.php deleted file mode 100644 index 0e56b515e7ebf..0000000000000 --- a/phpunit/tests/fonts-api/wpFonts/query.php +++ /dev/null @@ -1,151 +0,0 @@ -wp_fonts = new WP_Fonts(); - } - - /** - * @dataProvider data_invalid_query - * @dataProvider data_valid_query - * - * @param string $query_handle Handle to test. - */ - public function test_should_fail_when_handles_not_registered( $query_handle ) { - $this->assertFalse( $this->wp_fonts->query( $query_handle, 'registered' ) ); - } - - /** - * @dataProvider data_invalid_query - * @dataProvider data_valid_query - * - * @param string $query_handle Handle to test. - */ - public function test_should_fail_when_handles_not_registered_or_enqueued( $query_handle ) { - $this->assertFalse( $this->wp_fonts->query( $query_handle, 'queue' ) ); - } - - /** - * @dataProvider data_valid_query - * - * @param string $query_handle Handle to test. - */ - public function test_registered_query_should_succeed_when_registered( $query_handle ) { - $this->setup_registry(); - - $actual = $this->wp_fonts->query( $query_handle, 'registered' ); - $this->assertInstanceOf( '_WP_Dependency', $actual, 'Query should return an instance of _WP_Dependency' ); - $this->assertSame( $query_handle, $actual->handle, 'Query object handle should match the given handle to query' ); - } - - /** - * @dataProvider data_valid_query - * - * @param string $query_handle Handle to test. - */ - public function test_enqueued_query_should_succeed_when_registered_and_enqueued( $query_handle ) { - $this->setup_registry(); - $this->wp_fonts->enqueue( $query_handle ); - - $this->assertTrue( $this->wp_fonts->query( $query_handle, 'enqueued' ) ); - } - - /** - * @dataProvider data_valid_query - * - * @param string $query_handle Handle to test. - */ - public function test_enqueued_query_should_fail_when_not_registered_but_enqueued( $query_handle ) { - $this->wp_fonts->enqueue( $query_handle ); - - $this->assertFalse( $this->wp_fonts->query( $query_handle, 'enqueued' ) ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_invalid_query() { - return array( - 'DM Sans' => array( 'DM Sans' ), - 'roboto' => array( 'roboto' ), - 'my-font' => array( 'my-font' ), - ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_valid_query() { - return array( - 'lato' => array( 'lato' ), - 'merriweather' => array( 'merriweather' ), - 'Source Serif Pro' => array( 'source-serif-pro' ), - ); - } - - public function test_done_query_should_fail_when_no_variations() { - $this->wp_fonts->register_provider( 'local', WP_Fonts_Provider_Local::class ); - $this->setup_registry(); - $this->wp_fonts->enqueue( 'lato' ); - - $this->wp_fonts->do_items( 'lato' ); - - $this->assertFalse( $this->wp_fonts->query( 'lato', 'done' ) ); - } - - /** - * @dataProvider data_done_query - * - * @param string $query_handle Handle to test. - */ - public function test_done_query_should_succeed_when_registered_and_enqueued( $query_handle ) { - $this->wp_fonts->register_provider( 'local', WP_Fonts_Provider_Local::class ); - $this->setup_registry(); - $this->wp_fonts->enqueue( $query_handle ); - - // Process the fonts while ignoring all the printed output. - $this->expectOutputRegex( '`.`' ); - $this->wp_fonts->do_items( $query_handle ); - $this->getActualOutput(); - - $this->assertTrue( $this->wp_fonts->query( $query_handle, 'done' ) ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_done_query() { - return array( - 'merriweather' => array( 'merriweather' ), - 'Source Serif Pro' => array( 'source-serif-pro' ), - ); - } - - private function setup_registry() { - foreach ( $this->get_registered_local_fonts() as $handle => $variations ) { - $this->setup_register( $handle, $variations, $this->wp_fonts ); - } - } -} diff --git a/phpunit/tests/fonts-api/wpFonts/registerProvider.php b/phpunit/tests/fonts-api/wpFonts/registerProvider.php deleted file mode 100644 index c67976e0a6865..0000000000000 --- a/phpunit/tests/fonts-api/wpFonts/registerProvider.php +++ /dev/null @@ -1,116 +0,0 @@ -assertTrue( $wp_fonts->register_provider( $provider_id, $class_name ), 'WP_Fonts::register_provider() should return true' ); - $this->assertSame( $expected, $wp_fonts->get_providers(), 'Provider "' . $provider_id . '" should be registered in providers queue' ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_register_providers() { - return array( - 'mock' => array( - 'provider_id' => 'mock', - 'class' => Mock_Provider::class, - 'expected' => array( - 'mock' => array( - 'class' => Mock_Provider::class, - 'fonts' => array(), - ), - ), - ), - 'local' => array( - 'provider_id' => 'local', - 'class' => WP_Fonts_Provider_Local::class, - 'expected' => array( - 'local' => array( - 'class' => WP_Fonts_Provider_Local::class, - 'fonts' => array(), - ), - ), - ), - ); - } - - public function test_should_register_multiple_providers() { - $wp_fonts = new WP_Fonts(); - $providers = $this->get_provider_definitions(); - foreach ( $providers as $provider ) { - $this->assertTrue( $wp_fonts->register_provider( $provider['id'], $provider['class'] ), 'WP_Fonts::register_provider() should return true for provider ' . $provider['id'] ); - } - - $expected = array( - 'mock' => array( - 'class' => $providers['mock']['class'], - 'fonts' => array(), - ), - 'local' => array( - 'class' => $providers['local']['class'], - 'fonts' => array(), - ), - ); - - $this->assertSame( $expected, $wp_fonts->get_providers(), 'Both local and mock providers should be registered' ); - } - - /** - * @dataProvider data_invalid_providers - * - * @param string $provider_id Provider ID. - * @param string $class_name Provider class name. - */ - public function test_should_not_register( $provider_id, $class_name ) { - $wp_fonts = new WP_Fonts(); - - $this->assertFalse( $wp_fonts->register_provider( $provider_id, $class_name ), 'WP_Fonts::register_provider() should return false' ); - $this->assertArrayNotHasKey( $provider_id, $wp_fonts->get_providers(), 'Both local and mock providers should be registered' ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_invalid_providers() { - return array( - 'provider_id is empty' => array( - 'provider_id' => '', - 'class' => Mock_Provider::class, - ), - 'class is empty' => array( - 'provider_id' => 'local', - 'class' => '', - ), - 'class does not exist' => array( - 'provider_id' => 'doesnotexist', - 'class' => 'Provider_Does_Not_Exist', - ), - ); - } -} diff --git a/phpunit/tests/fonts-api/wpFonts/remove.php b/phpunit/tests/fonts-api/wpFonts/remove.php deleted file mode 100644 index 208bd58c3d2c3..0000000000000 --- a/phpunit/tests/fonts-api/wpFonts/remove.php +++ /dev/null @@ -1,118 +0,0 @@ -remove( array( 'handle-1', 'handle2' ) ); - - $this->assertEmpty( $wp_fonts->registered ); - } - - /** - * @dataProvider data_remove_when_registered - * - * @param array $handles Handles to remove. - * @param array $expected Expected handles are running test. - */ - public function test_should_remove_when_registered( array $handles, array $expected ) { - $wp_fonts = new WP_Fonts(); - $wp_fonts->registered = $this->generate_registered_queue(); - - $wp_fonts->remove( $handles ); - - $this->assertSameSets( $expected, array_keys( $wp_fonts->registered ), 'Registered queue should match after removing handles' ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_remove_when_registered() { - $all = array( - 'handle-1', - 'handle-2', - 'handle-3', - 'handle-4', - 'handle-5', - 'handle-6', - 'handle-7', - 'handle-8', - 'handle-9', - 'handle-10', - ); - - return array( - 'remove none' => array( - 'handles' => array(), - 'expected' => $all, - ), - 'remove handle-5' => array( - 'handles' => array( 'handle-5' ), - 'expected' => array( - 'handle-1', - 'handle-2', - 'handle-3', - 'handle-4', - 'handle-6', - 'handle-7', - 'handle-8', - 'handle-9', - 'handle-10', - ), - ), - 'remove 2 from start and end' => array( - 'handles' => array( 'handle-1', 'handle-2', 'handle-9', 'handle-10' ), - 'expected' => array( - 'handle-3', - 'handle-4', - 'handle-5', - 'handle-6', - 'handle-7', - 'handle-8', - ), - ), - 'remove all' => array( - 'handles' => $all, - 'expected' => array(), - ), - 'remove only registered' => array( - 'handles' => array( 'handle-1', 'handle-10', 'handle-abc', 'handle-5' ), - 'expected' => array( - 'handle-2', - 'handle-3', - 'handle-4', - 'handle-6', - 'handle-7', - 'handle-8', - 'handle-9', - ), - ), - ); - } - - private function generate_registered_queue() { - $queue = array(); - for ( $num = 1; $num <= 10; $num++ ) { - $handle = "handle-{$num}"; - $queue[ $handle ] = $num; - } - - return $queue; - } -} diff --git a/phpunit/tests/fonts-api/wpFonts/removeFontFamily.php b/phpunit/tests/fonts-api/wpFonts/removeFontFamily.php deleted file mode 100644 index 6e762307d0520..0000000000000 --- a/phpunit/tests/fonts-api/wpFonts/removeFontFamily.php +++ /dev/null @@ -1,89 +0,0 @@ -setup_registration_mocks( $inputs, $wp_fonts ); - // Test the before state, just to make sure. - $this->assertArrayHasKey( $font_family, $wp_fonts->registered, 'Registered queue should contain the font family before remove' ); - $this->assertSame( $registered_handles, array_keys( $wp_fonts->registered ), 'Font family and variations should be registered before remove' ); - - $wp_fonts->remove_font_family( $font_family ); - - $this->assertArrayNotHasKey( $font_family, $wp_fonts->registered, 'Registered queue should not contain the font family' ); - $this->assertSame( $expected, array_keys( $wp_fonts->registered ), 'Registered queue should match after removing font family' ); - } - - /** - * @dataProvider data_one_to_many_font_families_and_zero_to_many_variations - * - * @param string $font_family Font family to test. - * @param array $inputs Font family(ies) and variations to pre-register. - * @param array $registered_handles Not used. - * @param array $expected Array of expected handles. - */ - public function test_should_bail_out_when_not_registered( $font_family, array $inputs, array $registered_handles, array $expected ) { - $wp_fonts = new WP_Fonts(); - unset( $inputs[ $font_family ] ); - $this->setup_registration_mocks( $inputs, $wp_fonts ); - - $wp_fonts->remove_font_family( $font_family ); - - $this->assertArrayNotHasKey( $font_family, $wp_fonts->registered, 'Registered queue should not contain the font family' ); - $this->assertSame( $expected, array_keys( $wp_fonts->registered ), 'Registered queue should match after removing font family' ); - } - - /** - * Integration test for removing a font family and all of its variation when font family is registered. - * - * @dataProvider data_one_to_many_font_families_and_zero_to_many_variations - * - * @param string $font_family Font family to test. - * @param array $inputs Font family(ies) and variations to pre-register. - * @param array $registered_handles Expected handles after registering. - * @param array $expected Array of expected handles. - */ - public function test_should_deregister_when_registered( $font_family, array $inputs, array $registered_handles, array $expected ) { - $wp_fonts = new WP_Fonts(); - // Register all font families and their variations. - foreach ( $inputs as $input_font_family => $variations ) { - $handle = $wp_fonts->add_font_family( $input_font_family ); - foreach ( $variations as $variation_handle => $variation ) { - if ( ! is_string( $variation_handle ) ) { - $variation_handle = ''; - } - $wp_fonts->add_variation( $handle, $variation, $variation_handle ); - } - } - // Test the before state, just to make sure. - $this->assertArrayHasKey( $font_family, $wp_fonts->registered, 'Registered queue should contain the font family before remove' ); - $this->assertSame( $registered_handles, array_keys( $wp_fonts->registered ), 'Font family and variations should be registered before remove' ); - - $wp_fonts->remove_font_family( $font_family ); - - $this->assertArrayNotHasKey( $font_family, $wp_fonts->registered, 'Registered queue should not contain the font family' ); - $this->assertSame( $expected, array_keys( $wp_fonts->registered ), 'Registered queue should match after removing font family' ); - } -} diff --git a/phpunit/tests/fonts-api/wpFonts/removeVariation.php b/phpunit/tests/fonts-api/wpFonts/removeVariation.php deleted file mode 100644 index 508c8ce264d8f..0000000000000 --- a/phpunit/tests/fonts-api/wpFonts/removeVariation.php +++ /dev/null @@ -1,278 +0,0 @@ -wp_fonts = new WP_Fonts(); - $this->fonts_to_register = $this->get_registered_local_fonts(); - } - - /** - * Sets up the unit test by mocking the WP_Dependencies object using stdClass and - * registering each font family directly to the WP_Fonts::$registered property - * and its variations to the mocked $deps property. - */ - private function setup_unit_test() { - $this->setup_registration_mocks( $this->fonts_to_register, $this->wp_fonts ); - } - - /** - * Sets up the integration test by properly registering each font family and its variations - * by using the WP_Fonts::add() and WP_Fonts::add_variation() methods. - */ - private function setup_integration_test() { - foreach ( $this->fonts_to_register as $font_family_handle => $variations ) { - $this->setup_register( $font_family_handle, $variations, $this->wp_fonts ); - } - } - - /** - * Testing the test setup to ensure it works. - * - * @dataProvider data_remove_variations - * - * @param string $font_family_handle Font family for the variation. - * @param string $variation_handle Variation handle to remove. - */ - public function test_mocked_setup( $font_family_handle, $variation_handle ) { - $this->setup_unit_test(); - - $this->assertArrayHasKey( $variation_handle, $this->wp_fonts->registered, 'Variation should be in the registered queue before removal' ); - $this->assertContains( $variation_handle, $this->wp_fonts->registered[ $font_family_handle ]->deps, 'Variation should be in its font family deps before removal' ); - } - - /** - * Unit test. - * - * @dataProvider data_should_do_nothing_when_variation_and_font_family_not_registered - * - * @param string $font_family Font family name. - * @param string $font_family_handle Font family handle. - * @param string $variation_handle Variation handle to remove. - */ - public function test_unit_should_do_nothing_when_variation_and_font_family_not_registered( $font_family, $font_family_handle, $variation_handle ) { - // Set up the test. - unset( $this->fonts_to_register[ $font_family ] ); - $this->setup_unit_test(); - $registered_queue = $this->wp_fonts->registered; - - // Run the tests. - $this->wp_fonts->remove_variation( $font_family_handle, $variation_handle ); - $this->assertArrayNotHasKey( $font_family_handle, $this->wp_fonts->registered, 'Font family should not be registered' ); - $this->assertArrayNotHasKey( $variation_handle, $this->wp_fonts->registered, 'Variant should not be registered' ); - $this->assertSame( $registered_queue, $this->wp_fonts->registered, 'Registered queue should not have changed' ); - } - - /** - * Integration test. - * - * @dataProvider data_should_do_nothing_when_variation_and_font_family_not_registered - * - * @param string $font_family Font family name. - * @param string $font_family_handle Font family handle. - * @param string $variation_handle Variation handle to remove. - */ - public function test_should_do_nothing_when_variation_and_font_family_not_registered( $font_family, $font_family_handle, $variation_handle ) { - // Set up the test. - unset( $this->fonts_to_register[ $font_family ] ); - $this->setup_integration_test(); - $registered_queue = $this->wp_fonts->get_registered(); - - // Run the tests. - $this->wp_fonts->remove_variation( $font_family_handle, $variation_handle ); - $this->assertArrayNotHasKey( $font_family_handle, $this->wp_fonts->registered, 'Font family should not be registered' ); - $this->assertArrayNotHasKey( $variation_handle, $this->wp_fonts->registered, 'Variant should not be registered' ); - $this->assertSameSets( $registered_queue, $this->wp_fonts->get_registered(), 'Registered queue should not have changed' ); - } - - /** - * Data provider for testing removal of variations. - * - * @return array - */ - public function data_should_do_nothing_when_variation_and_font_family_not_registered() { - return array( - 'Font with 1 variation' => array( - 'font_family' => 'merriweather', - 'font_family_handle' => 'merriweather', - 'variation_handle' => 'merriweather-200-900-normal', - ), - 'Font with multiple variations' => array( - 'font_family' => 'Source Serif Pro', - 'font_family_handle' => 'source-serif-pro', - 'variation_handle' => 'Source Serif Pro-300-normal', - ), - ); - } - - /** - * Unit test. - * - * @dataProvider data_remove_variations - * - * @param string $font_family_handle Font family for the variation. - * @param string $variation_handle Variation handle to remove. - * @param array $expected Expected results. - */ - public function test_unit_should_only_remove_from_font_family_deps_when_variation_not_in_queue( $font_family_handle, $variation_handle, $expected ) { - // Set up the test. - $this->setup_unit_test(); - $this->setup_remove_variation_from_registered( $variation_handle ); - - // Run the tests. - $this->wp_fonts->remove_variation( $font_family_handle, $variation_handle ); - $this->assertArrayNotHasKey( $variation_handle, $this->wp_fonts->registered, 'Variant should not be registered' ); - $this->assertNotContains( $variation_handle, $this->wp_fonts->registered[ $font_family_handle ]->deps, 'Variation should not be its font family deps' ); - $this->assertSameSets( $expected['font_family_deps'], array_values( $this->wp_fonts->registered[ $font_family_handle ]->deps ), 'Only the tested variation handle should be removed from font family deps' ); - } - - /** - * Integration test. - * - * @dataProvider data_remove_variations - * - * @param string $font_family_handle Font family for the variation. - * @param string $variation_handle Variation handle to remove. - * @param array $expected Expected results. - */ - public function test_should_only_remove_from_font_family_deps_when_variation_not_in_queue( $font_family_handle, $variation_handle, $expected ) { - // Set up the test. - $this->setup_integration_test(); - $this->setup_remove_variation_from_registered( $variation_handle ); - - // Run the tests. - $this->wp_fonts->remove_variation( $font_family_handle, $variation_handle ); - $this->assertArrayNotHasKey( $variation_handle, $this->wp_fonts->registered, 'Variant should not be registered' ); - $this->assertNotContains( $variation_handle, $this->wp_fonts->registered[ $font_family_handle ]->deps, 'Variation should not be its font family deps' ); - $this->assertSameSets( $expected['font_family_deps'], array_values( $this->wp_fonts->registered[ $font_family_handle ]->deps ), 'Only the tested variation handle should be removed from font family deps' ); - } - - /** - * Unit test. - * - * @dataProvider data_remove_variations - * - * @param string $font_family_handle Font family for the variation. - * @param string $variation_handle Variation handle to remove. - * @param array $expected Expected results. - */ - public function test_unit_should_remove_variation_from_registered_queue_though_font_family_not_registered( $font_family_handle, $variation_handle, $expected ) { - // Set up the test. - $this->setup_unit_test(); - $this->setup_remove_from_font_family_deps( $font_family_handle, $variation_handle ); - - $this->assertArrayNotHasKey( $variation_handle, array_flip( $this->wp_fonts->registered[ $font_family_handle ]->deps ), 'Variation should not be in its font family deps before removal' ); - - $this->wp_fonts->remove_variation( $font_family_handle, $variation_handle ); - - $this->assertNotContains( $variation_handle, $this->wp_fonts->registered[ $font_family_handle ]->deps, 'Variation should not be its font family deps' ); - $this->assertSameSets( $expected['font_family_deps'], array_values( $this->wp_fonts->registered[ $font_family_handle ]->deps ), 'Only the tested variation handle should be removed from font family deps' ); - } - - /** - * Integration test. - * - * @dataProvider data_remove_variations - * - * @param string $font_family_handle Font family for the variation. - * @param string $variation_handle Variation handle to remove. - * @param array $expected Expected results. - */ - public function test_should_remove_variation_from_registered_queue_though_font_family_not_registered( $font_family_handle, $variation_handle, $expected ) { - // Set up the test. - $this->setup_integration_test(); - $this->setup_remove_from_font_family_deps( $font_family_handle, $variation_handle ); - - $this->assertArrayNotHasKey( $variation_handle, array_flip( $this->wp_fonts->registered[ $font_family_handle ]->deps ), 'Variation should not be in its font family deps before removal' ); - - $this->wp_fonts->remove_variation( $font_family_handle, $variation_handle ); - - $this->assertNotContains( $variation_handle, $this->wp_fonts->registered[ $font_family_handle ]->deps, 'Variation should not be its font family deps' ); - $this->assertSameSets( $expected['font_family_deps'], array_values( $this->wp_fonts->registered[ $font_family_handle ]->deps ), 'Only the tested variation handle should be removed from font family deps' ); - } - - /** - * Unit test. - * - * @dataProvider data_remove_variations - * - * @param string $font_family_handle Font family for the variation. - * @param string $variation_handle Variation handle to remove. - * @param array $expected Expected results. - */ - public function test_unit_should_remove_variation_from_queue_and_font_family_deps( $font_family_handle, $variation_handle, $expected ) { - // Set up the test. - $this->setup_unit_test(); - - $this->assertArrayHasKey( $variation_handle, array_flip( $this->wp_fonts->registered[ $font_family_handle ]->deps ), 'Variation should be in its font family deps before removal' ); - - $this->wp_fonts->remove_variation( $font_family_handle, $variation_handle ); - - $this->assertArrayNotHasKey( $variation_handle, $this->wp_fonts->registered, 'Variation should be not be in registered queue' ); - $this->assertNotContains( $variation_handle, $this->wp_fonts->registered[ $font_family_handle ]->deps, 'Variation should not be its font family deps' ); - $this->assertSameSets( $expected['font_family_deps'], array_values( $this->wp_fonts->registered[ $font_family_handle ]->deps ), 'Only the tested variation handle should be removed from font family deps' ); - } - - /** - * Integration test. - * - * @dataProvider data_remove_variations - * - * @param string $font_family_handle Font family for the variation. - * @param string $variation_handle Variation handle to remove. - * @param array $expected Expected results. - */ - public function test_should_remove_variation_from_queue_and_font_family_deps( $font_family_handle, $variation_handle, $expected ) { - // Set up the test. - $this->setup_integration_test(); - - $this->assertArrayHasKey( $variation_handle, array_flip( $this->wp_fonts->registered[ $font_family_handle ]->deps ), 'Variation should be in its font family deps before removal' ); - - $this->wp_fonts->remove_variation( $font_family_handle, $variation_handle ); - - $this->assertArrayNotHasKey( $variation_handle, $this->wp_fonts->registered, 'Variation should be not be in registered queue' ); - $this->assertNotContains( $variation_handle, $this->wp_fonts->registered[ $font_family_handle ]->deps, 'Variation should not be its font family deps' ); - $this->assertSameSets( $expected['font_family_deps'], array_values( $this->wp_fonts->registered[ $font_family_handle ]->deps ), 'Only the tested variation handle should be removed from font family deps' ); - } - - /** - * Remove the variation handle from the font family's deps. - * - * @param string $font_family_handle Font family. - * @param string $variation_handle The variation handle to remove. - */ - private function setup_remove_from_font_family_deps( $font_family_handle, $variation_handle ) { - foreach ( $this->wp_fonts->registered[ $font_family_handle ]->deps as $index => $vhandle ) { - if ( $variation_handle !== $vhandle ) { - continue; - } - unset( $this->wp_fonts->registered[ $font_family_handle ]->deps[ $index ] ); - break; - } - } - - /** - * Removes the variation from the WP_Fonts::$registered queue. - * - * @param string $variation_handle The variation handle to remove. - */ - private function setup_remove_variation_from_registered( $variation_handle ) { - unset( $this->wp_fonts->registered[ $variation_handle ] ); - } -} diff --git a/phpunit/tests/fonts-api/wpFontsProviderLocal.php b/phpunit/tests/fonts-api/wpFontsProviderLocal.php deleted file mode 100644 index f9319390c3b6b..0000000000000 --- a/phpunit/tests/fonts-api/wpFontsProviderLocal.php +++ /dev/null @@ -1,180 +0,0 @@ -provider = new WP_Fonts_Provider_Local(); - - $this->set_up_theme(); - } - - public function tear_down() { - // Restore the original theme directory setup. - $GLOBALS['wp_theme_directories'] = $this->orig_theme_dir; - wp_clean_themes_cache(); - unset( $GLOBALS['wp_themes'] ); - - parent::tear_down(); - } - - /** - * @covers WP_Fonts_Provider_Local::set_fonts - */ - public function test_set_fonts() { - $fonts = array( - 'source-serif-pro-200-900-normal-local' => array( - 'provider' => 'local', - 'font-family' => 'Source Serif Pro', - 'font-style' => 'normal', - 'font-weight' => '200 900', - 'font-stretch' => 'normal', - 'src' => 'https://example.com/assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2', - ), - 'source-serif-pro-200-900-italic-local' => array( - 'provider' => 'local', - 'font-family' => 'Source Serif Pro', - 'font-style' => 'italic', - 'font-weight' => '200 900', - 'font-stretch' => 'normal', - 'src' => 'https://example.com/assets/fonts/source-serif-pro/SourceSerif4Variable-Italic.ttf.woff2', - ), - ); - - $this->provider->set_fonts( $fonts ); - - $property = $this->get_fonts_property(); - $this->assertSame( $fonts, $property->getValue( $this->provider ) ); - } - - /** - * @covers WP_Fonts_Provider_Local::get_css - * - * @dataProvider data_get_css_print_styles - * - * @param array $fonts Prepared fonts (to store in WP_Fonts_Provider_Local::$fonts property). - * @param string $expected Expected CSS. - */ - public function test_get_css( array $fonts, $expected ) { - $property = $this->get_fonts_property(); - $property->setValue( $this->provider, $fonts ); - - $this->assertSame( $expected['font-face-css'], $this->provider->get_css() ); - } - - /** - * @covers WP_Fonts_Provider_Local::print_styles - * - * @dataProvider data_get_css_print_styles - * - * @param array $fonts Prepared fonts (to store in WP_Fonts_Provider_Local::$fonts property). - * @param string $expected Expected CSS. - */ - public function test_print_styles( array $fonts, $expected ) { - $property = $this->get_fonts_property(); - $property->setValue( $this->provider, $fonts ); - - $expected_output = sprintf( $expected['style-element'], $expected['font-face-css'] ); - $this->expectOutputString( $expected_output ); - $this->provider->print_styles(); - } - - /** - * Data provider. - * - * @return array - */ - public function data_get_css_print_styles() { - return array( - 'truetype format' => array( - 'fonts' => array( - 'open-sans-bold-italic-local' => array( - 'provider' => 'local', - 'font-family' => 'Open Sans', - 'font-style' => 'italic', - 'font-weight' => 'bold', - 'src' => 'http://example.org/assets/fonts/OpenSans-Italic-VariableFont_wdth,wght.ttf', - ), - ), - 'expected' => array( - 'style-element' => "\n", - 'font-face-css' => << array( - 'fonts' => array( - 'source-serif-pro-200-900-normal-local' => array( - 'provider' => 'local', - 'font-family' => 'Source Serif Pro', - 'font-style' => 'normal', - 'font-weight' => '200 900', - 'font-stretch' => 'normal', - 'src' => 'http://example.org/assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2', - ), - 'source-serif-pro-400-900-italic-local' => array( - 'provider' => 'local', - 'font-family' => 'Source Serif Pro', - 'font-style' => 'italic', - 'font-weight' => '200 900', - 'font-stretch' => 'normal', - 'src' => 'http://example.org/assets/fonts/source-serif-pro/SourceSerif4Variable-Italic.ttf.woff2', - ), - ), - 'expected' => array( - 'style-element' => "\n", - 'font-face-css' => <<theme_root = realpath( GUTENBERG_DIR_TESTDATA . '/themedir1' ); - $this->orig_theme_dir = $GLOBALS['wp_theme_directories']; - $GLOBALS['wp_theme_directories'] = array( $this->theme_root ); - - $theme_root_callback = function () { - return $this->theme_root; - }; - add_filter( 'theme_root', $theme_root_callback ); - add_filter( 'stylesheet_root', $theme_root_callback ); - add_filter( 'template_root', $theme_root_callback ); - - // Clear caches. - wp_clean_themes_cache(); - unset( $GLOBALS['wp_themes'] ); - } - - private function get_fonts_property() { - $property = new ReflectionProperty( $this->provider, 'fonts' ); - $property->setAccessible( true ); - - return $property; - } -} diff --git a/phpunit/tests/fonts-api/wpFontsResolver/addMissingFontsToThemeJson.php b/phpunit/tests/fonts-api/wpFontsResolver/addMissingFontsToThemeJson.php deleted file mode 100644 index d6e45561e5e33..0000000000000 --- a/phpunit/tests/fonts-api/wpFontsResolver/addMissingFontsToThemeJson.php +++ /dev/null @@ -1,252 +0,0 @@ -assertInstanceOf( WP_Theme_JSON_Gutenberg::class, $actual, 'Instance of WP_Theme_JSON_Gutenberg should be returned' ); - } - - /** - * @dataProvider data_themes - * - * @param string $theme Theme to use. - */ - public function test_should_bail_out_when_no_registered_fonts( $theme ) { - switch_theme( $theme ); - - $data = new WP_Theme_JSON_Gutenberg( self::$theme_json_data[ $theme ] ); - $actual = WP_Fonts_Resolver::add_missing_fonts_to_theme_json( $data ); - - $this->assertEmpty( wp_fonts()->get_registered_font_families(), 'No fonts should be registered in Fonts API' ); - $this->assertSame( $data, $actual, 'Same instance of WP_Theme_JSON_Gutenberg should be returned' ); - } - - /** - * Data Provider. - * - * @return array - */ - public function data_themes() { - return array( - 'no fonts defined' => array( 'block-theme' ), - 'no fonts registered' => array( static::FONTS_THEME ), - ); - } - - /** - * @dataProvider data_should_add_non_theme_json_fonts - * - * @param string $theme Theme to use. - * @param array $fonts Fonts to register. - * @param array $expected Expected fonts to be added. - */ - public function test_should_add_non_theme_json_fonts( $theme, $fonts, $expected ) { - switch_theme( static::FONTS_THEME ); - - // Register the fonts. - wp_register_fonts( $fonts ); - - $data = new WP_Theme_JSON_Gutenberg( self::$theme_json_data[ $theme ] ); - $actual = WP_Fonts_Resolver::add_missing_fonts_to_theme_json( $data ); - - $this->assertNotSame( $data, $actual, 'New instance of WP_Theme_JSON_Gutenberg should be returned' ); - $actual_raw_data = $actual->get_raw_data(); - - $this->assertArrayHasKey( 'typography', $actual_raw_data['settings'] ); - $this->assertArrayHasKey( 'fontFamilies', $actual_raw_data['settings']['typography'] ); - $this->assertArrayHasKey( 'theme', $actual_raw_data['settings']['typography']['fontFamilies'] ); - - $this->assertContains( - $expected, - $actual_raw_data['settings']['typography']['fontFamilies']['theme'], - 'Fonts should be added after running WP_Fonts_Resolver::add_missing_fonts_to_theme_json()' - ); - } - - /** - * Data Provider. - * - * @return array - */ - public function data_should_add_non_theme_json_fonts() { - $lato = array( - 'Lato' => array( - array( - 'font-family' => 'Lato', - 'font-style' => 'normal', - 'font-weight' => '400', - 'src' => 'https://example.com/tests/assets/fonts/lato/Lato-Regular.woff2', - ), - array( - 'font-family' => 'Lato', - 'font-style' => 'italic', - 'font-weight' => '400', - 'src' => 'https://example.com/tests/assets/fonts/lato/Lato-Regular-Italic.woff2', - ), - ), - ); - - $expected_lato = array( - 'fontFamily' => 'Lato', - 'name' => 'Lato', - 'slug' => 'lato', - 'fontFace' => array( - 'lato-400-normal' => array( - 'origin' => 'gutenberg_wp_fonts_api', - 'provider' => 'local', - 'fontFamily' => 'Lato', - 'fontStyle' => 'normal', - 'fontWeight' => '400', - 'fontDisplay' => 'fallback', - 'src' => 'https://example.com/tests/assets/fonts/lato/Lato-Regular.woff2', - ), - 'lato-400-italic' => array( - 'origin' => 'gutenberg_wp_fonts_api', - 'provider' => 'local', - 'fontFamily' => 'Lato', - 'fontStyle' => 'italic', - 'fontWeight' => '400', - 'fontDisplay' => 'fallback', - 'src' => 'https://example.com/tests/assets/fonts/lato/Lato-Regular-Italic.woff2', - ), - ), - ); - - return array( - 'theme with no fonts defined' => array( - 'theme' => 'block-theme', - 'fonts' => $lato, - 'expected' => $expected_lato, - ), - 'theme with fonts: new fonts not in theme' => array( - 'theme' => static::FONTS_THEME, - 'fonts' => $lato, - 'expected' => $expected_lato, - ), - - /* - * @TODO Add these tests fixing https://github.com/WordPress/gutenberg/issues/50047. - * - 'theme with fonts: new variations registered' => array( - 'theme' => static::FONTS_THEME, - 'fonts' => array( - 'DM Sans' => array( - 'dm-sans-500-normal' => array( - 'font-family' => 'DM Sans', - 'font-style' => 'normal', - 'font-weight' => '500', - 'src' => 'https://example.com/tests/assets/fonts/dm-sans/DMSans-Medium.woff2', - ), - 'dm-sans-500-italic' => array( - 'font-family' => 'DM Sans', - 'font-style' => 'italic', - 'font-weight' => '500', - 'src' => 'https://example.com/tests/assets/fonts/dm-sans/DMSans-Medium.woff2', - ), - ), - ), - 'expected' => array( - 'fontFace' => array( - array( - 'fontFamily' => 'DM Sans', - 'fontStretch' => 'normal', - 'fontStyle' => 'normal', - 'fontWeight' => '400', - 'src' => array( 'file:./assets/fonts/dm-sans/DMSans-Regular.woff2' ), - ), - array( - 'fontFamily' => 'DM Sans', - 'fontStretch' => 'normal', - 'fontStyle' => 'italic', - 'fontWeight' => '400', - 'src' => array( 'file:./assets/fonts/dm-sans/DMSans-Regular-Italic.woff2' ), - ), - 'dm-sans-500-normal' => array( - 'origin' => 'gutenberg_wp_fonts_api', - 'provider' => 'local', - 'fontFamily' => 'DM Sans', - 'fontStretch' => 'normal', - 'fontStyle' => 'normal', - 'fontWeight' => '500', - 'fontDisplay' => 'fallback', - 'src' => array( get_stylesheet_directory_uri() . 'assets/fonts/dm-sans/DMSans-Medium.woff2' ), - ), - 'dm-sans-500-italic' => array( - 'origin' => 'gutenberg_wp_fonts_api', - 'provider' => 'local', - 'fontFamily' => 'DM Sans', - 'fontStretch' => 'normal', - 'fontStyle' => 'italic', - 'fontWeight' => '500', - 'fontDisplay' => 'fallback', - 'src' => array( get_stylesheet_directory_uri() . 'assets/fonts/dm-sans/DMSans-Medium-Italic.woff2' ), - ), - array( - 'fontFamily' => 'DM Sans', - 'fontStretch' => 'normal', - 'fontStyle' => 'normal', - 'fontWeight' => '700', - 'src' => array( 'file:./assets/fonts/dm-sans/DMSans-Bold.woff2' ), - ), - array( - 'fontFamily' => 'DM Sans', - 'fontStretch' => 'normal', - 'fontStyle' => 'italic', - 'fontWeight' => '700', - 'src' => array( 'file:./assets/fonts/dm-sans/DMSans-Bold-Italic.woff2' ), - ), - ), - 'fontFamily' => '"DM Sans", sans-serif', - 'name' => 'DM Sans', - 'slug' => 'dm-sans', - ), - ), - */ - ); - } -} diff --git a/phpunit/tests/fonts-api/wpFontsResolver/enqueueUserSelectedFonts.php b/phpunit/tests/fonts-api/wpFontsResolver/enqueueUserSelectedFonts.php deleted file mode 100644 index 9ff01f1c3166c..0000000000000 --- a/phpunit/tests/fonts-api/wpFontsResolver/enqueueUserSelectedFonts.php +++ /dev/null @@ -1,131 +0,0 @@ -user->create( - array( - 'role' => 'administrator', - 'user_email' => 'administrator@example.com', - ) - ); - } - - /** - * @dataProvider data_should_not_enqueue_when_no_user_selected_fonts - * - * @param array $styles Optional. Test styles. Default empty array. - */ - public function test_should_not_enqueue_when_no_user_selected_fonts( $styles = array() ) { - $this->set_up_global_styles( $styles ); - - $mock = $this->set_up_mock( 'enqueue' ); - $mock->expects( $this->never() ) - ->method( 'enqueue' ); - - $expected = array(); - $this->assertSame( $expected, WP_Fonts_Resolver::enqueue_user_selected_fonts() ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_should_not_enqueue_when_no_user_selected_fonts() { - return array( - 'no user-selected styles' => array(), - 'invalid element' => array( - array( - 'elements' => array( - 'invalid' => array( - 'typography' => array( - 'fontFamily' => 'var:preset|font-family|font1', - 'fontStyle' => 'normal', - 'fontWeight' => '400', - ), - ), - ), - ), - ), - ); - } - - /** - * @dataProvider data_should_enqueue_when_user_selected_fonts - * - * @param array $styles Test styles. - * @param array $expected Expected results. - */ - public function test_should_enqueue_when_user_selected_fonts( $styles, $expected ) { - $mock = $this->set_up_mock( 'enqueue' ); - $mock->expects( $this->once() ) - ->method( 'enqueue' ) - ->with( - $this->identicalTo( $expected ) - ); - - $this->set_up_global_styles( $styles ); - - $this->assertSameSets( $expected, WP_Fonts_Resolver::enqueue_user_selected_fonts() ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_should_enqueue_when_user_selected_fonts() { - $global_styles = $this->get_mock_user_selected_fonts_global_styles(); - - return array( - 'heading, caption, text' => array( - 'styles' => $global_styles['font1'], - 'expected' => array( 'font1' ), - ), - 'heading, button' => array( - 'styles' => $global_styles['font2'], - 'expected' => array( 'font2' ), - ), - 'text' => array( - 'styles' => $global_styles['font3'], - 'expected' => array( 'font3' ), - ), - 'all' => array( - 'styles' => $global_styles['all'], - 'expected' => array( - 0 => 'font1', - // font1 occurs 2 more times and gets removed as duplicates. - 3 => 'font2', - 4 => 'font3', - ), - ), - 'all with invalid element' => array( - 'styles' => $global_styles['all with invalid element'], - 'expected' => array( - 0 => 'font1', - // font1 occurs 2 more times and gets removed as duplicates. - 3 => 'font2', - // Skips font2 for the "invalid" element. - 4 => 'font3', - ), - ), - ); - } -} diff --git a/phpunit/tests/fonts-api/wpFontsResolver/registerFontsFromThemeJson.php b/phpunit/tests/fonts-api/wpFontsResolver/registerFontsFromThemeJson.php deleted file mode 100644 index 0186dbf34f3fd..0000000000000 --- a/phpunit/tests/fonts-api/wpFontsResolver/registerFontsFromThemeJson.php +++ /dev/null @@ -1,297 +0,0 @@ - array( - // From theme.json. - 'dm-sans', - 'source-serif-pro', - // From style variation. - 'open-sans', - ), - ); - - public static function set_up_before_class() { - self::$requires_switch_theme_fixtures = true; - - parent::set_up_before_class(); - } - - public function test_should_bails_out_when_no_fonts_defined() { - switch_theme( 'block-theme' ); - - WP_Fonts_Resolver::register_fonts_from_theme_json(); - $wp_fonts = wp_fonts(); - - $this->assertEmpty( $wp_fonts->get_registered() ); - $this->assertEmpty( $wp_fonts->get_enqueued() ); - } - - public function test_should_register_and_enqueue_style_variation_fonts() { - switch_theme( static::FONTS_THEME ); - - WP_Fonts_Resolver::register_fonts_from_theme_json(); - $wp_fonts = wp_fonts(); - - $this->assertContains( 'open-sans', $wp_fonts->get_registered_font_families(), 'Font families should be registered' ); - $this->assertContains( 'open-sans', $wp_fonts->get_enqueued(), 'Font families should be enqueued' ); - } - - /** - * Tests all font families are registered and enqueued. "All" means all font families from - * the theme's theme.json and within the style variations. - */ - public function test_should_register_and_enqueue_all_defined_font_families() { - switch_theme( static::FONTS_THEME ); - - WP_Fonts_Resolver::register_fonts_from_theme_json(); - $wp_fonts = wp_fonts(); - - $expected = static::FONT_FAMILIES[ static::FONTS_THEME ]; - $this->assertSameSetsWithIndex( $expected, $wp_fonts->get_registered_font_families(), 'Font families should be registered' ); - $this->assertSameSetsWithIndex( $expected, $wp_fonts->get_enqueued(), 'Font families should be enqueued' ); - } - - /** - * Test ensures duplicate fonts and variations in the style variations - * are not re-registered. - * - * The Dm Sans fonts are duplicated in the theme's /styles/variations-duplicate-fonts.json. - */ - public function test_should_not_reregister_duplicate_fonts_from_style_variations() { - switch_theme( static::FONTS_THEME ); - - WP_Fonts_Resolver::register_fonts_from_theme_json(); - $wp_fonts = wp_fonts(); - - // Font families are not duplicated. - $this->assertSameSetsWithIndex( - static::FONT_FAMILIES[ static::FONTS_THEME ], - $wp_fonts->get_registered_font_families(), - 'Font families should not be duplicated' - ); - - // Font variations are not duplicated. - $this->assertSameSets( - array( - // From theme.json. - 'dm-sans', - 'dm-sans-400-normal', - 'dm-sans-400-italic', - 'dm-sans-700-normal', - 'dm-sans-700-italic', - 'source-serif-pro', - 'source-serif-pro-200-900-normal', - 'source-serif-pro-200-900-italic', - // From style variation. - 'open-sans', - 'open-sans-400-normal', - 'open-sans-400-italic', - 'dm-sans-500-normal', - 'dm-sans-500-italic', - ), - $wp_fonts->get_registered(), - 'Font families and their variations should not be duplicated' - ); - } - - /** - * @dataProvider data_should_replace_src_file_placeholder - * - * @param string $handle Variation's handle. - * @param string $expected Expected src. - */ - public function test_should_replace_src_file_placeholder( $handle, $expected ) { - switch_theme( static::FONTS_THEME ); - - WP_Fonts_Resolver::register_fonts_from_theme_json(); - - $variation = wp_fonts()->registered[ $handle ]; - $actual = array_pop( $variation->src ); - $expected = get_stylesheet_directory_uri() . $expected; - - $this->assertStringNotContainsString( 'file:./', $actual, 'Font src should not contain the "file:./" placeholder' ); - $this->assertSame( $expected, $actual, 'Font src should be an URL to its file' ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_should_replace_src_file_placeholder() { - return array( - // Theme's theme.json. - 'DM Sans: 400 normal' => array( - 'handle' => 'dm-sans-400-normal', - 'expected' => '/assets/fonts/dm-sans/DMSans-Regular.woff2', - ), - 'DM Sans: 400 italic' => array( - 'handle' => 'dm-sans-400-italic', - 'expected' => '/assets/fonts/dm-sans/DMSans-Regular-Italic.woff2', - ), - 'DM Sans: 700 normal' => array( - 'handle' => 'dm-sans-700-normal', - 'expected' => '/assets/fonts/dm-sans/DMSans-Bold.woff2', - ), - 'DM Sans: 700 italic' => array( - 'handle' => 'dm-sans-700-italic', - 'expected' => '/assets/fonts/dm-sans/DMSans-Bold-Italic.woff2', - ), - 'Source Serif Pro: 200-900 normal' => array( - 'handle' => 'source-serif-pro-200-900-normal', - 'expected' => '/assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2', - ), - 'Source Serif Pro: 200-900 italic' => array( - 'handle' => 'source-serif-pro-200-900-italic', - 'expected' => '/assets/fonts/source-serif-pro/SourceSerif4Variable-Italic.ttf.woff2', - ), - - // Style Variation: variation-with-new-font-family.json. - 'Style Variation: new font-family' => array( - 'handle' => 'open-sans-400-normal', - 'expected' => '/assets/fonts/open-sans/OpenSans-VariableFont_wdth,wght.tff', - ), - 'Style Variation: new font-family italic variation' => array( - 'handle' => 'open-sans-400-italic', - 'expected' => '/assets/fonts/open-sans/OpenSans-Italic-VariableFont_wdth,wght.tff', - ), - - // Style Variation: variation-with-new-variation.json. - 'Style Variation: new medium variation' => array( - 'handle' => 'dm-sans-500-normal', - 'expected' => '/assets/fonts/dm-sans/DMSans-Medium.woff2', - ), - 'Style Variation: new medium italic variation' => array( - 'handle' => 'dm-sans-500-italic', - 'expected' => '/assets/fonts/dm-sans/DMSans-Medium-Italic.woff2', - ), - ); - } - - public function test_should_convert_font_face_properties_into_kebab_case() { - switch_theme( static::FONTS_THEME ); - - WP_Fonts_Resolver::register_fonts_from_theme_json(); - - // Testing only one variation since this theme's fonts use the same properties. - $variation = wp_fonts()->registered['dm-sans-400-normal']; - $actual_properties = $variation->extra['font-properties']; - - $this->assertArrayHasKey( 'font-family', $actual_properties, 'fontFamily should have been converted into font-family' ); - $this->assertArrayNotHasKey( 'fontFamily', $actual_properties, 'fontFamily should not exist.' ); - $this->assertArrayHasKey( 'font-stretch', $actual_properties, 'fontStretch should have been converted into font-stretch' ); - $this->assertArrayNotHasKey( 'fontStretch', $actual_properties, 'fontStretch should not exist' ); - $this->assertArrayHasKey( 'font-style', $actual_properties, 'fontStyle should have been converted into font-style' ); - $this->assertArrayNotHasKey( 'fontStyle', $actual_properties, 'fontStyle should not exist.' ); - $this->assertArrayHasKey( 'font-weight', $actual_properties, 'fontWeight should have been converted into font-weight' ); - $this->assertArrayNotHasKey( 'fontWeight', $actual_properties, 'fontWeight should not exist' ); - } - - /** - * Tests that WP_Fonts_Resolver::register_fonts_from_theme_json() skips fonts that are already registered - * in the Fonts API. How does it do that? Using the 'origin' property when checking each variation. - * This property is added when WP_Theme_JSON_Resolver_Gutenberg::get_merged_data() runs. - * - * To simulate this scenario, a font is registered first, but not enqueued. Then after running, - * it checks if the WP_Fonts_Resolver::register_fonts_from_theme_json() enqueued the font. If no, then - * it was skipped as expected. - */ - public function test_should_skip_registered_fonts() { - switch_theme( static::FONTS_THEME ); - - // Register Lato font. - wp_register_fonts( - array( - 'Lato' => array( - array( - 'font-family' => 'Lato', - 'font-style' => 'normal', - 'font-weight' => '400', - 'src' => 'https://example.com/tests/assets/fonts/lato/Lato-Regular.woff2', - ), - array( - 'font-family' => 'Lato', - 'font-style' => 'italic', - 'font-weight' => '400', - 'src' => 'https://example.com/tests/assets/fonts/lato/Lato-Regular-Italic.woff2', - ), - ), - ) - ); - - // Pre-check to ensure no fonts are enqueued. - $this->assertEmpty( wp_fonts()->get_enqueued(), 'No fonts should be enqueued before running WP_Fonts_Resolver::register_fonts_from_theme_json()' ); - - /* - * When this function runs, it invokes WP_Theme_JSON_Resolver_Gutenberg::get_merged_data(), - * which will include the Lato fonts with a 'origin' property set in each variation. - */ - WP_Fonts_Resolver::register_fonts_from_theme_json(); - - $actual_enqueued_fonts = wp_fonts()->get_enqueued(); - - $this->assertNotContains( 'lato', $actual_enqueued_fonts, 'Lato font-family should not be enqueued' ); - $this->assertSameSets( static::FONT_FAMILIES[ static::FONTS_THEME ], $actual_enqueued_fonts, 'Only the theme font families should be enqueued' ); - } - - public function test_should_skip_when_font_face_not_defined() { - switch_theme( static::FONTS_THEME ); - $expected_font_family = 'source-serif-pro'; - - /** - * Callback that removes the 'fontFace' of the expected font family from the theme's theme.json data. - * This callback is invoked at the start of WP_Fonts_Resolver::register_fonts_from_theme_json() before processing - * within that function. How? It's in the call stack of WP_Theme_JSON_Resolver_Gutenberg::get_merged_data(). - * - * @param WP_Theme_JSON_Data_Gutenberg| WP_Theme_JSON_Data $theme_json_data Instance of the Data object. - * @return WP_Theme_JSON_Data_Gutenberg| WP_Theme_JSON_Data Modified instance. - * @throws ReflectionException - */ - $remove_expected_font_family = static function ( $theme_json_data ) use ( $expected_font_family ) { - // Need to get the underlying data array which is in WP_Theme_JSON_Gutenberg | WP_Theme_JSON object. - $property = new ReflectionProperty( $theme_json_data, 'theme_json' ); - $property->setAccessible( true ); - $theme_json_object = $property->getValue( $theme_json_data ); - - $property = new ReflectionProperty( $theme_json_object, 'theme_json' ); - $property->setAccessible( true ); - $data = $property->getValue( $theme_json_object ); - - // Loop through the fonts to find the expected font-family to modify. - foreach ( $data['settings']['typography']['fontFamilies']['theme'] as $index => $definitions ) { - if ( $expected_font_family !== $definitions['slug'] ) { - continue; - } - - // Remove the 'fontFace' element, which removes the font's variations. - unset( $data['settings']['typography']['fontFamilies']['theme'][ $index ]['fontFace'] ); - break; - } - - $theme_json_data->update_with( $data ); - - return $theme_json_data; - }; - add_filter( 'wp_theme_json_data_theme', $remove_expected_font_family ); - - WP_Fonts_Resolver::register_fonts_from_theme_json(); - - remove_filter( 'wp_theme_json_data_theme', $remove_expected_font_family ); - - $this->assertNotContains( $expected_font_family, wp_fonts()->get_registered_font_families() ); - } -} diff --git a/phpunit/tests/fonts-api/wpFontsUtils/convertFontFamilyIntoHandle.php b/phpunit/tests/fonts-api/wpFontsUtils/convertFontFamilyIntoHandle.php deleted file mode 100644 index 19b2f15c826ed..0000000000000 --- a/phpunit/tests/fonts-api/wpFontsUtils/convertFontFamilyIntoHandle.php +++ /dev/null @@ -1,84 +0,0 @@ -assertSame( $expected, WP_Fonts_Utils::convert_font_family_into_handle( $font_family ) ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_with_valid_input() { - return array( - 'font family single word name' => array( - 'font_family' => 'Merriweather', - 'expected' => 'merriweather', - ), - 'font family multiword name' => array( - 'font_family' => 'Source Sans Pro', - 'expected' => 'source-sans-pro', - ), - 'font family handle delimited by hyphens' => array( - 'font_family' => 'source-serif-pro', - 'expected' => 'source-serif-pro', - ), - 'font family handle delimited by underscore' => array( - 'font_family' => 'source_serif_pro', - 'expected' => 'source_serif_pro', - ), - 'font family handle delimited by hyphens and underscore' => array( - 'font_family' => 'my-custom_font_family', - 'expected' => 'my-custom_font_family', - ), - 'font family handle delimited mixture' => array( - 'font_family' => 'My custom_font-family', - 'expected' => 'my-custom_font-family', - ), - ); - } - - /** - * @dataProvider data_with_invalid_input - * - * @covers WP_Fonts_Utils::convert_font_family_into_handle - * - * @param mixed $invalid_input Invalid input. - */ - public function test_should_not_convert_with_invalid_input( $invalid_input ) { - $this->assertNull( WP_Fonts_Utils::convert_font_family_into_handle( $invalid_input ) ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_with_invalid_input() { - return array( - 'empty string' => array( '' ), - 'integer' => array( 10 ), - 'font family wrapped in an array' => array( array( 'source-serif-pro' ) ), - ); - } -} diff --git a/phpunit/tests/fonts-api/wpFontsUtils/convertVariationIntoHandle.php b/phpunit/tests/fonts-api/wpFontsUtils/convertVariationIntoHandle.php deleted file mode 100644 index 9268aac8ce372..0000000000000 --- a/phpunit/tests/fonts-api/wpFontsUtils/convertVariationIntoHandle.php +++ /dev/null @@ -1,122 +0,0 @@ -assertSame( $expected, WP_Fonts_Utils::convert_variation_into_handle( $font_family, $variation ) ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_with_valid_input() { - return array( - 'with only font-weight' => array( - 'font_family' => 'merriweather', - 'variation' => array( - 'font-weight' => '400', - ), - 'expected' => 'merriweather-400', - ), - 'with no font-style' => array( - 'font_family' => 'source-sans-pro', - 'variation' => array( - 'font-weight' => '200 900', - 'src' => 'https://example.com/assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2', - 'provider' => 'local', - ), - 'expected' => 'source-sans-pro-200-900', - ), - 'with font family name and full variant' => array( - 'font_family' => 'source-sans-pro', - 'variation' => array( - 'provider' => 'local', - 'font-family' => 'Source Serif Pro', - 'font-style' => 'normal', - 'font-weight' => '200 900', - 'font-stretch' => 'normal', - 'src' => 'https://example.com/assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2', - 'font-display' => 'fallback', - ), - 'expected' => 'source-sans-pro-200-900-normal', - ), - ); - } - - /** - * @dataProvider data_with_invalid_input - * - * @param string $font_family Font family to test. - * @param array $invalid_input Variation to test. - */ - public function tests_should_convert_with_invalid_input( $font_family, $invalid_input ) { - $this->expectNotice(); - $this->expectNoticeMessage( 'Variant handle could not be determined as font-weight and/or font-style are require' ); - - $this->assertNull( WP_Fonts_Utils::convert_variation_into_handle( $font_family, $invalid_input ) ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_with_invalid_input() { - return array( - 'with no font-weight or font-style' => array( - 'font_family' => 'merriweather', - 'variation' => array( - 'provider' => 'local', - 'font-stretch' => 'normal', - 'src' => 'https://example.com/assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2', - 'font-display' => 'fallback', - ), - ), - 'with non-string font-weight' => array( - 'font_family' => 'merriweather', - 'variation' => array( - 'font-weight' => 400, - ), - ), - 'with non-string font-style' => array( - 'font_family' => 'merriweather', - 'variation' => array( - 'font-style' => 0, - ), - ), - 'with empty string font-weight' => array( - 'font_family' => 'merriweather', - 'variation' => array( - 'font-weight' => '', - ), - ), - 'with empty string font-style' => array( - 'font_family' => 'merriweather', - 'variation' => array( - 'font-style' => '', - ), - ), - ); - } -} diff --git a/phpunit/tests/fonts-api/wpFontsUtils/getFontFamilyFromVariation.php b/phpunit/tests/fonts-api/wpFontsUtils/getFontFamilyFromVariation.php deleted file mode 100644 index 2b3e3689c4317..0000000000000 --- a/phpunit/tests/fonts-api/wpFontsUtils/getFontFamilyFromVariation.php +++ /dev/null @@ -1,134 +0,0 @@ -assertSame( $expected, WP_Fonts_Utils::get_font_family_from_variation( $variation ) ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_with_valid_variation() { - return array( - 'keyed by font-family' => array( - 'variation' => array( - 'provider' => 'local', - 'font-family' => 'Source Serif Pro', - 'font-style' => 'normal', - 'font-weight' => '200 900', - 'font-stretch' => 'normal', - 'src' => 'https://example.com/assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2', - 'font-display' => 'fallback', - ), - 'expected' => 'Source Serif Pro', - ), - 'keyed by fontFamily and as a handle' => array( - 'variation' => array( - 'fontFamily' => 'source-sans-pro', - 'font-weight' => '200 900', - 'src' => 'https://example.com/assets/fonts/source-sans-pro/source-sans-pro.ttf.woff2', - 'provider' => 'local', - ), - 'expected' => 'source-sans-pro', - ), - 'with font family name and full variant' => array( - 'variation' => array( - 'provider' => 'local', - 'font-family' => 'Merriweather', - 'font-style' => 'normal', - 'font-weight' => '400 600', - 'font-stretch' => 'normal', - 'src' => 'https://example.com/assets/fonts/merriweather.ttf.woff2', - 'font-display' => 'fallback', - ), - 'expected' => 'Merriweather', - ), - ); - } - - /** - * @dataProvider data_with_invalid_input - * - * @param array $invalid_variation Variation to test. - * @param string $expected_message Expected notice message. - */ - public function test_with_invalid_input( array $invalid_variation, $expected_message ) { - $this->expectNotice(); - $this->expectNoticeMessage( $expected_message ); - - $this->assertNull( WP_Fonts_Utils::get_font_family_from_variation( $invalid_variation ) ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_with_invalid_input() { - return array( - 'keyed with underscore' => array( - 'variation' => array( - 'provider' => 'local', - 'font_family' => 'Source Serif Pro', - 'font-style' => 'normal', - 'font-weight' => '200 900', - 'font-stretch' => 'normal', - 'src' => 'https://example.com/assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2', - 'font-display' => 'fallback', - ), - 'expected_message' => 'Font family not found.', - ), - 'keyed with space' => array( - 'variation' => array( - 'font family' => 'Source Sans Pro', - 'font-weight' => '200 900', - 'src' => 'https://example.com/assets/fonts/source-sans-pro/source-sans-pro.ttf.woff2', - 'provider' => 'local', - ), - 'expected_message' => 'Font family not found.', - ), - 'fontFamily => empty string' => array( - 'variation' => array( - 'fontFamily' => '', - 'font-weight' => '200 900', - 'src' => 'https://example.com/assets/fonts/source-sans-pro/source-sans-pro.ttf.woff2', - 'provider' => 'local', - ), - 'expected_message' => 'Font family not defined in the variation.', - ), - 'font-family => empty string' => array( - 'variation' => array( - 'provider' => 'local', - 'font-family' => '', - 'font-style' => 'normal', - 'font-weight' => '200 900', - 'font-stretch' => 'normal', - 'src' => 'https://example.com/assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2', - 'font-display' => 'fallback', - ), - 'expected_message' => 'Font family not defined in the variation.', - ), - ); - } -} diff --git a/phpunit/tests/fonts-api/wpFontsUtils/isDefined.php b/phpunit/tests/fonts-api/wpFontsUtils/isDefined.php deleted file mode 100644 index 3ae48ad52671a..0000000000000 --- a/phpunit/tests/fonts-api/wpFontsUtils/isDefined.php +++ /dev/null @@ -1,61 +0,0 @@ -assertTrue( WP_Fonts_Utils::is_defined( $input ) ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_when_defined() { - return array( - 'name: non empty string' => array( 'Some Font Family' ), - 'handle: non empty string' => array( 'some-font-family' ), - ); - } - - /** - * @dataProvider data_when_not_defined - * - * @param mixed $invalid_input Input to test. - */ - public function test_should_return_false_when_not_defined( $invalid_input ) { - $this->assertFalse( WP_Fonts_Utils::is_defined( $invalid_input ) ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_when_not_defined() { - return array( - 'empty string' => array( '' ), - 'string 0' => array( '0' ), - 'integer' => array( 10 ), - 'name wrapped in an array' => array( array( 'Some Font Family' ) ), - 'handle wrapped in an array' => array( array( 'some-font-family' ) ), - ); - } -} diff --git a/phpunit/tests/fonts-api/wpPrintFonts.php b/phpunit/tests/fonts-api/wpPrintFonts.php deleted file mode 100644 index 40b416aa56421..0000000000000 --- a/phpunit/tests/fonts-api/wpPrintFonts.php +++ /dev/null @@ -1,230 +0,0 @@ -assertSame( array(), wp_print_fonts() ); - } - - /** - * Unit test which mocks WP_Fonts methods. - * - * @dataProvider data_mocked_handles - * - * @param string|string[] $handles Handles to test. - */ - public function test_should_return_mocked_handles( $handles ) { - $mock = $this->set_up_mock( array( 'get_registered_font_families', 'do_items' ) ); - $mock->expects( $this->once() ) - ->method( 'get_registered_font_families' ) - ->will( $this->returnValue( $handles ) ); - - $mock->expects( $this->once() ) - ->method( 'do_items' ) - ->with( - $this->identicalTo( $handles ) - ) - ->will( $this->returnValue( $handles ) ); - - wp_print_fonts( $handles ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_mocked_handles() { - return array( - 'font family' => array( - array( 'my-custom-font' ), - ), - 'multiple font families' => array( - array( - 'font1', - 'font2', - ), - ), - ); - } - - /** - * Integration test that registers providers and fonts and then enqueues before - * testing the printing functionality. - * - * @dataProvider data_print_enqueued - * - * @param array $setup Test set up information for provider, fonts, and enqueued. - * @param array $expected_done Expected array of printed handles. - * @param string $expected_output Expected printed output. - */ - public function test_should_print_enqueued( $setup, $expected_done, $expected_output ) { - $wp_fonts = wp_fonts(); - - $this->setup_integrated_deps( $setup, $wp_fonts ); - - $this->expectOutputString( $expected_output ); - $actual_done = wp_print_fonts(); - $this->assertSameSets( $expected_done, $actual_done, 'Printed handles should match' ); - } - - /** - * Integration test to validate printing given handles. Rather than mocking internal functionality, - * it registers providers and fonts but does not enqueue. - * - * @dataProvider data_print_enqueued - * - * @param array $setup Test set up information for provider, fonts, and enqueued. - * @param array $expected_done Expected array of printed handles. - * @param string $expected_output Expected printed output. - */ - public function test_should_print_handles_when_not_enqueued( $setup, $expected_done, $expected_output ) { - $wp_fonts = wp_fonts(); - - $this->setup_integrated_deps( $setup, $wp_fonts, false ); - // Do not enqueue. Instead, pass the handles to wp_print_fonts(). - $handles = $setup['enqueued']; - $this->assertEmpty( $wp_fonts->queue, 'No fonts should be enqueued' ); - - $this->expectOutputString( $expected_output ); - $actual_done = wp_print_fonts( $handles ); - $this->assertSameSets( $expected_done, $actual_done, 'Printed handles should match' ); - } - - /** - * @dataProvider data_should_print_all_registered_fonts_for_iframed_editor - * - * @param string $fonts Fonts to register. - * @param array $expected Expected results. - */ - public function test_should_print_all_registered_fonts_for_iframed_editor( $fonts, $expected ) { - wp_register_fonts( $fonts ); - - $this->expectOutputString( $expected['output'] ); - $actual_done = wp_print_fonts( true ); - $this->assertSameSets( $expected['done'], $actual_done, 'All registered font-family handles should be returned' ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_should_print_all_registered_fonts_for_iframed_editor() { - $local_fonts = $this->get_registered_local_fonts(); - $font_faces = $this->get_registered_fonts_css(); - - return array( - 'Merriweather with 1 variation' => array( - 'fonts' => array( 'merriweather' => $local_fonts['merriweather'] ), - 'expected' => array( - 'done' => array( 'merriweather', 'merriweather-200-900-normal' ), - 'output' => sprintf( - "\n", - $font_faces['merriweather-200-900-normal'] - ), - ), - ), - 'Source Serif Pro with 2 variations' => array( - 'fonts' => array( 'Source Serif Pro' => $local_fonts['Source Serif Pro'] ), - 'expected' => array( - 'done' => array( 'source-serif-pro', 'Source Serif Pro-300-normal', 'Source Serif Pro-900-italic' ), - 'output' => sprintf( - "\n", - $font_faces['Source Serif Pro-300-normal'], - $font_faces['Source Serif Pro-900-italic'] - ), - ), - ), - 'all fonts' => array( - 'fonts' => $local_fonts, - 'expected' => array( - 'done' => array( - 'merriweather', - 'merriweather-200-900-normal', - 'source-serif-pro', - 'Source Serif Pro-300-normal', - 'Source Serif Pro-900-italic', - ), - 'output' => sprintf( - "\n", - $font_faces['merriweather-200-900-normal'], - $font_faces['Source Serif Pro-300-normal'], - $font_faces['Source Serif Pro-900-italic'] - ), - ), - ), - ); - } - - /** - * Integration test for printing user-selected global fonts. - * This test registers providers and fonts and then enqueues before testing the printing functionality. - * - * @dataProvider data_print_user_selected_fonts - * - * @param array $global_styles Test set up information for provider, fonts, and enqueued. - * @param array $expected_done Expected array of printed handles. - * @param string $expected_output Expected printed output. - */ - public function test_should_print_user_selected_fonts( $global_styles, $expected_done, $expected_output ) { - $wp_fonts = wp_fonts(); - - $setup = array( - 'provider' => array( 'mock' => $this->get_provider_definitions( 'mock' ) ), - 'registered' => $this->get_registered_mock_fonts(), - 'global_styles' => $global_styles, - ); - $this->setup_integrated_deps( $setup, $wp_fonts, false ); - - $this->expectOutputString( $expected_output ); - $actual_printed_fonts = wp_print_fonts(); - $this->assertSameSets( $expected_done, $actual_printed_fonts, 'Should print font-faces for given user-selected fonts' ); - } - - - /** - * Sets up the dependencies for integration test. - * - * @param array $setup Dependencies to set up. - * @param WP_Fonts $wp_fonts Instance of WP_Fonts. - * @param bool $enqueue Whether to enqueue. Default true. - */ - private function setup_integrated_deps( array $setup, $wp_fonts, $enqueue = true ) { - foreach ( $setup['provider'] as $provider ) { - $wp_fonts->register_provider( $provider['id'], $provider['class'] ); - } - foreach ( $setup['registered'] as $handle => $variations ) { - $this->setup_register( $handle, $variations, $wp_fonts ); - } - - if ( $enqueue ) { - $wp_fonts->enqueue( $setup['enqueued'] ); - } - - if ( ! empty( $setup['global_styles'] ) ) { - $this->set_up_global_styles( $setup['global_styles'] ); - } - } -} diff --git a/phpunit/tests/fonts-api/wpRegisterFontProvider.php b/phpunit/tests/fonts-api/wpRegisterFontProvider.php deleted file mode 100644 index 907355bdc91c8..0000000000000 --- a/phpunit/tests/fonts-api/wpRegisterFontProvider.php +++ /dev/null @@ -1,95 +0,0 @@ -set_up_mock( 'register_provider' ); - $mock->expects( $this->once() ) - ->method( 'register_provider' ) - ->with( - $this->identicalTo( $provider_id ), - $this->identicalTo( $class_name ) - ) - ->will( $this->returnValue( true ) ); - - $this->assertTrue( wp_register_font_provider( $provider_id, $class_name ), 'wp_register_font_provider() should return true' ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_register_providers() { - return array( - 'mock' => array( - 'provider_id' => 'mock', - 'class' => Mock_Provider::class, - ), - 'local' => array( - 'provider_id' => 'local', - 'class' => WP_Fonts_Provider_Local::class, - ), - ); - } - - /** - * @dataProvider data_invalid_providers - * - * @param string $provider_id Provider ID. - * @param string $class_name Provider class name. - */ - public function test_should_not_register( $provider_id, $class_name ) { - $mock = $this->set_up_mock( 'register_provider' ); - $mock->expects( $this->once() ) - ->method( 'register_provider' ) - ->with( - $this->identicalTo( $provider_id ), - $this->identicalTo( $class_name ) - ) - ->will( $this->returnValue( false ) ); - - $this->assertFalse( wp_register_font_provider( $provider_id, $class_name ), 'wp_register_font_provider() should return false' ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_invalid_providers() { - return array( - 'provider_id is empty' => array( - 'provider_id' => '', - 'class' => Mock_Provider::class, - ), - 'class is empty' => array( - 'provider_id' => 'local', - 'class' => '', - ), - 'class does not exist' => array( - 'provider_id' => 'doesnotexist', - 'class' => 'Provider_Does_Not_Exist', - ), - ); - } -} diff --git a/phpunit/tests/fonts-api/wpRegisterFonts.php b/phpunit/tests/fonts-api/wpRegisterFonts.php deleted file mode 100644 index c57c1406a6cac..0000000000000 --- a/phpunit/tests/fonts-api/wpRegisterFonts.php +++ /dev/null @@ -1,104 +0,0 @@ -assertSame( $expected['wp_register_fonts'], $actual, 'Font family handle(s) should be returned' ); - $this->assertSame( $expected['get_registered'], $this->get_registered_handles(), 'Web fonts should match registered queue' ); - } - - /** - * @dataProvider data_fonts - * - * @param array $fonts Array of fonts to test. - */ - public function test_should_not_enqueue_on_registration( array $fonts ) { - wp_register_fonts( $fonts ); - $this->assertEmpty( $this->get_enqueued_handles() ); - } - - /** - * Data provider. - * - * @return array - */ - public function data_fonts() { - return array( - 'font family keyed with slug' => array( - 'fonts' => array( - 'source-serif-pro' => array( - array( - 'provider' => 'local', - 'font-family' => 'Source Serif Pro', - 'font-style' => 'normal', - 'font-weight' => '200 900', - 'font-stretch' => 'normal', - 'src' => 'https://example.com/assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2', - 'font-display' => 'fallback', - ), - ), - ), - 'expected' => array( - 'wp_register_fonts' => array( 'source-serif-pro' ), - 'get_registered' => array( - 'source-serif-pro', - 'source-serif-pro-200-900-normal', - ), - ), - ), - 'font family keyed with name' => array( - 'fonts' => array( - 'Source Serif Pro' => array( - array( - 'provider' => 'local', - 'font-family' => 'Source Serif Pro', - 'font-style' => 'normal', - 'font-weight' => '200 900', - 'font-stretch' => 'normal', - 'src' => 'https://example.com/assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2', - 'font-display' => 'fallback', - ), - array( - 'provider' => 'local', - 'font-family' => 'Source Serif Pro', - 'font-style' => 'italic', - 'font-weight' => '200 900', - 'font-stretch' => 'normal', - 'src' => 'https://example.com/assets/fonts/source-serif-pro/SourceSerif4Variable-Italic.ttf.woff2', - 'font-display' => 'fallback', - ), - ), - ), - 'expected' => array( - 'wp_register_fonts' => array( 'source-serif-pro' ), - 'get_registered' => array( - 'source-serif-pro', - 'source-serif-pro-200-900-normal', - 'source-serif-pro-200-900-italic', - ), - ), - ), - ); - } -} diff --git a/test/e2e/specs/editor/various/list-view.spec.js b/test/e2e/specs/editor/various/list-view.spec.js index 674801cf94aba..00f21b4e51c5e 100644 --- a/test/e2e/specs/editor/various/list-view.spec.js +++ b/test/e2e/specs/editor/various/list-view.spec.js @@ -53,11 +53,40 @@ test.describe( 'List View', () => { name: 'Paragraph', exact: true, } ); + const imageBlockItem = listView.getByRole( 'gridcell', { + name: 'Image', + exact: true, + } ); const headingBlockItem = listView.getByRole( 'gridcell', { name: 'Heading', exact: true, } ); - await paragraphBlockItem.dragTo( headingBlockItem, { x: 0, y: 0 } ); + + await paragraphBlockItem.hover(); + await page.mouse.down(); + + // To work around a drag and drop bug in Safari, the list view applies + // `pointer-events: none` to the list view while dragging, so that + // `onDragLeave` is not fired when dragging within the list view. + // Without the `force: true` option, the `hover` action will fail + // as playwright will complain that pointer-events are intercepted. + // https://bugs.webkit.org/show_bug.cgi?id=66547 + // See: https://github.com/WordPress/gutenberg/pull/56625 + + // Hover over each block to mimic moving up the list view. + // Also, hover twice to ensure a dragover event is dispatched. + // See: https://playwright.dev/docs/input#dragging-manually + await imageBlockItem.hover( { force: true } ); + await imageBlockItem.hover( { force: true } ); + await headingBlockItem.hover( { force: true } ); + await headingBlockItem.hover( { force: true } ); + + // Disable reason: Need to wait until the throttle timeout of 250ms has passed. + /* eslint-disable playwright/no-wait-for-timeout */ + await editor.page.waitForTimeout( 300 ); + /* eslint-enable playwright/no-wait-for-timeout */ + + await page.mouse.up(); // Ensure the block was dropped correctly. await expect diff --git a/test/e2e/specs/interactivity/directive-each.spec.ts b/test/e2e/specs/interactivity/directive-each.spec.ts new file mode 100644 index 0000000000000..4f024b1f828a9 --- /dev/null +++ b/test/e2e/specs/interactivity/directive-each.spec.ts @@ -0,0 +1,486 @@ +/** + * Internal dependencies + */ +import { test, expect } from './fixtures'; + +test.describe( 'data-wp-each', () => { + test.beforeAll( async ( { interactivityUtils: utils } ) => { + await utils.activatePlugins(); + await utils.addPostWithBlock( 'test/directive-each' ); + } ); + + test.beforeEach( async ( { interactivityUtils: utils, page } ) => { + await page.goto( utils.getLink( 'test/directive-each' ) ); + } ); + + test.afterAll( async ( { interactivityUtils: utils } ) => { + await utils.deactivatePlugins(); + await utils.deleteAllPosts(); + } ); + + test( 'should use `item` as the defaul item name in the context', async ( { + page, + } ) => { + const elements = page.getByTestId( 'letters' ).getByTestId( 'item' ); + await expect( elements ).toHaveText( [ 'A', 'B', 'C' ] ); + } ); + + test( 'should use the specified item name in the context', async ( { + page, + } ) => { + const elements = page.getByTestId( 'fruits' ).getByTestId( 'item' ); + await expect( elements ).toHaveText( [ + 'avocado', + 'banana', + 'cherimoya', + ] ); + } ); + + test.describe( 'without `wp-each-key`', () => { + test.beforeEach( async ( { page } ) => { + const elements = page.getByTestId( 'fruits' ).getByTestId( 'item' ); + + // These tags are included to check that the elements are not unmounted + // and mounted again. If an element remounts, its tag should be missing. + await elements.evaluateAll( ( refs ) => + refs.forEach( ( ref, index ) => { + if ( ref instanceof HTMLElement ) { + ref.dataset.tag = `${ index }`; + } + } ) + ); + } ); + + test( 'should preserve elements on deletion', async ( { page } ) => { + const elements = page.getByTestId( 'fruits' ).getByTestId( 'item' ); + + // An item is removed when clicked. + await elements.first().click(); + + await expect( elements ).toHaveText( [ 'banana', 'cherimoya' ] ); + await expect( elements.getByText( 'avocado' ) ).toBeHidden(); + + // Get the tags. They should not have disappeared. + const [ banana, cherimoya ] = await elements.all(); + await expect( banana ).toHaveAttribute( 'data-tag', '1' ); + await expect( cherimoya ).toHaveAttribute( 'data-tag', '2' ); + } ); + + test( 'should preserve elements on reordering', async ( { page } ) => { + const elements = page.getByTestId( 'fruits' ).getByTestId( 'item' ); + + await page.getByTestId( 'fruits' ).getByTestId( 'rotate' ).click(); + + await expect( elements ).toHaveText( [ + 'cherimoya', + 'avocado', + 'banana', + ] ); + + // Get the tags. They should not have disappeared or changed. + const [ cherimoya, avocado, banana ] = await elements.all(); + await expect( cherimoya ).toHaveAttribute( 'data-tag', '2' ); + await expect( avocado ).toHaveAttribute( 'data-tag', '0' ); + await expect( banana ).toHaveAttribute( 'data-tag', '1' ); + } ); + + test( 'should preserve elements on addition', async ( { page } ) => { + const elements = page.getByTestId( 'fruits' ).getByTestId( 'item' ); + + await page.getByTestId( 'fruits' ).getByTestId( 'add' ).click(); + + await expect( elements ).toHaveText( [ + 'ananas', + 'avocado', + 'banana', + 'cherimoya', + ] ); + + // Get the tags. They should not have disappeared or changed, + // except for the newly created element. + const [ ananas, avocado, banana, cherimoya ] = await elements.all(); + await expect( ananas ).not.toHaveAttribute( 'data-tag' ); + await expect( avocado ).toHaveAttribute( 'data-tag', '0' ); + await expect( banana ).toHaveAttribute( 'data-tag', '1' ); + await expect( cherimoya ).toHaveAttribute( 'data-tag', '2' ); + } ); + + test( 'should preserve elements on replacement', async ( { page } ) => { + const elements = page.getByTestId( 'fruits' ).getByTestId( 'item' ); + + await page.getByTestId( 'fruits' ).getByTestId( 'replace' ).click(); + + await expect( elements ).toHaveText( [ + 'ananas', + 'banana', + 'cherimoya', + ] ); + + // Get the tags. They should not have disappeared or changed, + // except for the newly created element. + const [ ananas, banana, cherimoya ] = await elements.all(); + await expect( ananas ).not.toHaveAttribute( 'data-tag' ); + await expect( banana ).toHaveAttribute( 'data-tag', '1' ); + await expect( cherimoya ).toHaveAttribute( 'data-tag', '2' ); + } ); + } ); + + test.describe( 'with `wp-each-key`', () => { + test.beforeEach( async ( { page } ) => { + const elements = page.getByTestId( 'books' ).getByTestId( 'item' ); + + // These tags are included to check that the elements are not unmounted + // and mounted again. If an element remounts, its tag should be missing. + await elements.evaluateAll( ( refs ) => + refs.forEach( ( ref, index ) => { + if ( ref instanceof HTMLElement ) { + ref.dataset.tag = `${ index }`; + } + } ) + ); + } ); + + test( 'should preserve elements on deletion', async ( { page } ) => { + const elements = page.getByTestId( 'books' ).getByTestId( 'item' ); + + await expect( elements ).toHaveText( [ + 'A Game of Thrones', + 'A Clash of Kings', + 'A Storm of Swords', + ] ); + + // An item is removed when clicked. + await elements.first().click(); + + await expect( elements ).toHaveText( [ + 'A Clash of Kings', + 'A Storm of Swords', + ] ); + + // Get the tags. They should not have disappeared. + const [ acok, asos ] = await elements.all(); + await expect( acok ).toHaveAttribute( 'data-tag', '1' ); + await expect( asos ).toHaveAttribute( 'data-tag', '2' ); + } ); + + test( 'should preserve elements on reordering', async ( { page } ) => { + const elements = page.getByTestId( 'books' ).getByTestId( 'item' ); + + await page.getByTestId( 'books' ).getByTestId( 'rotate' ).click(); + + await expect( elements ).toHaveText( [ + 'A Storm of Swords', + 'A Game of Thrones', + 'A Clash of Kings', + ] ); + + // Get the tags. They should not have disappeared or changed. + const [ asos, agot, acok ] = await elements.all(); + await expect( asos ).toHaveAttribute( 'data-tag', '2' ); + await expect( agot ).toHaveAttribute( 'data-tag', '0' ); + await expect( acok ).toHaveAttribute( 'data-tag', '1' ); + } ); + + test( 'should preserve elements on addition', async ( { page } ) => { + const elements = page.getByTestId( 'books' ).getByTestId( 'item' ); + + await page.getByTestId( 'books' ).getByTestId( 'add' ).click(); + + await expect( elements ).toHaveText( [ + 'A Feast for Crows', + 'A Game of Thrones', + 'A Clash of Kings', + 'A Storm of Swords', + ] ); + + // Get the tags. They should not have disappeared or changed, + // except for the newly created element. + const [ affc, agot, acok, asos ] = await elements.all(); + await expect( affc ).not.toHaveAttribute( 'data-tag' ); + await expect( agot ).toHaveAttribute( 'data-tag', '0' ); + await expect( acok ).toHaveAttribute( 'data-tag', '1' ); + await expect( asos ).toHaveAttribute( 'data-tag', '2' ); + } ); + + test( 'should preserve elements on replacement', async ( { page } ) => { + const elements = page.getByTestId( 'books' ).getByTestId( 'item' ); + + await page.getByTestId( 'books' ).getByTestId( 'replace' ).click(); + + await expect( elements ).toHaveText( [ + 'A Feast for Crows', + 'A Clash of Kings', + 'A Storm of Swords', + ] ); + + // Get the tags. They should not have disappeared or changed, + // except for the newly created element. + const [ affc, acok, asos ] = await elements.all(); + await expect( affc ).not.toHaveAttribute( 'data-tag' ); + await expect( acok ).toHaveAttribute( 'data-tag', '1' ); + await expect( asos ).toHaveAttribute( 'data-tag', '2' ); + } ); + + test( 'should preserve elements on modification', async ( { + page, + } ) => { + const elements = page.getByTestId( 'books' ).getByTestId( 'item' ); + + await page.getByTestId( 'books' ).getByTestId( 'modify' ).click(); + + await expect( elements ).toHaveText( [ + 'A GAME OF THRONES', + 'A Clash of Kings', + 'A Storm of Swords', + ] ); + + // Get the tags. They should not have disappeared or changed. + const [ agot, acok, asos ] = await elements.all(); + await expect( agot ).toHaveAttribute( 'data-tag', '0' ); + await expect( acok ).toHaveAttribute( 'data-tag', '1' ); + await expect( asos ).toHaveAttribute( 'data-tag', '2' ); + } ); + } ); + + test( 'should respect elements after', async ( { page } ) => { + const elements = page.getByTestId( 'numbers' ).getByTestId( 'item' ); + await expect( elements ).toHaveText( [ '1', '2', '3', '4' ] ); + await page.getByTestId( 'numbers' ).getByTestId( 'shift' ).click(); + await expect( elements ).toHaveText( [ '2', '3', '4' ] ); + await page + .getByTestId( 'numbers' ) + .getByTestId( 'unshift' ) + .click( { clickCount: 2 } ); + await expect( elements ).toHaveText( [ '0', '1', '2', '3', '4' ] ); + } ); + + test( 'should support initial empty lists', async ( { page } ) => { + const elements = page.getByTestId( 'empty' ).getByTestId( 'item' ); + await expect( elements ).toHaveText( [ 'item X' ] ); + await page + .getByTestId( 'empty' ) + .getByTestId( 'add' ) + .click( { clickCount: 2 } ); + + await expect( elements ).toHaveText( [ 'item 0', 'item 1', 'item X' ] ); + } ); + + test( 'should support multiple siblings inside the template', async ( { + page, + } ) => { + const elements = page.getByTestId( 'siblings' ).getByTestId( 'item' ); + await expect( elements ).toHaveText( [ + 'two', + '2', + 'three', + '3', + 'four', + '4', + ] ); + await page.getByTestId( 'siblings' ).getByTestId( 'unshift' ).click(); + await expect( elements ).toHaveText( [ + 'one', + '1', + 'two', + '2', + 'three', + '3', + 'four', + '4', + ] ); + } ); + + test( 'should work on navigation', async ( { page } ) => { + const elements = page + .getByTestId( 'navigation-updated list' ) + .getByTestId( 'item' ); + + // These tags are included to check that the elements are not unmounted + // and mounted again. If an element remounts, its tag should be missing. + await elements.evaluateAll( ( refs ) => + refs.forEach( ( ref, index ) => { + if ( ref instanceof HTMLElement ) { + ref.dataset.tag = `${ index }`; + } + } ) + ); + + await expect( elements ).toHaveText( [ 'beta', 'gamma', 'delta' ] ); + + await page + .getByTestId( 'navigation-updated list' ) + .getByTestId( 'navigate' ) + .click(); + + await expect( elements ).toHaveText( [ + 'alpha', + 'beta', + 'gamma', + 'delta', + ] ); + + // Get the tags. They should not have disappeared or changed, + // except for the newly created element. + const [ alpha, beta, gamma, delta ] = await elements.all(); + await expect( alpha ).not.toHaveAttribute( 'data-tag' ); + await expect( beta ).toHaveAttribute( 'data-tag', '0' ); + await expect( gamma ).toHaveAttribute( 'data-tag', '1' ); + await expect( delta ).toHaveAttribute( 'data-tag', '2' ); + } ); + + test( 'should work with nested lists', async ( { page } ) => { + const mainElement = page.getByTestId( 'nested' ); + + // These tags are included to check that the elements are not unmounted + // and mounted again. If an element remounts, its tag should be missing. + const listItems = mainElement.getByRole( 'listitem' ); + await listItems.evaluateAll( ( refs ) => + refs.forEach( ( ref, index ) => { + if ( ref instanceof HTMLElement ) { + ref.dataset.tag = `${ index }`; + } + } ) + ); + + const animals = mainElement.getByTestId( 'animal' ); + + { + // Ensure it hydrates correctly. + const [ dog, cat ] = await animals.all(); + await expect( dog.getByTestId( 'name' ) ).toHaveText( 'Dog' ); + await expect( dog.getByRole( 'listitem' ) ).toHaveText( [ + 'chihuahua', + 'rottweiler', + ] ); + await expect( cat.getByTestId( 'name' ) ).toHaveText( 'Cat' ); + await expect( cat.getByRole( 'listitem' ) ).toHaveText( [ + 'sphynx', + 'siamese', + ] ); + } + + await mainElement.getByTestId( 'add animal' ).click(); + + { + // Ensure it works when the top list is modified. + const [ rat, dog, cat ] = await animals.all(); + await expect( rat.getByTestId( 'name' ) ).toHaveText( 'Rat' ); + await expect( rat.getByRole( 'listitem' ) ).toHaveText( [ + 'dumbo', + 'rex', + ] ); + await expect( dog.getByTestId( 'name' ) ).toHaveText( 'Dog' ); + await expect( dog.getByRole( 'listitem' ) ).toHaveText( [ + 'chihuahua', + 'rottweiler', + ] ); + await expect( cat.getByTestId( 'name' ) ).toHaveText( 'Cat' ); + await expect( cat.getByRole( 'listitem' ) ).toHaveText( [ + 'sphynx', + 'siamese', + ] ); + await expect( rat ).not.toHaveAttribute( 'data-tag' ); + const [ d1, d2 ] = await dog.getByRole( 'listitem' ).all(); + await expect( dog ).toHaveAttribute( 'data-tag', '0' ); + await expect( d1 ).toHaveAttribute( 'data-tag', '1' ); + await expect( d2 ).toHaveAttribute( 'data-tag', '2' ); + const [ c1, c2 ] = await cat.getByRole( 'listitem' ).all(); + await expect( cat ).toHaveAttribute( 'data-tag', '3' ); + await expect( c1 ).toHaveAttribute( 'data-tag', '4' ); + await expect( c2 ).toHaveAttribute( 'data-tag', '5' ); + } + + // Reset tags so the added elements have one. + await listItems.evaluateAll( ( refs ) => + refs.forEach( ( ref, index ) => { + if ( ref instanceof HTMLElement ) { + ref.dataset.tag = `${ index }`; + } + } ) + ); + + await mainElement.getByTestId( 'add breeds' ).click(); + + { + // Ensure it works when the top list is modified. + const [ rat, dog, cat ] = await animals.all(); + await expect( rat.getByTestId( 'name' ) ).toHaveText( 'Rat' ); + await expect( rat.getByRole( 'listitem' ) ).toHaveText( [ + 'satin', + 'dumbo', + 'rex', + ] ); + await expect( dog.getByTestId( 'name' ) ).toHaveText( 'Dog' ); + await expect( dog.getByRole( 'listitem' ) ).toHaveText( [ + 'german shepherd', + 'chihuahua', + 'rottweiler', + ] ); + await expect( cat.getByTestId( 'name' ) ).toHaveText( 'Cat' ); + await expect( cat.getByRole( 'listitem' ) ).toHaveText( [ + 'maine coon', + 'sphynx', + 'siamese', + ] ); + const [ r1, r2, r3 ] = await rat.getByRole( 'listitem' ).all(); + await expect( rat ).toHaveAttribute( 'data-tag', '0' ); + await expect( r1 ).not.toHaveAttribute( 'data-tag' ); + await expect( r2 ).toHaveAttribute( 'data-tag', '1' ); + await expect( r3 ).toHaveAttribute( 'data-tag', '2' ); + const [ d1, d2, d3 ] = await dog.getByRole( 'listitem' ).all(); + await expect( dog ).toHaveAttribute( 'data-tag', '3' ); + await expect( d1 ).not.toHaveAttribute( 'data-tag' ); + await expect( d2 ).toHaveAttribute( 'data-tag', '4' ); + await expect( d3 ).toHaveAttribute( 'data-tag', '5' ); + const [ c1, c2, c3 ] = await cat.getByRole( 'listitem' ).all(); + await expect( cat ).toHaveAttribute( 'data-tag', '6' ); + await expect( c1 ).not.toHaveAttribute( 'data-tag' ); + await expect( c2 ).toHaveAttribute( 'data-tag', '7' ); + await expect( c3 ).toHaveAttribute( 'data-tag', '8' ); + } + } ); + + test( 'should do nothing when used on non-template elements', async ( { + page, + } ) => { + const elements = page + .getByTestId( 'invalid tag' ) + .getByTestId( 'item' ); + + await expect( elements ).toHaveCount( 1 ); + await expect( elements ).toBeEmpty(); + } ); + + test( 'should work with derived state as keys', async ( { page } ) => { + const elements = page + .getByTestId( 'derived state' ) + .getByTestId( 'item' ); + + // These tags are included to check that the elements are not unmounted + // and mounted again. If an element remounts, its tag should be missing. + await elements.evaluateAll( ( refs ) => + refs.forEach( ( ref, index ) => { + if ( ref instanceof HTMLElement ) { + ref.dataset.tag = `${ index }`; + } + } ) + ); + + await page + .getByTestId( 'derived state' ) + .getByTestId( 'rotate' ) + .click(); + + await expect( elements ).toHaveText( [ + 'cherimoya', + 'avocado', + 'banana', + ] ); + + // Get the tags. They should not have disappeared or changed. + const [ cherimoya, avocado, banana ] = await elements.all(); + await expect( cherimoya ).toHaveAttribute( 'data-tag', '2' ); + await expect( avocado ).toHaveAttribute( 'data-tag', '0' ); + await expect( banana ).toHaveAttribute( 'data-tag', '1' ); + } ); +} ); diff --git a/test/e2e/specs/interactivity/directive-on-document.spec.ts b/test/e2e/specs/interactivity/directive-on-document.spec.ts index 824e217f08714..56ac7e91d3121 100644 --- a/test/e2e/specs/interactivity/directive-on-document.spec.ts +++ b/test/e2e/specs/interactivity/directive-on-document.spec.ts @@ -30,17 +30,28 @@ test.describe( 'data-wp-on-document', () => { page, } ) => { const counter = page.getByTestId( 'counter' ); + const isEventAttached = page.getByTestId( 'isEventAttached' ); const visibilityButton = page.getByTestId( 'visibility' ); + await expect( counter ).toHaveText( '0' ); + await expect( isEventAttached ).toHaveText( 'yes' ); await page.keyboard.press( 'ArrowDown' ); await expect( counter ).toHaveText( '1' ); + // Remove the element. await visibilityButton.click(); // This keyboard press should not increase the counter. await page.keyboard.press( 'ArrowDown' ); + // Add the element back. await visibilityButton.click(); await expect( counter ).toHaveText( '1' ); + await expect( counter ).toHaveText( '1' ); + + // Wait until the effects run again. + await expect( isEventAttached ).toHaveText( 'yes' ); + + // Check that the event listener is attached again. await page.keyboard.press( 'ArrowDown' ); await expect( counter ).toHaveText( '2' ); } ); diff --git a/test/e2e/specs/site-editor/new-templates-list.spec.js b/test/e2e/specs/site-editor/new-templates-list.spec.js index 272a3ffff80bf..13484abcb13ad 100644 --- a/test/e2e/specs/site-editor/new-templates-list.spec.js +++ b/test/e2e/specs/site-editor/new-templates-list.spec.js @@ -18,11 +18,7 @@ test.describe( 'Templates', () => { ] ); } ); test( 'Sorting', async ( { admin, page } ) => { - await admin.visitSiteEditor( { path: '/wp_template' } ); - // Switch to table layout. - await page.getByLabel( 'View options' ).click(); - await page.getByRole( 'menuitem', { name: 'Layout' } ).click(); - await page.getByRole( 'menuitemradio', { name: 'Table' } ).click(); + await admin.visitSiteEditor( { path: '/wp_template/all' } ); // Descending by title. await page .getByRole( 'button', { name: 'Template', exact: true } ) @@ -52,13 +48,7 @@ test.describe( 'Templates', () => { title: 'Date Archives', content: 'hi', } ); - await admin.visitSiteEditor( { path: '/wp_template' } ); - - // Switch to table layout. - await page.getByLabel( 'View options' ).click(); - await page.getByRole( 'menuitem', { name: 'Layout' } ).click(); - await page.getByRole( 'menuitemradio', { name: 'Table' } ).click(); - + await admin.visitSiteEditor( { path: '/wp_template/all' } ); // Global search. await page.getByRole( 'searchbox', { name: 'Filter list' } ).click(); await page.keyboard.type( 'tag' ); @@ -94,13 +84,7 @@ test.describe( 'Templates', () => { await expect( titles ).toHaveCount( 2 ); } ); test( 'Field visibility', async ( { admin, page } ) => { - await admin.visitSiteEditor( { path: '/wp_template' } ); - - // Switch to table layout. - await page.getByLabel( 'View options' ).click(); - await page.getByRole( 'menuitem', { name: 'Layout' } ).click(); - await page.getByRole( 'menuitemradio', { name: 'Table' } ).click(); - + await admin.visitSiteEditor( { path: '/wp_template/all' } ); await page.getByRole( 'button', { name: 'Description' } ).click(); await page.getByRole( 'menuitem', { name: 'Hide' } ).click(); await expect(