Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/Testing/Assert/Expectation.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

namespace Playwright\Testing\Assert;

use PHPUnit\Framework\AssertionFailedError;
use Playwright\Assertions\Failure\AssertionException;
use Playwright\Locator\LocatorInterface;
use Playwright\Page\PageInterface;

Expand Down Expand Up @@ -48,7 +48,7 @@ public function not(): self
public function toBeVisible(?LocatorOptions $o = null): void
{
if (!$this->subject instanceof LocatorInterface) {
throw new AssertionFailedError('Subject is not a Locator');
throw new AssertionException('Subject is not a Locator');
}
$timeout = $this->timeoutMs;
if (!is_int($timeout)) {
Expand All @@ -71,13 +71,13 @@ public function toBeVisible(?LocatorOptions $o = null): void
} while (\microtime(true) < $deadline);

$msg = $this->negated ? 'not to be visible' : 'to be visible';
throw new AssertionFailedError("Expected locator {$msg}, last state: {$last}");
throw new AssertionException("Expected locator {$msg}, last state: {$last}");
}

public function toHaveURL(string|\Stringable|Regex $url, ?PageOptions $o = null): void
{
if (!$this->subject instanceof PageInterface) {
throw new AssertionFailedError('Subject is not a Page');
throw new AssertionException('Subject is not a Page');
}
$timeout = $this->timeoutMs;
if (!is_int($timeout)) {
Expand Down Expand Up @@ -114,6 +114,6 @@ public function toHaveURL(string|\Stringable|Regex $url, ?PageOptions $o = null)
} while (\microtime(true) < $deadline);

$expectText = $this->negated ? 'not to match' : 'to match';
throw new AssertionFailedError("Expected page URL {$expectText} {$pattern}, last observed: {$last}");
throw new AssertionException("Expected page URL {$expectText} {$pattern}, last observed: {$last}");
}
}
13 changes: 5 additions & 8 deletions src/Testing/Expect.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@

namespace Playwright\Testing;

use PHPUnit\Framework\Assert;
use PHPUnit\Framework\AssertionFailedError;
use Playwright\Assertions\Failure\AssertionException;
use Playwright\Locator\LocatorInterface;
use Playwright\Page\PageInterface;

Expand Down Expand Up @@ -383,12 +382,10 @@ private function retryAssertion(callable $condition, bool $expectedResult, strin
$actualResult = $condition();

if ($actualResult === $expectedResult) {
Assert::assertEquals($expectedResult, $actualResult);

return;
}

$lastException = new AssertionFailedError($message);
$lastException = new AssertionException($message);
} catch (\Throwable $e) {
$lastException = $e;
}
Expand All @@ -407,15 +404,15 @@ private function retryAssertion(callable $condition, bool $expectedResult, strin
}
}

if ($lastException instanceof AssertionFailedError) {
if ($lastException instanceof AssertionException) {
throw $lastException;
}

if ($lastException) {
throw new AssertionFailedError(\sprintf('Assertion timed out after %dms: %s. Last error: %s', $this->timeoutMs, $finalMessage, $lastException->getMessage()), 0, $lastException);
throw new AssertionException(\sprintf('Assertion timed out after %dms: %s. Last error: %s', $this->timeoutMs, $finalMessage, $lastException->getMessage()));
}

throw new AssertionFailedError(\sprintf('Assertion timed out after %dms: %s', $this->timeoutMs, $finalMessage));
throw new AssertionException(\sprintf('Assertion timed out after %dms: %s', $this->timeoutMs, $finalMessage));
}

public function toHaveCSS(string $name, string $value): void
Expand Down
178 changes: 178 additions & 0 deletions src/Testing/ExpectDecorator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
<?php

declare(strict_types=1);

