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
74 changes: 74 additions & 0 deletions src/Codeception/Module/Symfony/BrowserAssertionsTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
use PHPUnit\Framework\Constraint\LogicalNot;
use Symfony\Component\BrowserKit\Test\Constraint\BrowserCookieValueSame;
use Symfony\Component\BrowserKit\Test\Constraint\BrowserHasCookie;
use Symfony\Component\BrowserKit\Test\Constraint\BrowserHistoryIsOnFirstPage;
use Symfony\Component\BrowserKit\Test\Constraint\BrowserHistoryIsOnLastPage;
use Symfony\Component\HttpFoundation\Test\Constraint\RequestAttributeValueSame;
use Symfony\Component\HttpFoundation\Test\Constraint\ResponseCookieValueSame;
use Symfony\Component\HttpFoundation\Test\Constraint\ResponseFormatSame;
Expand Down Expand Up @@ -71,6 +73,78 @@ public function assertBrowserNotHasCookie(string $name, string $path = '/', ?str
$this->assertThatForClient(new LogicalNot(new BrowserHasCookie($name, $path, $domain)), $message);
}

/**
* Asserts that the browser history is currently on the first page.
*
* ```php
* <?php
* $I->assertBrowserHistoryIsOnFirstPage();
* ```
*/
public function assertBrowserHistoryIsOnFirstPage(string $message = ''): void
{
$this->assertTrue(
class_exists(BrowserHistoryIsOnFirstPage::class),
'The assertBrowserHistoryIsOnFirstPage method requires symfony/browser-kit >= 7.4.'
);

$this->assertThatForClient(new BrowserHistoryIsOnFirstPage(), $message);
}

/**
* Asserts that the browser history is not currently on the first page.
*
* ```php
* <?php
* $I->assertBrowserHistoryIsNotOnFirstPage();
* ```
*/
public function assertBrowserHistoryIsNotOnFirstPage(string $message = ''): void
{
$this->assertTrue(
class_exists(BrowserHistoryIsOnFirstPage::class),
'The assertBrowserHistoryIsNotOnFirstPage method requires symfony/browser-kit >= 7.4.'
);

$this->assertThatForClient(new LogicalNot(new BrowserHistoryIsOnFirstPage()), $message);
}

/**
* Asserts that the browser history is currently on the last page.
*
* ```php
* <?php
* $I->assertBrowserHistoryIsOnLastPage();
* ```
*/
public function assertBrowserHistoryIsOnLastPage(string $message = ''): void
{
$this->assertTrue(
class_exists(BrowserHistoryIsOnLastPage::class),
'The assertBrowserHistoryIsOnLastPage method requires symfony/browser-kit >= 7.4.'
);

$this->assertThatForClient(new BrowserHistoryIsOnLastPage(), $message);
}

/**
* Asserts that the browser history is not currently on the last page.
*
* ```php
* <?php
* $I->assertBrowserHistoryIsNotOnLastPage();
* ```
*/
public function assertBrowserHistoryIsNotOnLastPage(string $message = ''): void
{
$this->assertTrue(
class_exists(BrowserHistoryIsOnLastPage::class),
'The assertBrowserHistoryIsNotOnLastPage method requires symfony/browser-kit >= 7.4.'
);

$this->assertThatForClient(new LogicalNot(new BrowserHistoryIsOnLastPage()), $message);
}

/**
* Asserts that the specified request attribute matches the expected value.
*
Expand Down
94 changes: 94 additions & 0 deletions src/Codeception/Module/Symfony/DomCrawlerAssertionsTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@
namespace Codeception\Module\Symfony;

use PHPUnit\Framework\Constraint\Constraint;
use PHPUnit\Framework\Constraint\LogicalAnd;
use PHPUnit\Framework\Constraint\LogicalNot;
use Symfony\Component\DomCrawler\Test\Constraint\CrawlerAnySelectorTextContains;
use Symfony\Component\DomCrawler\Test\Constraint\CrawlerAnySelectorTextSame;
use Symfony\Component\DomCrawler\Test\Constraint\CrawlerSelectorAttributeValueSame;
use Symfony\Component\DomCrawler\Test\Constraint\CrawlerSelectorCount;
use Symfony\Component\DomCrawler\Test\Constraint\CrawlerSelectorExists;
use Symfony\Component\DomCrawler\Test\Constraint\CrawlerSelectorTextContains;
use Symfony\Component\DomCrawler\Test\Constraint\CrawlerSelectorTextSame;

use function class_exists;
use function sprintf;

trait DomCrawlerAssertionsTrait
Expand Down Expand Up @@ -119,6 +124,20 @@ public function assertSelectorNotExists(string $selector, string $message = ''):
$this->assertThatCrawler(new LogicalNot(new CrawlerSelectorExists($selector)), $message);
}

/**
* Asserts that the given selector matches the expected number of elements.
*
* ```php
* <?php
* $I->assertSelectorCount(3, '.item');
* ```
*/
public function assertSelectorCount(int $expectedCount, string $selector, string $message = ''): void
{
$this->assertDomCrawlerConstraintAvailable(CrawlerSelectorCount::class, __FUNCTION__);
$this->assertThatCrawler(new CrawlerSelectorCount($expectedCount, $selector), $message);
}

