Skip to content

Commit 1615c3e

Browse files
committed
Add missing Symfony assertions
1 parent c350ee2 commit 1615c3e

8 files changed

Lines changed: 434 additions & 2 deletions

src/Codeception/Module/Symfony/BrowserAssertionsTrait.php

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
use PHPUnit\Framework\Constraint\LogicalNot;
1010
use Symfony\Component\BrowserKit\Test\Constraint\BrowserCookieValueSame;
1111
use Symfony\Component\BrowserKit\Test\Constraint\BrowserHasCookie;
12+
use Symfony\Component\BrowserKit\Test\Constraint\BrowserHistoryIsOnFirstPage;
13+
use Symfony\Component\BrowserKit\Test\Constraint\BrowserHistoryIsOnLastPage;
1214
use Symfony\Component\HttpFoundation\Test\Constraint\RequestAttributeValueSame;
1315
use Symfony\Component\HttpFoundation\Test\Constraint\ResponseCookieValueSame;
1416
use Symfony\Component\HttpFoundation\Test\Constraint\ResponseFormatSame;
@@ -71,6 +73,78 @@ public function assertBrowserNotHasCookie(string $name, string $path = '/', ?str
7173
$this->assertThatForClient(new LogicalNot(new BrowserHasCookie($name, $path, $domain)), $message);
7274
}
7375