/*
* This file is part of the community-maintained Playwright PHP project.
* It is not affiliated with or endorsed by Microsoft.
*
* (c) 2025-Present - Playwright PHP - https://github.com/playwright-php
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Playwright\Testing;

/**
* Decorator for Expect that automatically increments PHPUnit assertion count when available.
* This allows the Expect class to work independently (without PHPUnit) while still
* counting assertions properly when used within PHPUnit tests.
*/
final class ExpectDecorator implements ExpectInterface
{
private int $assertionCount = 0;

public function __construct(
private readonly ExpectInterface $expect,
private readonly ?object $testCase = null,
) {
}

public function toBeVisible(): void
{
$this->expect->toBeVisible();
$this->recordAssertion(1);
}

public function toBeHidden(): void
{
$this->expect->toBeHidden();
$this->recordAssertion(1);
}

public function toHaveText(string $text): void
{
$this->expect->toHaveText($text);
$this->recordAssertion(1);
}

public function toContainText(string $text): void
{
$this->expect->toContainText($text);
$this->recordAssertion(1);
}

public function toHaveExactText(string $text): void
{
$this->expect->toHaveExactText($text);
$this->recordAssertion(1);
}

public function toHaveValue(string $value): void
{
$this->expect->toHaveValue($value);
$this->recordAssertion(1);
}

public function toHaveAttribute(string $name, string $value): void
{
$this->expect->toHaveAttribute($name, $value);
$this->recordAssertion(1);
}

public function toBeChecked(): void
{
$this->expect->toBeChecked();
$this->recordAssertion(1);
}

public function toBeEnabled(): void
{
$this->expect->toBeEnabled();
$this->recordAssertion(1);
}

public function toBeDisabled(): void
{
$this->expect->toBeDisabled();
$this->recordAssertion(1);
}

public function toHaveCSS(string $name, string $value): void
{
$this->expect->toHaveCSS($name, $value);
$this->recordAssertion(1);
}

public function toHaveId(string $id): void
{
$this->expect->toHaveId($id);
$this->recordAssertion(1);
}

/**
* @param string|string[] $class
*/
public function toHaveClass(string|array $class): void
{
$this->expect->toHaveClass($class);
$this->recordAssertion(1);
}

public function toBeEmpty(): void
{
$this->expect->toBeEmpty();
$this->recordAssertion(1);
}

public function toHaveCount(int $count): void
{
$this->expect->toHaveCount($count);
$this->recordAssertion(1);
}

public function toBeFocused(): void
{
$this->expect->toBeFocused();
$this->recordAssertion(1);
}

public function toHaveFocus(): void
{
$this->expect->toHaveFocus();
$this->recordAssertion(1);
}

public function toHaveTitle(string $title): void
{
$this->expect->toHaveTitle($title);
$this->recordAssertion(1);
}

public function toHaveURL(string $url): void
{
$this->expect->toHaveURL($url);
$this->recordAssertion(1);
}

public function not(): self
{
$this->expect->not();

return $this;
}

public function withTimeout(int $timeoutMs): self
{
$this->expect->withTimeout($timeoutMs);

return $this;
}

public function withPollInterval(int $pollIntervalMs): self
{
$this->expect->withPollInterval($pollIntervalMs);

return $this;
}

private function recordAssertion(int $count): void
{
$this->assertionCount += $count;

if (null !== $this->testCase && method_exists($this->testCase, 'addToAssertionCount')) {
$this->testCase->addToAssertionCount($count);
}
}
}
2 changes: 1 addition & 1 deletion src/Testing/PlaywrightTestCaseTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ protected function assertElementExists(string $selector): void

protected function expect(LocatorInterface|PageInterface $subject): ExpectInterface
{
return new Expect($subject);
return new ExpectDecorator(new Expect($subject), $this);
}

private function resolveLogger(?LoggerInterface $logger): ?LoggerInterface
Expand Down
14 changes: 0 additions & 14 deletions tests/Integration/Testing/ExpectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ public function itAssertsVisibility(): void

$expect = $this->expect($this->page->locator('#div-2'));
$expect->toBeHidden();

$this->addToAssertionCount(2);
}

#[Test]
Expand All @@ -81,8 +79,6 @@ public function itAssertsTextContent(): void

$expect = $this->expect($this->page->locator('h1'));
$expect->not()->toHaveText('Wrong Text');

$this->addToAssertionCount(2);
}

#[Test]
Expand All @@ -105,8 +101,6 @@ public function itAssertsInputValue(): void

$expect = $this->expect($this->page->locator('#input-text'));
$expect->not()->toHaveValue('wrong value');

$this->addToAssertionCount(2);
}

#[Test]
Expand All @@ -117,8 +111,6 @@ public function itAssertsAttributeValue(): void

$expect = $this->expect($this->page->locator('#input-text'));
$expect->not()->toHaveAttribute('type', 'password');

$this->addToAssertionCount(2);
}

#[Test]
Expand All @@ -131,8 +123,6 @@ public function itAssertsCheckedState(): void

$expect = $this->expect($this->page->locator('#input-checkbox'));
$expect->not()->toBeChecked();

$this->addToAssertionCount(2);
}

#[Test]
Expand All @@ -146,8 +136,6 @@ public function itAssertsEnabledState(): void

$expect = $this->expect($this->page->locator('#button-2'));
$expect->toBeDisabled();

$this->addToAssertionCount(2);
}

#[Test]
Expand All @@ -158,8 +146,6 @@ public function itAssertsElementCount(): void

$expect = $this->expect($this->page->locator('button'));
$expect->not()->toHaveCount(1);

$this->addToAssertionCount(2);
}

#[Test]
Expand Down