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 efce271f..644627f0 100644 --- a/src/Dom/Node.php +++ b/src/Dom/Node.php @@ -128,8 +128,15 @@ 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 { + 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(), ]); @@ -137,7 +144,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..4c290006 100644 --- a/tests/DomTest.php +++ b/tests/DomTest.php @@ -2,6 +2,7 @@ namespace HeadlessChromium\Test; +use Generator; use HeadlessChromium\Browser; use HeadlessChromium\BrowserFactory; use HeadlessChromium\Exception\StaleElementException; @@ -140,6 +141,51 @@ public function testSetAttribute(): void self::assertSame('hello', $value); } + /** + * @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'); + + if (null !== $boxModel) { + $position = $element->getPosition($boxModel); + } else { + $position = $element->getPosition(); + } + + 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 { $page = $this->openSitePage('domForm.html'); 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 +
+ +