Skip to content

Commit b9154cc

Browse files
authored
Merge pull request #1817 from WordPress/update/od-test-coverage
Improve test coverage for Optimization Detective
2 parents 762e52a + 275d102 commit b9154cc

22 files changed

+453
-38
lines changed

plugins/optimization-detective/class-od-link-collection.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,18 @@ public function add_link( array $attributes, ?int $minimum_viewport_width = null
114114
* @return LinkAttributes[] Prepared links with adjacent-duplicates merged together and media attributes added.
115115
*/
116116
private function get_prepared_links(): array {
117+
$links_by_rel = array_values( $this->links_by_rel );
118+
if ( count( $links_by_rel ) === 0 ) {
119+
// This condition is needed for PHP 7.2 and PHP 7.3 in which array_merge() fails if passed a spread empty array: 'array_merge() expects at least 1 parameter, 0 given'.
120+
return array();
121+
}
122+
117123
return array_merge(
118124
...array_map(
119125
function ( array $links ): array {
120126
return $this->merge_consecutive_links( $links );
121127
},
122-
array_values( $this->links_by_rel )
128+
$links_by_rel
123129
)
124130
);
125131
}

plugins/optimization-detective/class-od-strict-url-metric.php

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
* This is used exclusively in the REST API endpoint for capturing new URL Metrics to prevent invalid additional data from being
1919
* submitted in the request. For URL Metrics which have been stored the looser OD_URL_Metric class is used instead.
2020
*
21+
* @phpstan-import-type JSONSchema from OD_URL_Metric
22+
*
2123
* @since 0.6.0
2224
* @access private
2325
*/
@@ -28,7 +30,7 @@ final class OD_Strict_URL_Metric extends OD_URL_Metric {
2830
*
2931
* @since 0.6.0
3032
*
31-
* @return array<string, mixed> Schema.
33+
* @return JSONSchema Schema.
3234
*/
3335
public static function get_json_schema(): array {
3436
return self::set_additional_properties_to_false( parent::get_json_schema() );
@@ -43,34 +45,36 @@ public static function get_json_schema(): array {
4345
* @since 0.6.0
4446
* @see rest_default_additional_properties_to_false()
4547
*
46-
* @param mixed $schema Schema.
47-
* @return mixed Processed schema.
48+
* @phpstan-param JSONSchema $schema
49+
*
50+
* @param array<string, mixed> $schema Schema.
51+
* @return JSONSchema Processed schema.
4852
*/
49-
private static function set_additional_properties_to_false( $schema ) {
50-
if ( ! isset( $schema['type'] ) ) {
51-
return $schema;
52-
}
53-
53+
private static function set_additional_properties_to_false( array $schema ): array {
5454
$type = (array) $schema['type'];
5555

5656
if ( in_array( 'object', $type, true ) ) {
5757
if ( isset( $schema['properties'] ) ) {
5858
foreach ( $schema['properties'] as $key => $child_schema ) {
59-
$schema['properties'][ $key ] = self::set_additional_properties_to_false( $child_schema );
59+
if ( isset( $child_schema['type'] ) ) {
60+
$schema['properties'][ $key ] = self::set_additional_properties_to_false( $child_schema );
61+
}
6062
}
6163
}
6264

6365
if ( isset( $schema['patternProperties'] ) ) {
6466
foreach ( $schema['patternProperties'] as $key => $child_schema ) {
65-
$schema['patternProperties'][ $key ] = self::set_additional_properties_to_false( $child_schema );
67+
if ( isset( $child_schema['type'] ) ) {
68+
$schema['patternProperties'][ $key ] = self::set_additional_properties_to_false( $child_schema );
69+
}
6670
}
6771
}
6872

6973
$schema['additionalProperties'] = false;
7074
}
7175

7276
if ( in_array( 'array', $type, true ) ) {
73-
if ( isset( $schema['items'] ) ) {
77+
if ( isset( $schema['items'], $schema['items']['type'] ) ) {
7478
$schema['items'] = self::set_additional_properties_to_false( $schema['items'] );
7579
}
7680
}

plugins/optimization-detective/class-od-url-metric-group-collection.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,9 +271,12 @@ public function add_url_metric( OD_URL_Metric $new_url_metric ): void {
271271
return;
272272
}
273273
}
274+
// @codeCoverageIgnoreStart
275+
// In practice this exception should never get thrown because create_groups() creates groups from a minimum of 0 to a maximum of PHP_INT_MAX.
274276
throw new InvalidArgumentException(
275277
esc_html__( 'No group available to add URL Metric to.', 'optimization-detective' )
276278
);
279+
// @codeCoverageIgnoreEnd
277280
}
278281

279282
/**
@@ -296,6 +299,8 @@ public function get_group_for_viewport_width( int $viewport_width ): OD_URL_Metr
296299
return $group;
297300
}
298301
}
302+
// @codeCoverageIgnoreStart
303+
// In practice this exception should never get thrown because create_groups() creates groups from a minimum of 0 to a maximum of PHP_INT_MAX.
299304
throw new InvalidArgumentException(
300305
esc_html(
301306
sprintf(
@@ -305,6 +310,7 @@ public function get_group_for_viewport_width( int $viewport_width ): OD_URL_Metr
305310
)
306311
)
307312
);
313+
// @codeCoverageIgnoreEnd
308314
} )();
309315

310316
$this->result_cache[ __FUNCTION__ ][ $viewport_width ] = $result;

plugins/optimization-detective/class-od-url-metric.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,19 @@
4545
* viewport: ViewportRect,
4646
* elements: ElementData[]
4747
* }
48+
* @phpstan-type JSONSchema array{
49+
* type: string|string[],
50+
* items?: mixed,
51+
* properties?: array<string, mixed>,
52+
* patternProperties?: array<string, mixed>,
53+
* required?: bool,
54+
* minimum?: int,
55+
* maximum?: int,
56+
* pattern?: non-empty-string,
57+
* additionalProperties?: bool,
58+
* format?: non-empty-string,
59+
* readonly?: bool,
60+
* }
4861
*
4962
* @since 0.1.0
5063
* @access private
@@ -161,7 +174,7 @@ public function set_group( OD_URL_Metric_Group $group ): void {
161174
*
162175
* @todo Cache the return value?
163176
*
164-
* @return array<string, mixed> Schema.
177+
* @return JSONSchema Schema.
165178
*/
166179
public static function get_json_schema(): array {
167180
/*

plugins/optimization-detective/hooks.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
}
1313
// @codeCoverageIgnoreEnd
1414

15+
// The addition of the following hooks is tested in Test_OD_Hooks::test_hooks_added() and Test_OD_Storage_Post_Type::test_add_hooks().
16+
17+
// @codeCoverageIgnoreStart
1518
add_action( 'init', 'od_initialize_extensions', PHP_INT_MAX );
1619
add_filter( 'template_include', 'od_buffer_output', PHP_INT_MAX );
1720
OD_URL_Metrics_Post_Type::add_hooks();
@@ -20,3 +23,4 @@
2023
add_filter( 'site_status_tests', 'od_add_rest_api_availability_test' );
2124
add_action( 'admin_init', 'od_maybe_run_rest_api_health_check' );
2225
add_action( 'after_plugin_row_meta', 'od_render_rest_api_health_check_admin_notice_in_plugin_row', 30 );
26+
// @codeCoverageIgnoreEnd

plugins/optimization-detective/storage/rest-api.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ function od_handle_rest_request( WP_REST_Request $request ) {
168168
);
169169
} catch ( InvalidArgumentException $exception ) {
170170
// Note: This should never happen because an exception only occurs if a viewport width is less than zero, and the JSON Schema enforces that the viewport.width have a minimum of zero.
171-
return new WP_Error( 'invalid_viewport_width', $exception->getMessage() );
171+
return new WP_Error( 'invalid_viewport_width', $exception->getMessage() ); // @codeCoverageIgnore
172172
}
173173
if ( $url_metric_group->is_complete() ) {
174174
return new WP_Error(
@@ -279,7 +279,7 @@ function od_handle_rest_request( WP_REST_Request $request ) {
279279
* @since 0.8.0
280280
* @access private
281281
*
282-
* @param int $cache_purge_post_id Cache purge post ID.
282+
* @param positive-int $cache_purge_post_id Cache purge post ID.
283283
*/
284284
function od_trigger_page_cache_invalidation( int $cache_purge_post_id ): void {
285285
$post = get_post( $cache_purge_post_id );

plugins/optimization-detective/tests/storage/test-rest-api.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ static function ( array $properties ) use ( $property_name ): array {
7575
* @covers ::od_register_endpoint
7676
* @covers ::od_handle_rest_request
7777
* @covers ::od_trigger_page_cache_invalidation
78+
* @covers OD_Strict_URL_Metric::set_additional_properties_to_false
79+
* @covers OD_URL_Metric_Store_Request_Context::__construct
7880
*/
7981
public function test_rest_request_good_params( Closure $set_up ): void {
8082
$stored_context = null;
@@ -140,6 +142,28 @@ function ( OD_URL_Metric_Store_Request_Context $context ) use ( &$stored_context
140142
}
141143
}
142144

145+
/**
146+
* Test good params.
147+
*
148+
* @dataProvider data_provider_to_test_rest_request_good_params
149+
*
150+
* @covers ::od_register_endpoint
151+
* @covers ::od_handle_rest_request
152+
* @covers OD_Strict_URL_Metric::set_additional_properties_to_false
153+
*/
154+
public function test_rest_request_good_params_but_post_save_failed( Closure $set_up ): void {
155+
$valid_params = $set_up();
156+
157+
add_filter( 'wp_insert_post_empty_content', '__return_true' ); // Cause wp_insert_post() to return WP_Error.
158+
159+
$request = $this->create_request( $valid_params );
160+
$response = rest_get_server()->dispatch( $request );
161+
162+
$error = $response->as_error();
163+
$this->assertInstanceOf( WP_Error::class, $error );
164+
$this->assertSame( 'unable_to_store_url_metric', $error->get_error_code() );
165+
}
166+
143167
/**
144168
* Data provider for test_rest_request_bad_params.
145169
*
@@ -274,6 +298,7 @@ static function ( $params ) use ( $valid_params ) {
274298
*
275299
* @covers ::od_register_endpoint
276300
* @covers ::od_handle_rest_request
301+
* @covers OD_Strict_URL_Metric::set_additional_properties_to_false
277302
*
278303
* @dataProvider data_provider_invalid_params
279304
*
@@ -655,6 +680,22 @@ static function ( string $hook, ...$args ) use ( &$all_hook_callback_args ): voi
655680
$this->assertTrue( $found, 'Expected save_post to have been fired for the post queried object.' );
656681
}
657682

683+
/**
684+
* Test od_trigger_page_cache_invalidation() for an invalid post.
685+
*
686+
* @covers ::od_trigger_page_cache_invalidation
687+
*/
688+
public function test_od_trigger_page_cache_invalidation_invalid_post_id(): void {
689+
wp_delete_post( 1, true );
690+
$before_clean_post_cache_count = did_action( 'clean_post_cache' );
691+
$before_transition_post_status_count = did_action( 'transition_post_status' );
692+
$before_save_post_count = did_action( 'save_post' );
693+
od_trigger_page_cache_invalidation( 1 );
694+
$this->assertSame( $before_clean_post_cache_count, did_action( 'clean_post_cache' ) );
695+
$this->assertSame( $before_transition_post_status_count, did_action( 'transition_post_status' ) );
696+
$this->assertSame( $before_save_post_count, did_action( 'save_post' ) );
697+
}
698+
658699
/**
659700
* Populate URL Metrics.
660701
*
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<html lang="en">
2+
<head>
3+
<meta charset="utf-8">
4+
<title>...</title>
5+
</head>
6+
<body>
7+
<div id="page">
8+
<img src="https://example.com/image.jpg" alt="" width="100" height="100">
9+
</div>
10+
</body>
11+
</html>

plugins/optimization-detective/tests/test-cases/preload-link/expected.html

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
return static function (): void {
3+
4+
add_action(
5+
'od_register_tag_visitors',
6+
static function ( OD_Tag_Visitor_Registry $registry ): void {
7+
$registry->register(
8+
'img-preload',
9+
static function ( OD_Tag_Visitor_Context $context ): bool {
10+
if ( 'IMG' === $context->processor->get_tag() ) {
11+
$context->link_collection->add_link(
12+
array(
13+
'rel' => 'preload',
14+
'as' => 'image',
15+
'href' => $context->processor->get_attribute( 'src' ),
16+
)
17+
);
18+
}
19+
return false;
20+
}
21+
);
22+
}
23+
);
24+
};

0 commit comments

Comments
 (0)