/**
* Asserts that the first element matching the given selector contains the expected text.
*
Expand All @@ -132,6 +151,48 @@ public function assertSelectorTextContains(string $selector, string $text, strin
$this->assertThatCrawler(new CrawlerSelectorTextContains($selector, $text), $message);
}

/**
* Asserts that at least one element matching the given selector contains the expected text.
*
* ```php
* <?php
* $I->assertAnySelectorTextContains('.item', 'Available');
* ```
*/
public function assertAnySelectorTextContains(string $selector, string $text, string $message = ''): void
{
$this->assertDomCrawlerConstraintAvailable(CrawlerAnySelectorTextContains::class, __FUNCTION__);

$this->assertThatCrawler(
LogicalAnd::fromConstraints(
new CrawlerSelectorExists($selector),
new CrawlerAnySelectorTextContains($selector, $text)
),
$message
);
}

/**
* Asserts that at least one element matching the given selector has exactly the expected text.
*
* ```php
* <?php
* $I->assertAnySelectorTextSame('.item', 'In stock');
* ```
*/
public function assertAnySelectorTextSame(string $selector, string $text, string $message = ''): void
{
$this->assertDomCrawlerConstraintAvailable(CrawlerAnySelectorTextSame::class, __FUNCTION__);

$this->assertThatCrawler(
LogicalAnd::fromConstraints(
new CrawlerSelectorExists($selector),
new CrawlerAnySelectorTextSame($selector, $text)
),
$message
);
}

/**
* Asserts that the first element matching the given selector does not contain the expected text.
*
Expand All @@ -145,6 +206,27 @@ public function assertSelectorTextNotContains(string $selector, string $text, st
$this->assertThatCrawler(new LogicalNot(new CrawlerSelectorTextContains($selector, $text)), $message);
}

/**
* Asserts that no element matching the given selector contains the expected text.
*
* ```php
* <?php
* $I->assertAnySelectorTextNotContains('.item', 'Error');
* ```
*/
public function assertAnySelectorTextNotContains(string $selector, string $text, string $message = ''): void
{
$this->assertDomCrawlerConstraintAvailable(CrawlerAnySelectorTextContains::class, __FUNCTION__);

$this->assertThatCrawler(
LogicalAnd::fromConstraints(
new CrawlerSelectorExists($selector),
new LogicalNot(new CrawlerAnySelectorTextContains($selector, $text))
),
$message
);
}

/**
* Asserts that the text of the first element matching the given selector equals the expected text.
*
Expand Down Expand Up @@ -184,4 +266,16 @@ private function assertInputValue(string $fieldName, string $expectedValue, bool
}
$this->assertThatCrawler($constraint, $context);
}

private function assertDomCrawlerConstraintAvailable(string $constraintClass, string $function): void
{
$this->assertTrue(
class_exists($constraintClass),
sprintf(
"The '%s' assertion is not available with your installed symfony/dom-crawler version. Missing constraint: %s",
$function,
$constraintClass
)
);
}
}
45 changes: 44 additions & 1 deletion src/Codeception/Module/Symfony/MailerAssertionsTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,21 @@ public function seeEmailIsSent(int $expectedCount = 1): void
$this->assertThat($this->getMessageMailerEvents(), new MailerConstraint\EmailCount($expectedCount));
}

/**
* Returns all mailer events for the given transport.
*
* ```php
* <?php
* $events = $I->getMailerEvents();
* ```
*
* @return MessageEvent[]
*/
public function getMailerEvents(?string $transport = null): array
{
return $this->getMessageMailerEvents()->getEvents($transport);
}