76+
/**
77+
* Asserts that the browser history is currently on the first page.
78+
*
79+
* ```php
80+
* <?php
81+
* $I->assertBrowserHistoryIsOnFirstPage();
82+
* ```
83+
*/
84+
public function assertBrowserHistoryIsOnFirstPage(string $message = ''): void
85+
{
86+
$this->assertTrue(
87+
class_exists(BrowserHistoryIsOnFirstPage::class),
88+
'The assertBrowserHistoryIsOnFirstPage method requires symfony/browser-kit >= 7.4.'
89+
);
90+
91+
$this->assertThatForClient(new BrowserHistoryIsOnFirstPage(), $message);
92+
}
93+
94+
/**
95+
* Asserts that the browser history is not currently on the first page.
96+
*
97+
* ```php
98+
* <?php
99+
* $I->assertBrowserHistoryIsNotOnFirstPage();
100+
* ```
101+
*/
102+
public function assertBrowserHistoryIsNotOnFirstPage(string $message = ''): void
103+
{
104+
$this->assertTrue(
105+
class_exists(BrowserHistoryIsOnFirstPage::class),
106+
'The assertBrowserHistoryIsNotOnFirstPage method requires symfony/browser-kit >= 7.4.'
107+
);
108+
109+
$this->assertThatForClient(new LogicalNot(new BrowserHistoryIsOnFirstPage()), $message);
110+
}
111+
112+
/**
113+
* Asserts that the browser history is currently on the last page.
114+
*
115+
* ```php
116+
* <?php
117+
* $I->assertBrowserHistoryIsOnLastPage();
118+
* ```
119+
*/
120+
public function assertBrowserHistoryIsOnLastPage(string $message = ''): void
121+
{
122+
$this->assertTrue(
123+
class_exists(BrowserHistoryIsOnLastPage::class),
124+
'The assertBrowserHistoryIsOnLastPage method requires symfony/browser-kit >= 7.4.'
125+
);
126+
127+
$this->assertThatForClient(new BrowserHistoryIsOnLastPage(), $message);
128+
}
129+
130+
/**
131+
* Asserts that the browser history is not currently on the last page.
132+
*
133+
* ```php
134+
* <?php
135+
* $I->assertBrowserHistoryIsNotOnLastPage();
136+
* ```
137+
*/
138+
public function assertBrowserHistoryIsNotOnLastPage(string $message = ''): void
139+
{
140+
$this->assertTrue(
141+
class_exists(BrowserHistoryIsOnLastPage::class),
142+
'The assertBrowserHistoryIsNotOnLastPage method requires symfony/browser-kit >= 7.4.'
143+
);
144+
145+
$this->assertThatForClient(new LogicalNot(new BrowserHistoryIsOnLastPage()), $message);
146+
}
147+
74148
/**
75149
* Asserts that the specified request attribute matches the expected value.
76150
*

src/Codeception/Module/Symfony/DomCrawlerAssertionsTrait.php

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,19 @@
55
namespace Codeception\Module\Symfony;
66

77
use PHPUnit\Framework\Constraint\Constraint;
8+
use PHPUnit\Framework\Constraint\LogicalAnd;
89
use PHPUnit\Framework\Constraint\LogicalNot;
10+
use Symfony\Component\DomCrawler\Test\Constraint\CrawlerAnySelectorTextContains;
11+
use Symfony\Component\DomCrawler\Test\Constraint\CrawlerAnySelectorTextSame;
912
use Symfony\Component\DomCrawler\Test\Constraint\CrawlerSelectorAttributeValueSame;
13+
use Symfony\Component\DomCrawler\Test\Constraint\CrawlerSelectorCount;
1014
use Symfony\Component\DomCrawler\Test\Constraint\CrawlerSelectorExists;
1115
use Symfony\Component\DomCrawler\Test\Constraint\CrawlerSelectorTextContains;
1216
use Symfony\Component\DomCrawler\Test\Constraint\CrawlerSelectorTextSame;
1317

18+
use function class_exists;
19+
use function sprintf;
20+
1421
trait DomCrawlerAssertionsTrait
1522
{
1623
/**
@@ -117,6 +124,20 @@ public function assertSelectorNotExists(string $selector, string $message = ''):
117124
$this->assertThatCrawler(new LogicalNot(new CrawlerSelectorExists($selector)), $message);
118125
}
119126

127+
/**
128+
* Asserts that the given selector matches the expected number of elements.
129+
*
130+
* ```php
131+
* <?php
132+
* $I->assertSelectorCount(3, '.item');
133+
* ```
134+
*/
135+
public function assertSelectorCount(int $expectedCount, string $selector, string $message = ''): void
136+
{
137+
$this->assertDomCrawlerConstraintAvailable(CrawlerSelectorCount::class, __FUNCTION__);
138+
$this->assertThatCrawler(new CrawlerSelectorCount($expectedCount, $selector), $message);
139+
}
140+
120141
/**
121142
* Asserts that the first element matching the given selector contains the expected text.
122143
*
@@ -130,6 +151,48 @@ public function assertSelectorTextContains(string $selector, string $text, strin
130151
$this->assertThatCrawler(new CrawlerSelectorTextContains($selector, $text), $message);
131152
}
132153

154+
/**
155+
* Asserts that at least one element matching the given selector contains the expected text.
156+
*
157+
* ```php
158+
* <?php
159+
* $I->assertAnySelectorTextContains('.item', 'Available');
160+
* ```
161+
*/
162+
public function assertAnySelectorTextContains(string $selector, string $text, string $message = ''): void
163+
{
164+
$this->assertDomCrawlerConstraintAvailable(CrawlerAnySelectorTextContains::class, __FUNCTION__);
165+
166+
$this->assertThatCrawler(
167+
LogicalAnd::fromConstraints(
168+
new CrawlerSelectorExists($selector),
169+
new CrawlerAnySelectorTextContains($selector, $text)
170+
),
171+
$message
172+
);
173+
}
174+
175+
/**
176+
* Asserts that at least one element matching the given selector has exactly the expected text.
177+
*
178+
* ```php
179+
* <?php
180+
* $I->assertAnySelectorTextSame('.item', 'In stock');
181+
* ```
182+
*/
183+
public function assertAnySelectorTextSame(string $selector, string $text, string $message = ''): void
184+
{
185+
$this->assertDomCrawlerConstraintAvailable(CrawlerAnySelectorTextSame::class, __FUNCTION__);
186+
187+
$this->assertThatCrawler(
188+
LogicalAnd::fromConstraints(
189+
new CrawlerSelectorExists($selector),
190+
new CrawlerAnySelectorTextSame($selector, $text)
191+
),
192+
$message
193+
);
194+
}
195+
133196
/**
134197
* Asserts that the first element matching the given selector does not contain the expected text.
135198
*
@@ -143,6 +206,27 @@ public function assertSelectorTextNotContains(string $selector, string $text, st
143206
$this->assertThatCrawler(new LogicalNot(new CrawlerSelectorTextContains($selector, $text)), $message);
144207
}
145208

209+
/**
210+
* Asserts that no element matching the given selector contains the expected text.
211+
*
212+
* ```php
213+
* <?php
214+
* $I->assertAnySelectorTextNotContains('.item', 'Error');
215+
* ```
216+
*/
217+
public function assertAnySelectorTextNotContains(string $selector, string $text, string $message = ''): void
218+
{
219+
$this->assertDomCrawlerConstraintAvailable(CrawlerAnySelectorTextContains::class, __FUNCTION__);
220+
221+
$this->assertThatCrawler(
222+
LogicalAnd::fromConstraints(
223+
new CrawlerSelectorExists($selector),
224+
new LogicalNot(new CrawlerAnySelectorTextContains($selector, $text))
225+
),
226+
$message
227+
);
228+
}
229+
146230
/**
147231
* Asserts that the text of the first element matching the given selector equals the expected text.
148232
*
@@ -179,4 +263,16 @@ private function assertInputValue(string $fieldName, string $value, bool $same,
179263
}
180264
$this->assertThatCrawler($constraint, $message);
181265
}
266+
267+
private function assertDomCrawlerConstraintAvailable(string $constraintClass, string $function): void
268+
{
269+
$this->assertTrue(
270+
class_exists($constraintClass),
271+
sprintf(
272+
"The '%s' assertion is not available with your installed symfony/dom-crawler version. Missing constraint: %s",
273+
$function,
274+
$constraintClass
275+
)
276+
);
277+
}
182278
}

src/Codeception/Module/Symfony/MailerAssertionsTrait.php

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Symfony\Component\Mailer\EventListener\MessageLoggerListener;
1212
use Symfony\Component\Mailer\Test\Constraint as MailerConstraint;
1313
use Symfony\Component\Mime\Email;
14+
use Symfony\Component\Mime\RawMessage;
1415

1516
use function array_key_last;
1617

@@ -148,6 +149,21 @@ public function seeEmailIsSent(int $expectedCount = 1): void
148149
$this->assertThat($this->getMessageMailerEvents(), new MailerConstraint\EmailCount($expectedCount));
149150
}
150151

152+
/**
153+
* Returns all mailer events for the given transport.
154+
*
155+
* ```php
156+
* <?php
157+
* $events = $I->getMailerEvents();
158+
* ```
159+
*
160+
* @return MessageEvent[]
161+
*/
162+
public function getMailerEvents(?string $transport = null): array
163+
{
164+
return $this->getMessageMailerEvents()->getEvents($transport);
165+
}
166+
151167
/**
152168
* Returns the mailer event at the specified index.
153169
*
@@ -158,7 +174,35 @@ public function seeEmailIsSent(int $expectedCount = 1): void
158174
*/
159175
public function getMailerEvent(int $index = 0, ?string $transport = null): ?MessageEvent
160176
{
161-
return $this->getMessageMailerEvents()->getEvents($transport)[$index] ?? null;
177+
return $this->getMailerEvents($transport)[$index] ?? null;
178+
}
179+
180+
/**
181+
* Returns all sent mailer messages for the given transport.
182+
*
183+
* ```php
184+
* <?php
185+
* $messages = $I->getMailerMessages();
186+
* ```
187+
*
188+
* @return RawMessage[]
189+
*/
190+
public function getMailerMessages(?string $transport = null): array
191+
{
192+
return $this->getMessageMailerEvents()->getMessages($transport);
193+
}
194+
195+
/**
196+
* Returns the mailer message at the specified index.
197+
*
198+
* ```php
199+
* <?php
200+
* $message = $I->getMailerMessage();
201+
* ```
202+
*/
203+
public function getMailerMessage(int $index = 0, ?string $transport = null): ?RawMessage
204+
{
205+
return $this->getMailerMessages($transport)[$index] ?? null;
162206
}
163207

