Skip to content

Commit

Permalink
Fix DOMRect using floats for width/height not ints
Browse files Browse the repository at this point in the history
  • Loading branch information
westonruter committed Jul 26, 2024
1 parent f6359c1 commit 02b8fb3
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 15 deletions.
10 changes: 5 additions & 5 deletions plugins/optimization-detective/class-od-url-metric.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
/**
* Representation of the measurements taken from a single client's visit to a specific URL.
*
* @phpstan-type RectData array{ width: int, height: int }
* @phpstan-type RectData array{ width: float, height: float }
* @phpstan-type ElementData array{
* isLCP: bool,
* isLCPCandidate: bool,
Expand All @@ -26,7 +26,7 @@
* @phpstan-type Data array{
* url: string,
* timestamp: float,
* viewport: RectData,
* viewport: array{ width: int, height: int },
* elements: ElementData[]
* }
*
Expand Down Expand Up @@ -82,11 +82,11 @@ public static function get_json_schema(): array {
'properties' => array(
'width' => array(
'type' => 'number',
'minimum' => 0,
'minimum' => 0.0,
),
'height' => array(
'type' => 'number',
'minimum' => 0,
'minimum' => 0.0,
),
),
// TODO: There are other properties to define if we need them: x, y, top, right, bottom, left.
Expand Down Expand Up @@ -179,7 +179,7 @@ public function get_url(): string {
/**
* Gets viewport data.
*
* @return RectData Viewport data.
* @return array{ width: int, height: int } Viewport data.
*/
public function get_viewport(): array {
return $this->data['viewport'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ final class OD_URL_Metrics_Group_Collection implements Countable, IteratorAggreg
* get_groups_by_lcp_element?: array<string, OD_URL_Metrics_Group[]>,
* get_common_lcp_element?: ElementData|null,
* get_all_element_max_intersection_ratios?: array<string, float>,
* get_all_element_minimum_heights?: array<string, int>
* get_all_element_minimum_heights?: array<string, float>
* }
*/
private $result_cache = array();
Expand Down Expand Up @@ -434,7 +434,9 @@ public function get_all_element_max_intersection_ratios(): array {
/**
* Gets the minimum heights of all elements across all groups and their captured URL metrics.
*
* @return array<string, int> Keys are XPaths and values are the minimum heights.
* @since n.e.x.t
*
* @return array<string, float> Keys are XPaths and values are the minimum heights.
*/
public function get_all_element_minimum_heights(): array {
if ( array_key_exists( __FUNCTION__, $this->result_cache ) ) {
Expand Down Expand Up @@ -479,10 +481,12 @@ public function get_element_max_intersection_ratio( string $xpath ): ?float {
/**
* Gets the minimum height of an element across all groups and their captured URL metrics.
*
* @since n.e.x.t
*
* @param string $xpath XPath for the element.
* @return int Minimum height in pixels.
* @return float Minimum height in pixels.
*/
public function get_element_minimum_height( string $xpath ): ?int {
public function get_element_minimum_height( string $xpath ): ?float {
return $this->get_all_element_minimum_heights()[ $xpath ] ?? null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
*
* @package optimization-detective
*
* @phpstan-import-type Data from OD_URL_Metric
*
* @coversDefaultClass OD_URL_Metric
*/
class Test_OD_URL_Metric extends WP_UnitTestCase {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,77 @@ public function test_get_all_element_max_intersection_ratios( array $url_metrics
}
}

/**
* Data provider.
*
* @return array<string, mixed>
* @throws OD_Data_Validation_Exception But it won't really.
*/
public function data_provider_element_minimum_heights(): array {
$xpath1 = '/*[0][self::HTML]/*[1][self::BODY]/*[0][self::IMG]/*[1]';
$xpath2 = '/*[0][self::HTML]/*[1][self::BODY]/*[0][self::IMG]/*[2]';
$xpath3 = '/*[0][self::HTML]/*[1][self::BODY]/*[0][self::IMG]/*[3]';
return array(
'one-element-sample-size-one' => array(
'url_metrics' => array(
$this->get_validated_url_metric( 400, $xpath1, 1.0, 480 ),
$this->get_validated_url_metric( 600, $xpath1, 1.0, 240 ),
$this->get_validated_url_metric( 800, $xpath1, 1.0, 768 ),
),
'expected' => array(
$xpath1 => 240.0,
),
),
'three-elements-sample-size-two' => array(
'url_metrics' => array(
// Group 1.
$this->get_validated_url_metric( 400, $xpath1, 1.0, 400 ),
$this->get_validated_url_metric( 400, $xpath1, 1.0, 600 ),
// Group 2.
$this->get_validated_url_metric( 600, $xpath2, 1.0, 100.1 ),
$this->get_validated_url_metric( 600, $xpath2, 1.0, 100.2 ),
$this->get_validated_url_metric( 600, $xpath2, 1.0, 100.05 ),
// Group 3.
$this->get_validated_url_metric( 800, $xpath3, 1.0, 500 ),
$this->get_validated_url_metric( 800, $xpath3, 1.0, 500 ),
),
'expected' => array(
$xpath1 => 400.0,
$xpath2 => 100.05,
$xpath3 => 500.0,
),
),
'no-url-metrics' => array(
'url_metrics' => array(),
'expected' => array(),
),

);
}

/**
* Test get_all_element_max_intersection_ratios() and get_element_max_intersection_ratio().
*
* @covers ::get_all_element_minimum_heights
* @covers ::get_element_minimum_height
*
* @dataProvider data_provider_element_minimum_heights
*
* @param array<string, mixed> $url_metrics URL metrics.
* @param array<string, float> $expected Expected.
*/
public function test_get_all_element_minimum_heights( array $url_metrics, array $expected ): void {
$breakpoints = array( 480, 600, 782 );
$sample_size = 3;
$group_collection = new OD_URL_Metrics_Group_Collection( $url_metrics, $breakpoints, $sample_size, 0 );
$actual = $group_collection->get_all_element_minimum_heights();
$this->assertSame( $actual, $group_collection->get_all_element_minimum_heights(), 'Cached result is identical.' );
$this->assertSame( $expected, $actual );
foreach ( $expected as $expected_xpath => $expected_max_ratio ) {
$this->assertSame( $expected_max_ratio, $group_collection->get_element_minimum_height( $expected_xpath ) );
}
}

/**
* Test get_flattened_url_metrics().
*
Expand Down Expand Up @@ -756,13 +827,16 @@ public function test_json_serialize(): void {
/**
* Gets a validated URL metric for testing.
*
* @param int $viewport_width Viewport width.
* @param string $lcp_element_xpath LCP element XPath.
* @param float $intersection_ratio Intersection ratio.
* @todo Replace this with {@see Optimization_Detective_Test_Helpers::get_validated_url_metric()}
*
* @param int $viewport_width Viewport width.
* @param string $lcp_element_xpath LCP element XPath.
* @param float $intersection_ratio Intersection ratio.
* @param float $intersection_height Intersection height.
* @return OD_URL_Metric Validated URL metric.
* @throws OD_Data_Validation_Exception From OD_URL_Metric if there is a parse error, but there won't be.
*/
private function get_validated_url_metric( int $viewport_width = 480, string $lcp_element_xpath = '/*[0][self::HTML]/*[1][self::BODY]/*[0][self::IMG]/*[1]', float $intersection_ratio = 1.0 ): OD_URL_Metric {
private function get_validated_url_metric( int $viewport_width = 480, string $lcp_element_xpath = '/*[0][self::HTML]/*[1][self::BODY]/*[0][self::IMG]/*[1]', float $intersection_ratio = 1.0, float $intersection_height = 100 ): OD_URL_Metric {
$data = array(
'url' => home_url( '/' ),
'viewport' => array(
Expand All @@ -778,11 +852,11 @@ private function get_validated_url_metric( int $viewport_width = 480, string $lc
'intersectionRatio' => $intersection_ratio,
'intersectionRect' => array(
'width' => 100,
'height' => 100,
'height' => $intersection_height,
),
'boundingClientRect' => array(
'width' => 100,
'height' => 100,
'height' => $intersection_height,
),
),
),
Expand Down

0 comments on commit 02b8fb3

Please sign in to comment.