/**
* Returns the mailer event at the specified index.
*
Expand All @@ -155,7 +170,35 @@ public function seeEmailIsSent(int $expectedCount = 1): void
*/
public function getMailerEvent(int $index = 0, ?string $transport = null): ?MessageEvent
{
return $this->getMessageMailerEvents()->getEvents($transport)[$index] ?? null;
return $this->getMailerEvents($transport)[$index] ?? null;
}

/**
* Returns all sent mailer messages for the given transport.
*
* ```php
* <?php
* $messages = $I->getMailerMessages();
* ```
*
* @return RawMessage[]
*/
public function getMailerMessages(?string $transport = null): array
{
return $this->getMessageMailerEvents()->getMessages($transport);
}

/**
* Returns the mailer message at the specified index.
*
* ```php
* <?php
* $message = $I->getMailerMessage();
* ```
*/
public function getMailerMessage(int $index = 0, ?string $transport = null): ?RawMessage
{
return $this->getMailerMessages($transport)[$index] ?? null;
}

protected function grabLastSentRawMessage(): ?RawMessage
Expand Down
57 changes: 57 additions & 0 deletions src/Codeception/Module/Symfony/MimeAssertionsTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Symfony\Component\Mime\RawMessage;
use Symfony\Component\Mime\Test\Constraint as MimeConstraint;

use function class_exists;
use function sprintf;

trait MimeAssertionsTrait
Expand All @@ -30,6 +31,20 @@ public function assertEmailAddressContains(string $headerName, string $expectedV
$this->assertThat($this->getMessageOrFail($email, __FUNCTION__), new MimeConstraint\EmailAddressContains($headerName, $expectedValue));
}

/**
* Verify that an email does not contain the given address in the specified header.
* If no Message is specified, the last sent message is used instead.
*
* ```php
* <?php
* $I->assertEmailAddressNotContains('To', 'john_doe@example.com');
* ```
*/
public function assertEmailAddressNotContains(string $headerName, string $expectedValue, ?Message $email = null): void
{
$this->assertThat($this->getMessageOrFail($email, __FUNCTION__), new LogicalNot(new MimeConstraint\EmailAddressContains($headerName, $expectedValue)));
}

/**
* Verify that an email has the specified number `$count` of attachments.
* If no Email is specified, the last sent email is used instead.
Expand Down Expand Up @@ -158,6 +173,36 @@ public function assertEmailTextBodyNotContains(string $text, ?Email $email = nul
$this->assertThat($this->getMessageOrFail($email, __FUNCTION__), new LogicalNot(new MimeConstraint\EmailTextBodyContains($text)));
}

/**
* Verify that an email subject contains `$expectedValue`.
* If no Email is specified, the last sent email is used instead.
*
* ```php
* <?php
* $I->assertEmailSubjectContains('Account created successfully');
* ```
*/
public function assertEmailSubjectContains(string $expectedValue, ?Email $email = null): void
{
$this->assertMimeConstraintAvailable(MimeConstraint\EmailSubjectContains::class, __FUNCTION__);
$this->assertThat($this->getMessageOrFail($email, __FUNCTION__), new MimeConstraint\EmailSubjectContains($expectedValue));
}

/**
* Verify that an email subject does not contain `$expectedValue`.
* If no Email is specified, the last sent email is used instead.
*
* ```php
* <?php
* $I->assertEmailSubjectNotContains('Password reset');
* ```
*/
public function assertEmailSubjectNotContains(string $expectedValue, ?Email $email = null): void
{
$this->assertMimeConstraintAvailable(MimeConstraint\EmailSubjectContains::class, __FUNCTION__);
$this->assertThat($this->getMessageOrFail($email, __FUNCTION__), new LogicalNot(new MimeConstraint\EmailSubjectContains($expectedValue)));
}

/**
* Resolves a Message for assertion or fails the test.
*
Expand All @@ -174,4 +219,16 @@ private function getMessageOrFail(?Message $message, string $caller): Message

return $message;
}

private function assertMimeConstraintAvailable(string $constraintClass, string $function): void
{
$this->assertTrue(
class_exists($constraintClass),
sprintf(
"The '%s' assertion is not available with your installed symfony/mime version. Missing constraint: %s",
$function,
$constraintClass
)
);
}
}
Loading