From 15fcac0713136b3641e34cd0ce10465ee9def2ec Mon Sep 17 00:00:00 2001 From: Albert Prat Date: Thu, 18 Jun 2026 12:06:51 +0200 Subject: [PATCH 1/2] Add a parameter to `Node::getPostion()` to allow to chose the box model --- src/Dom/Node.php | 7 ++- tests/DomTest.php | 56 ++++++++++++++++++++---- tests/resources/static-web/boxModel.html | 27 ++++++++++++ 3 files changed, 80 insertions(+), 10 deletions(-) create mode 100644 tests/resources/static-web/boxModel.html diff --git a/src/Dom/Node.php b/src/Dom/Node.php index efce271f..535cfa28 100644 --- a/src/Dom/Node.php +++ b/src/Dom/Node.php @@ -128,7 +128,10 @@ public function getAttribute(string $name): ?string return $this->getAttributes()->get($name); } - public function getPosition(): ?NodePosition + /** + * @param 'content'|'padding'|'border'|'margin' $boxModel + */ + public function getPosition(string $boxModel = 'content'): ?NodePosition { $message = new Message('DOM.getBoxModel', [ 'nodeId' => $this->getNodeIdForRequest(), @@ -137,7 +140,7 @@ public function getPosition(): ?NodePosition $this->assertNotError($response); - $points = $response->getResultData('model')['content']; + $points = $response->getResultData('model')[$boxModel] ?? null; if (null !== $points) { return new NodePosition($points); diff --git a/tests/DomTest.php b/tests/DomTest.php index 3a5a5fdd..6010dd84 100644 --- a/tests/DomTest.php +++ b/tests/DomTest.php @@ -5,6 +5,7 @@ use HeadlessChromium\Browser; use HeadlessChromium\BrowserFactory; use HeadlessChromium\Exception\StaleElementException; +use PHPUnit\Framework\Attributes\TestWith; /** * @covers \HeadlessChromium\Dom\Dom @@ -26,14 +27,6 @@ public static function tearDownAfterClass(): void self::$browser->close(); } - private function openSitePage($file) - { - $page = self::$browser->createPage(); - $page->navigate(self::sitePath($file))->waitForNavigation(); - - return $page; - } - public function testSearchByCssSelector(): void { $page = $this->openSitePage('domForm.html'); @@ -140,6 +133,45 @@ public function testSetAttribute(): void self::assertSame('hello', $value); } + #[TestWith(['margin', 0, 0, 310, 360])] + /** @phpstan-ignore attribute.nonRepeatable */ + #[TestWith(['border', 20, 10, 270, 340])] + /** @phpstan-ignore attribute.nonRepeatable */ + #[TestWith(['padding', 25, 15, 260, 330])] + /** @phpstan-ignore attribute.nonRepeatable */ + #[TestWith(['content', 55, 30, 200, 300])] + /** @phpstan-ignore attribute.nonRepeatable */ + #[TestWith([null, 55, 30, 200, 300])] + /** @phpstan-ignore attribute.nonRepeatable */ + #[TestWith(['-invalid-', 0, 0, 0, 0])] + public function testGetPosition( + ?string $boxModel, + float $expectedX, + float $expectedY, + float $expectedWidth, + float $expectedHeight, + ): void { + $page = $this->openSitePage('boxModel.html'); + + $element = $page->dom()->querySelector('#elem'); + + if (null !== $boxModel) { + $position = $element->getPosition($boxModel); + } else { + $position = $element->getPosition(); + } + + if ('-invalid-' !== $boxModel) { + self::assertNotNull($position); + self::assertSame($expectedX, $position->getX()); + self::assertSame($expectedY, $position->getY()); + self::assertSame($expectedWidth, $position->getWidth()); + self::assertSame($expectedHeight, $position->getHeight()); + } else { + self::assertNull($position); + } + } + public function testUploadFile(): void { $page = $this->openSitePage('domForm.html'); @@ -240,4 +272,12 @@ public function testRegularNodeIsMarkedAsStaleAfterReload(): void $inputNode->sendKeys('test'); } + + private function openSitePage($file) + { + $page = self::$browser->createPage(); + $page->navigate(self::sitePath($file))->waitForNavigation(); + + return $page; + } } diff --git a/tests/resources/static-web/boxModel.html b/tests/resources/static-web/boxModel.html new file mode 100644 index 00000000..5f64ede9 --- /dev/null +++ b/tests/resources/static-web/boxModel.html @@ -0,0 +1,27 @@ + + + box model - test + + + + +
+ some content +
+ + From 0f50d784cec5222b091074d1d5d68a3cf2c6b823 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Mon, 6 Jul 2026 00:54:59 +0100 Subject: [PATCH 2/2] Validate the box model and fix PHP 7.4 test compatibility --- CHANGELOG.md | 1 + src/Dom/Node.php | 4 +++ tests/DomTest.php | 78 +++++++++++++++++++++++++---------------------- 3 files changed, 47 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cf7eeea..545cdd11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ## 1.16.0 (UPCOMING) * Add `disableJavascript` option +* Allow choosing the box model in `Node::getPosition()` ## 1.15.0 (2025-12-27) diff --git a/src/Dom/Node.php b/src/Dom/Node.php index 535cfa28..644627f0 100644 --- a/src/Dom/Node.php +++ b/src/Dom/Node.php @@ -133,6 +133,10 @@ public function getAttribute(string $name): ?string */ public function getPosition(string $boxModel = 'content'): ?NodePosition { + if (!\in_array($boxModel, ['content', 'padding', 'border', 'margin'], true)) { + throw new \InvalidArgumentException('Invalid box model "'.$boxModel.'" for node position. Box model must be "content", "padding", "border" or "margin".'); + } + $message = new Message('DOM.getBoxModel', [ 'nodeId' => $this->getNodeIdForRequest(), ]); diff --git a/tests/DomTest.php b/tests/DomTest.php index 6010dd84..4c290006 100644 --- a/tests/DomTest.php +++ b/tests/DomTest.php @@ -2,10 +2,10 @@ namespace HeadlessChromium\Test; +use Generator; use HeadlessChromium\Browser; use HeadlessChromium\BrowserFactory; use HeadlessChromium\Exception\StaleElementException; -use PHPUnit\Framework\Attributes\TestWith; /** * @covers \HeadlessChromium\Dom\Dom @@ -27,6 +27,14 @@ public static function tearDownAfterClass(): void self::$browser->close(); } + private function openSitePage($file) + { + $page = self::$browser->createPage(); + $page->navigate(self::sitePath($file))->waitForNavigation(); + + return $page; + } + public function testSearchByCssSelector(): void { $page = $this->openSitePage('domForm.html'); @@ -133,24 +141,11 @@ public function testSetAttribute(): void self::assertSame('hello', $value); } - #[TestWith(['margin', 0, 0, 310, 360])] - /** @phpstan-ignore attribute.nonRepeatable */ - #[TestWith(['border', 20, 10, 270, 340])] - /** @phpstan-ignore attribute.nonRepeatable */ - #[TestWith(['padding', 25, 15, 260, 330])] - /** @phpstan-ignore attribute.nonRepeatable */ - #[TestWith(['content', 55, 30, 200, 300])] - /** @phpstan-ignore attribute.nonRepeatable */ - #[TestWith([null, 55, 30, 200, 300])] - /** @phpstan-ignore attribute.nonRepeatable */ - #[TestWith(['-invalid-', 0, 0, 0, 0])] - public function testGetPosition( - ?string $boxModel, - float $expectedX, - float $expectedY, - float $expectedWidth, - float $expectedHeight, - ): void { + /** + * @dataProvider providerGetPosition + */ + public function testGetPosition(?string $boxModel, float $expectedX, float $expectedY, float $expectedWidth, float $expectedHeight): void + { $page = $this->openSitePage('boxModel.html'); $element = $page->dom()->querySelector('#elem'); @@ -161,15 +156,34 @@ public function testGetPosition( $position = $element->getPosition(); } - if ('-invalid-' !== $boxModel) { - self::assertNotNull($position); - self::assertSame($expectedX, $position->getX()); - self::assertSame($expectedY, $position->getY()); - self::assertSame($expectedWidth, $position->getWidth()); - self::assertSame($expectedHeight, $position->getHeight()); - } else { - self::assertNull($position); - } + self::assertNotNull($position); + self::assertSame($expectedX, $position->getX()); + self::assertSame($expectedY, $position->getY()); + self::assertSame($expectedWidth, $position->getWidth()); + self::assertSame($expectedHeight, $position->getHeight()); + } + + /** + * @return Generator + */ + public static function providerGetPosition(): Generator + { + yield 'margin' => ['margin', 0.0, 0.0, 310.0, 360.0]; + yield 'border' => ['border', 20.0, 10.0, 270.0, 340.0]; + yield 'padding' => ['padding', 25.0, 15.0, 260.0, 330.0]; + yield 'content' => ['content', 55.0, 30.0, 200.0, 300.0]; + yield 'default' => [null, 55.0, 30.0, 200.0, 300.0]; + } + + public function testGetPositionWithInvalidBoxModel(): void + { + $page = $this->openSitePage('boxModel.html'); + + $element = $page->dom()->querySelector('#elem'); + + $this->expectException(\InvalidArgumentException::class); + + $element->getPosition('-invalid-'); } public function testUploadFile(): void @@ -272,12 +286,4 @@ public function testRegularNodeIsMarkedAsStaleAfterReload(): void $inputNode->sendKeys('test'); } - - private function openSitePage($file) - { - $page = self::$browser->createPage(); - $page->navigate(self::sitePath($file))->waitForNavigation(); - - return $page; - } }