164208
protected function getMessageMailerEvents(): MessageEvents

src/Codeception/Module/Symfony/MimeAssertionsTrait.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Symfony\Component\Mime\Email;
1010
use Symfony\Component\Mime\Test\Constraint as MimeConstraint;
1111

12+
use function class_exists;
1213
use function sprintf;
1314

1415
trait MimeAssertionsTrait
@@ -29,6 +30,22 @@ public function assertEmailAddressContains(string $headerName, string $expectedV
2930
$this->assertThat($email, new MimeConstraint\EmailAddressContains($headerName, $expectedValue));
3031
}
3132

33+
/**
34+
* Verify that an email does not contain the given address in the specified header.
35+
* If the Email object is not specified, the last email sent is used instead.
36+
*
37+
* ```php
38+
* <?php
39+
* $I->assertEmailAddressNotContains('To', 'john_doe@example.com');
40+
* ```
41+
*/
42+
public function assertEmailAddressNotContains(string $headerName, string $expectedValue, ?Email $email = null): void
43+
{
44+
$this->assertMimeConstraintAvailable(MimeConstraint\EmailAddressContains::class, __FUNCTION__);
45+
$email = $this->verifyEmailObject($email, __FUNCTION__);
46+
$this->assertThat($email, new LogicalNot(new MimeConstraint\EmailAddressContains($headerName, $expectedValue)));
47+
}
48+
3249
/**
3350
* Verify that an email has sent the specified number `$count` of attachments.
3451
* If the Email object is not specified, the last email sent is used instead.
@@ -166,6 +183,38 @@ public function assertEmailTextBodyNotContains(string $text, ?Email $email = nul
166183
$this->assertThat($email, new LogicalNot(new MimeConstraint\EmailTextBodyContains($text)));
167184
}
168185

186+
/**
187+
* Verify that an email subject contains `$expectedValue`.
188+
* If the Email object is not specified, the last email sent is used instead.
189+
*
190+
* ```php
191+
* <?php
192+
* $I->assertEmailSubjectContains('Account created successfully');
193+
* ```
194+
*/
195+
public function assertEmailSubjectContains(string $expectedValue, ?Email $email = null): void
196+
{
197+
$this->assertMimeConstraintAvailable(MimeConstraint\EmailSubjectContains::class, __FUNCTION__);
198+
$email = $this->verifyEmailObject($email, __FUNCTION__);
199+
$this->assertThat($email, new MimeConstraint\EmailSubjectContains($expectedValue));
200+
}
201+
202+
/**
203+
* Verify that an email subject does not contain `$expectedValue`.
204+
* If the Email object is not specified, the last email sent is used instead.
205+
*
206+
* ```php
207+
* <?php
208+
* $I->assertEmailSubjectNotContains('Password reset');
209+
* ```
210+
*/
211+
public function assertEmailSubjectNotContains(string $expectedValue, ?Email $email = null): void
212+
{
213+
$this->assertMimeConstraintAvailable(MimeConstraint\EmailSubjectContains::class, __FUNCTION__);
214+
$email = $this->verifyEmailObject($email, __FUNCTION__);
215+
$this->assertThat($email, new LogicalNot(new MimeConstraint\EmailSubjectContains($expectedValue)));
216+
}
217+
169218
/**
170219
* Returns the last email sent if $email is null. If no email has been sent it fails.
171220
*/
@@ -177,4 +226,16 @@ private function verifyEmailObject(?Email $email, string $function): Email
177226
sprintf($errorMsgTemplate, $function)
178227
);
179228
}
229+
230+
private function assertMimeConstraintAvailable(string $constraintClass, string $function): void
231+
{
232+
$this->assertTrue(
233+
class_exists($constraintClass),
234+
sprintf(
235+
"The '%s' assertion is not available with your installed symfony/mime version. Missing constraint: %s",
236+
$function,
237+
$constraintClass
238+
)
239+
);
240+
}
180241
}

0 commit comments

Comments
 (0)