Skip to content

Commit

Permalink
get the inherent Symfony assertions
Browse files Browse the repository at this point in the history
  • Loading branch information
TavoNiievez committed Aug 13, 2024
1 parent 9b77251 commit 1987a3d
Show file tree
Hide file tree
Showing 5 changed files with 424 additions and 57 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"type": "library",
"keywords": [
"codeception",
"functional testing",
"symfony"
],
"authors": [
Expand Down
2 changes: 2 additions & 0 deletions src/Codeception/Module/Symfony.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Codeception\Module\Symfony\BrowserAssertionsTrait;
use Codeception\Module\Symfony\ConsoleAssertionsTrait;
use Codeception\Module\Symfony\DoctrineAssertionsTrait;
use Codeception\Module\Symfony\DomCrawlerAssertionsTrait;
use Codeception\Module\Symfony\EventsAssertionsTrait;
use Codeception\Module\Symfony\FormAssertionsTrait;
use Codeception\Module\Symfony\MailerAssertionsTrait;
Expand Down Expand Up @@ -135,6 +136,7 @@ class Symfony extends Framework implements DoctrineProvider, PartedModule
use BrowserAssertionsTrait;
use ConsoleAssertionsTrait;
use DoctrineAssertionsTrait;
use DomCrawlerAssertionsTrait;
use EventsAssertionsTrait;
use FormAssertionsTrait;
use MailerAssertionsTrait;
Expand Down
195 changes: 194 additions & 1 deletion src/Codeception/Module/Symfony/BrowserAssertionsTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,191 @@

namespace Codeception\Module\Symfony;

use PHPUnit\Framework\Constraint\Constraint;
use PHPUnit\Framework\Constraint\LogicalAnd;
use PHPUnit\Framework\Constraint\LogicalNot;
use Symfony\Component\BrowserKit\Test\Constraint\BrowserCookieValueSame;
use Symfony\Component\BrowserKit\Test\Constraint\BrowserHasCookie;
use Symfony\Component\HttpFoundation\Test\Constraint\RequestAttributeValueSame;
use Symfony\Component\HttpFoundation\Test\Constraint\ResponseCookieValueSame;
use Symfony\Component\HttpFoundation\Test\Constraint\ResponseFormatSame;
use Symfony\Component\HttpFoundation\Test\Constraint\ResponseHasCookie;
use Symfony\Component\HttpFoundation\Test\Constraint\ResponseHasHeader;
use Symfony\Component\HttpFoundation\Test\Constraint\ResponseHeaderLocationSame;
use Symfony\Component\HttpFoundation\Test\Constraint\ResponseHeaderSame;
use Symfony\Component\HttpFoundation\Test\Constraint\ResponseIsRedirected;
use Symfony\Component\HttpFoundation\Test\Constraint\ResponseIsSuccessful;
use Symfony\Component\HttpFoundation\Test\Constraint\ResponseIsUnprocessable;
use Symfony\Component\HttpFoundation\Test\Constraint\ResponseStatusCodeSame;
use function sprintf;

trait BrowserAssertionsTrait
{
/**
* Asserts the response format returned by the `Response::getFormat()` method is the same as the expected value.
*/
public function assertResponseFormatSame(?string $expectedFormat, string $message = ''): void
{
$this->assertThatForResponse(new ResponseFormatSame($this->getClient()->getRequest(), $expectedFormat), $message);
}

/**
* Asserts a specific HTTP status code.
*/
public function assertResponseStatusCodeSame(int $expectedCode, string $message = '', bool $verbose = true): void
{
$this->assertThatForResponse(new ResponseStatusCodeSame($expectedCode, $verbose), $message);
}

/**
* Asserts the response is a redirect response (optionally, you can check the target location and status code).
* The excepted location can be either an absolute or a relative path.
*/
public function assertResponseRedirects(?string $expectedLocation = null, ?int $expectedCode = null, string $message = '', bool $verbose = true): void
{
$constraint = new ResponseIsRedirected($verbose);
if ($expectedLocation) {
if (class_exists(ResponseHeaderLocationSame::class)) {
$locationConstraint = new ResponseHeaderLocationSame($this->getClient()->getRequest(), $expectedLocation);
} else {
$locationConstraint = new ResponseHeaderSame('Location', $expectedLocation);
}

$constraint = LogicalAnd::fromConstraints($constraint, $locationConstraint);
}
if ($expectedCode) {
$constraint = LogicalAnd::fromConstraints($constraint, new ResponseStatusCodeSame($expectedCode));
}

$this->assertThatForResponse($constraint, $message);
}

/**
* Asserts the given header is available on the response, e.g. assertResponseHasHeader('content-type');.
*/
public function assertResponseHasHeader(string $headerName, string $message = ''): void
{
$this->assertThatForResponse(new ResponseHasHeader($headerName), $message);
}

/**
* Asserts the given header is not available on the response, e.g. assertResponseNotHasHeader('content-type');.
*/
public function assertResponseNotHasHeader(string $headerName, string $message = ''): void
{
$this->assertThatForResponse(new LogicalNot(new ResponseHasHeader($headerName)), $message);
}

/**
* Asserts the given header does contain the expected value on the response,
* e.g. assertResponseHeaderSame('content-type', 'application/octet-stream');.
*/
public function assertResponseHeaderSame(string $headerName, string $expectedValue, string $message = ''): void
{
$this->assertThatForResponse(new ResponseHeaderSame($headerName, $expectedValue), $message);
}

/**
* Asserts the given header does not contain the expected value on the response,
* e.g. assertResponseHeaderNotSame('content-type', 'application/octet-stream');.
*/
public function assertResponseHeaderNotSame(string $headerName, string $expectedValue, string $message = ''): void
{
$this->assertThatForResponse(new LogicalNot(new ResponseHeaderSame($headerName, $expectedValue)), $message);
}

/**
* Asserts the given cookie is present in the response (optionally checking for a specific cookie path or domain).
*/
public function assertResponseHasCookie(string $name, string $path = '/', ?string $domain = null, string $message = ''): void
{
$this->assertThatForResponse(new ResponseHasCookie($name, $path, $domain), $message);
}

/**
* Asserts the given cookie is not present in the response (optionally checking for a specific cookie path or domain).
*/
public function assertResponseNotHasCookie(string $name, string $path = '/', ?string $domain = null, string $message = ''): void
{
$this->assertThatForResponse(new LogicalNot(new ResponseHasCookie($name, $path, $domain)), $message);
}

/**
* Asserts the given cookie is present and set to the expected value.
*/
public function assertResponseCookieValueSame(string $name, string $expectedValue, string $path = '/', ?string $domain = null, string $message = ''): void
{
$this->assertThatForResponse(LogicalAnd::fromConstraints(
new ResponseHasCookie($name, $path, $domain),
new ResponseCookieValueSame($name, $expectedValue, $path, $domain)
), $message);
}

/**
* Asserts the response is unprocessable (HTTP status is 422)
*/
public function assertResponseIsUnprocessable(string $message = '', bool $verbose = true): void
{
$this->assertThatForResponse(new ResponseIsUnprocessable($verbose), $message);
}

/**
* Asserts that the test Client does have the given cookie set (meaning, the cookie was set by any response in the test).
*/
public function assertBrowserHasCookie(string $name, string $path = '/', ?string $domain = null, string $message = ''): void
{
$this->assertThatForClient(new BrowserHasCookie($name, $path, $domain), $message);
}

protected function assertThatForClient(Constraint $constraint, string $message = ''): void
{
$this->assertThat($this->getClient(), $constraint, $message);
}

/**
* Asserts that the test Client does not have the given cookie set (meaning, the cookie was set by any response in the test).
*/
public function assertBrowserNotHasCookie(string $name, string $path = '/', ?string $domain = null, string $message = ''): void
{
$this->assertThatForClient(new LogicalNot(new BrowserHasCookie($name, $path, $domain)), $message);
}

/**
* Asserts the given cookie in the test Client is set to the expected value.
*/
public function assertBrowserCookieValueSame(string $name, string $expectedValue, bool $raw = false, string $path = '/', ?string $domain = null, string $message = ''): void
{
$this->assertThatForClient(LogicalAnd::fromConstraints(
new BrowserHasCookie($name, $path, $domain),
new BrowserCookieValueSame($name, $expectedValue, $raw, $path, $domain)
), $message);
}

/**
* Asserts the given request attribute is set to the expected value.
*/
public function assertRequestAttributeValueSame(string $name, string $expectedValue, string $message = ''): void
{
$this->assertThat($this->getClient()->getRequest(), new RequestAttributeValueSame($name, $expectedValue), $message);
}

/**
* Asserts the request matches the given route and optionally route parameters.
*/
public function assertRouteSame(string $expectedRoute, array $parameters = [], string $message = ''): void
{
$constraint = new RequestAttributeValueSame('_route', $expectedRoute);
$constraints = [];
foreach ($parameters as $key => $value) {
$constraints[] = new RequestAttributeValueSame($key, $value);
}
if ($constraints) {
$constraint = LogicalAnd::fromConstraints($constraint, ...$constraints);
}

$this->assertThat($this->getClient()->getRequest(), $constraint, $message);
}

/**
* Reboot client's kernel.
* Can be used to manually reboot kernel when 'rebootable_client' => false
Expand Down Expand Up @@ -50,7 +230,15 @@ public function seePageIsAvailable(?string $url = null): void
$this->seeInCurrentUrl($url);
}

$this->assertThat($this->getClient()->getResponse(), new ResponseIsSuccessful());
$this->assertResponseIsSuccessful();
}

/**
* Asserts that the response was successful (HTTP status is 2xx).
*/
public function assertResponseIsSuccessful(string $message = '', bool $verbose = true): void
{
$this->assertThatForResponse(new ResponseIsSuccessful($verbose), $message);
}

/**
Expand Down Expand Up @@ -104,4 +292,9 @@ public function submitSymfonyForm(string $name, array $fields): void

$this->submitForm($selector, $params, $button);
}

protected function assertThatForResponse(Constraint $constraint, string $message = ''): void
{
$this->assertThat($this->getClient()->getResponse(), $constraint, $message);
}
}
137 changes: 137 additions & 0 deletions src/Codeception/Module/Symfony/DomCrawlerAssertionsTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<?php

declare(strict_types=1);

namespace Codeception\Module\Symfony;

use PHPUnit\Framework\Constraint\LogicalAnd;
use PHPUnit\Framework\Constraint\LogicalNot;
use Symfony\Component\DomCrawler\Crawler;
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;

trait DomCrawlerAssertionsTrait
{
public function assertSelectorExists(string $selector, string $message = ''): void
{
$this->assertThat($this->getCrawler(), new CrawlerSelectorExists($selector), $message);
}

public function assertSelectorNotExists(string $selector, string $message = ''): void
{
$this->assertThat($this->getCrawler(), new LogicalNot(new CrawlerSelectorExists($selector)), $message);
}

public function assertSelectorCount(int $expectedCount, string $selector, string $message = ''): void
{
$this->assertThat($this->getCrawler(), new CrawlerSelectorCount($expectedCount, $selector), $message);
}

public function assertAnySelectorTextContains(string $selector, string $text, string $message = ''): void
{
$this->assertThat($this->getCrawler(), LogicalAnd::fromConstraints(
new CrawlerSelectorExists($selector),
new CrawlerAnySelectorTextContains($selector, $text)
), $message);
}

public function assertAnySelectorTextSame(string $selector, string $text, string $message = ''): void
{
$this->assertThat($this->getCrawler(), LogicalAnd::fromConstraints(
new CrawlerSelectorExists($selector),
new CrawlerAnySelectorTextSame($selector, $text)
), $message);
}

public function assertSelectorTextNotContains(string $selector, string $text, string $message = ''): void
{
$this->assertThat($this->getCrawler(), LogicalAnd::fromConstraints(
new CrawlerSelectorExists($selector),
new LogicalNot(new CrawlerSelectorTextContains($selector, $text))
), $message);
}

public function assertAnySelectorTextNotContains(string $selector, string $text, string $message = ''): void
{
$this->assertThat($this->getCrawler(), LogicalAnd::fromConstraints(
new CrawlerSelectorExists($selector),
new LogicalNot(new CrawlerAnySelectorTextContains($selector, $text))
), $message);
}

public function assertPageTitleSame(string $expectedTitle, string $message = ''): void
{
$this->assertSelectorTextSame('title', $expectedTitle, $message);
}

public function assertSelectorTextSame(string $selector, string $text, string $message = ''): void
{
$this->assertThat($this->getCrawler(), LogicalAnd::fromConstraints(
new CrawlerSelectorExists($selector),
new CrawlerSelectorTextSame($selector, $text)
), $message);
}

public function assertPageTitleContains(string $expectedTitle, string $message = ''): void
{
$this->assertSelectorTextContains('title', $expectedTitle, $message);
}

public function assertSelectorTextContains(string $selector, string $text, string $message = ''): void
{
$this->assertThat($this->getCrawler(), LogicalAnd::fromConstraints(
new CrawlerSelectorExists($selector),
new CrawlerSelectorTextContains($selector, $text)
), $message);
}

public function assertInputValueSame(string $fieldName, string $expectedValue, string $message = ''): void
{
$this->assertThat($this->getCrawler(), LogicalAnd::fromConstraints(
new CrawlerSelectorExists("input[name=\"$fieldName\"]"),
new CrawlerSelectorAttributeValueSame("input[name=\"$fieldName\"]", 'value', $expectedValue)
), $message);
}

public function assertInputValueNotSame(string $fieldName, string $expectedValue, string $message = ''): void
{
$this->assertThat($this->getCrawler(), LogicalAnd::fromConstraints(
new CrawlerSelectorExists("input[name=\"$fieldName\"]"),
new LogicalNot(new CrawlerSelectorAttributeValueSame("input[name=\"$fieldName\"]", 'value', $expectedValue))
), $message);
}

/**
* Asserts that the checkbox with the given name is checked.
*/
public function assertCheckboxChecked(string $fieldName, string $message = ''): void
{
$this->assertThat(
$this->getCrawler(),
new CrawlerSelectorExists("input[name=\"$fieldName\"]:checked"),
$message
);
}

/**
* Asserts that the checkbox with the given name is not checked.
*/
public function assertCheckboxNotChecked(string $fieldName, string $message = ''): void
{
$this->assertThat(
$this->getCrawler(),
new LogicalNot(new CrawlerSelectorExists("input[name=\"$fieldName\"]:checked")),
$message
);
}

protected function getCrawler(): Crawler
{
return $this->client->getCrawler();
}
}
Loading

0 comments on commit 1987a3d

Please sign in to comment.