5
5
namespace Codeception \Module \Symfony ;
6
6
7
7
use Symfony \Component \HttpKernel \DataCollector \EventDataCollector ;
8
+ use Symfony \Component \VarDumper \Cloner \Data ;
9
+
10
+ use function array_column ;
11
+ use function array_merge ;
12
+ use function in_array ;
8
13
use function is_array ;
9
14
use function is_object ;
15
+ use function is_string ;
16
+ use function str_starts_with ;
10
17
11
18
trait EventsAssertionsTrait
12
19
{
13
20
/**
14
- * Verifies that there were no events during the test.
15
- * Both regular and orphan events are checked.
21
+ * Verifies that **no** events (regular **or** orphan) were dispatched during the test.
16
22
*
17
23
* ```php
18
- * <?php
19
- * $I->dontSeeEvent();
20
- * $I->dontSeeEvent('App\MyEvent');
21
- * $I->dontSeeEvent(['App\MyEvent', 'App\MyOtherEvent']);
22
- * ```
24
+ * <?php
25
+ * $I->dontSeeEvent();
26
+ * $I->dontSeeEvent('App\ \MyEvent');
27
+ * $I->dontSeeEvent(['App\\ MyEvent', 'App\ \MyOtherEvent']);
28
+ * ```
23
29
*
24
- * @param string|string[] |null $expected
30
+ * @param string|list< string> |null $expected Fully-qualified event class(es) that must **not** appear.
25
31
*/
26
32
public function dontSeeEvent (array |string |null $ expected = null ): void
27
33
{
28
- $ actualEvents = [... array_column ( $ this ->getCalledListeners (), ' event ' )] ;
29
- $ actual = [$ this ->getOrphanedEvents (), $ actualEvents ];
34
+ $ actualEvents = $ this ->getDispatchedEventNames () ;
35
+ $ actual = [$ this ->getOrphanedEvents (), $ actualEvents ];
30
36
$ this ->assertEventTriggered (false , $ expected , $ actual );
31
37
}
32
38
33
39
/**
34
- * Verifies that one or more event listeners were not called during the test.
40
+ * Verifies that one or more ** listeners** were ** not** called during the test.
35
41
*
36
42
* ```php
37
43
* <?php
@@ -41,8 +47,8 @@ public function dontSeeEvent(array|string|null $expected = null): void
41
47
* $I->dontSeeEventListenerIsCalled('App\MyEventListener', ['my.event', 'my.other.event']);
42
48
* ```
43
49
*
44
- * @param class- string|class- string[] $expected
45
- * @param string|string[] $events
50
+ * @param string|object|list< string|object> $expected Listener(s) (class-string or instance) that must **not** be called.
51
+ * @param string|list< string> $events Event name(s) to scope the assertion to; empty array means “any event”.
46
52
*/
47
53
public function dontSeeEventListenerIsCalled (array |object |string $ expected , array |string $ events = []): void
48
54
{
@@ -59,8 +65,8 @@ public function dontSeeEventListenerIsCalled(array|object|string $expected, arra
59
65
* $I->dontSeeEventTriggered(['App\MyEvent', 'App\MyOtherEvent']);
60
66
* ```
61
67
*
62
- * @param object|string|string[] $expected
63
- * @deprecated Use ` dontSeeEventListenerIsCalled` instead.
68
+ * @param string| object|list< string|object> $expected
69
+ * @deprecated Use {@see dontSeeEventListenerIsCalled()} instead.
64
70
*/
65
71
public function dontSeeEventTriggered (array |object |string $ expected ): void
66
72
{
@@ -85,7 +91,7 @@ public function dontSeeEventTriggered(array|object|string $expected): void
85
91
* $I->dontSeeOrphanEvent(['App\MyEvent', 'App\MyOtherEvent']);
86
92
* ```
87
93
*
88
- * @param string|string[] $expected
94
+ * @param string|list< string>|null $expected Event class(es) that must NOT appear as orphan.
89
95
*/
90
96
public function dontSeeOrphanEvent (array |string |null $ expected = null ): void
91
97
{
@@ -94,29 +100,24 @@ public function dontSeeOrphanEvent(array|string|null $expected = null): void
94
100
}
95
101
96
102
/**
97
- * Verifies that one or more events were dispatched during the test.
98
- * Both regular and orphan events are checked.
99
- *
100
- * If you need to verify that expected event is not orphan,
101
- * add `dontSeeOrphanEvent` call.
102
- *
103
+ * Verifies that at least one of the given events **was** dispatched (regular **or** orphan).
103
104
* ```php
104
- * <?php
105
- * $I->seeEvent('App\MyEvent');
106
- * $I->seeEvent(['App\MyEvent', 'App\MyOtherEvent']);
107
- * ```
105
+ * <?php
106
+ * $I->seeEvent('App\MyEvent');
107
+ * $I->seeEvent(['App\MyEvent', 'App\MyOtherEvent']);
108
+ * ```
108
109
*
109
- * @param string|string[] $expected
110
+ * @param string|list< string> $expected Fully-qualified class-name(s) of the expected event(s).
110
111
*/
111
112
public function seeEvent (array |string $ expected ): void
112
113
{
113
- $ actualEvents = [... array_column ( $ this ->getCalledListeners (), ' event ' )] ;
114
- $ actual = [$ this ->getOrphanedEvents (), $ actualEvents ];
114
+ $ actualEvents = $ this ->getDispatchedEventNames () ;
115
+ $ actual = [$ this ->getOrphanedEvents (), $ actualEvents ];
115
116
$ this ->assertEventTriggered (true , $ expected , $ actual );
116
117
}
117
118
118
119
/**
119
- * Verifies that one or more event listeners were called during the test.
120
+ * Verifies that one or more ** listeners** were called during the test.
120
121
*
121
122
* ```php
122
123
* <?php
@@ -126,8 +127,8 @@ public function seeEvent(array|string $expected): void
126
127
* $I->seeEventListenerIsCalled('App\MyEventListener', ['my.event', 'my.other.event']);
127
128
* ```
128
129
*
129
- * @param class- string|class- string[] $expected
130
- * @param string|string[] $events
130
+ * @param string|object|list< string|object> $expected Listeners (class-strings or object instances).
131
+ * @param string|list< string> $events Event name(s) (empty = any).
131
132
*/
132
133
public function seeEventListenerIsCalled (array |object |string $ expected , array |string $ events = []): void
133
134
{
@@ -144,8 +145,8 @@ public function seeEventListenerIsCalled(array|object|string $expected, array|st
144
145
* $I->seeEventTriggered(['App\MyEvent', 'App\MyOtherEvent']);
145
146
* ```
146
147
*
147
- * @param object|string|string[] $expected
148
- * @deprecated Use ` seeEventListenerIsCalled` instead.
148
+ * @param string| object|list< string|object> $expected
149
+ * @deprecated Use {@see seeEventListenerIsCalled()} instead.
149
150
*/
150
151
public function seeEventTriggered (array |object |string $ expected ): void
151
152
{
@@ -157,7 +158,7 @@ public function seeEventTriggered(array|object|string $expected): void
157
158
}
158
159
159
160
/**
160
- * Verifies that one or more orphan events were dispatched during the test.
161
+ * Verifies that one or more orphan events ** were** dispatched during the test.
161
162
*
162
163
* An orphan event is an event that was triggered by manually executing the
163
164
* [`dispatch()`](https://symfony.com/doc/current/components/event_dispatcher.html#dispatch-the-event) method
@@ -169,84 +170,122 @@ public function seeEventTriggered(array|object|string $expected): void
169
170
* $I->seeOrphanEvent(['App\MyEvent', 'App\MyOtherEvent']);
170
171
* ```
171
172
*
172
- * @param string|string[] $expected
173
+ * @param string|list< string> $expected Event class-name(s) expected to be orphan.
173
174
*/
174
175
public function seeOrphanEvent (array |string $ expected ): void
175
176
{
176
177
$ actual = [$ this ->getOrphanedEvents ()];
177
178
$ this ->assertEventTriggered (true , $ expected , $ actual );
178
179
}
179
180
180
- protected function getCalledListeners (): array
181
+ /** @return list<array{event: string, pretty: string}> */
182
+ protected function getDispatchedEvents (): array
181
183
{
182
- $ eventCollector = $ this ->grabEventCollector (__FUNCTION__ );
184
+ $ eventCollector = $ this ->grabEventCollector (__FUNCTION__ );
183
185
$ calledListeners = $ eventCollector ->getCalledListeners ($ this ->getDefaultDispatcher ());
184
- return [...$ calledListeners ->getValue (true )];
186
+ $ raw = $ calledListeners instanceof Data ? $ calledListeners ->getValue (true ) : $ calledListeners ;
187
+
188
+ /** @var list<array{event:string,pretty:string}> $events */
189
+ $ events = is_array ($ raw ) ? array_values ($ raw ) : [];
190
+ return $ events ;
185
191
}
186
192
193
+ /** @return list<string> */
194
+ private function getDispatchedEventNames (): array
195
+ {
196
+ $ names = [];
197
+ foreach ($ this ->getDispatchedEvents () as $ listener ) {
198
+ $ names [] = $ listener ['event ' ];
199
+ }
200
+ return $ names ;
201
+ }
202
+
203
+ /** @return list<string> */
187
204
protected function getOrphanedEvents (): array
188
205
{
189
206
$ eventCollector = $ this ->grabEventCollector (__FUNCTION__ );
190
- $ orphanedEvents = $ eventCollector ->getOrphanedEvents ($ this ->getDefaultDispatcher ());
191
- return [...$ orphanedEvents ->getValue (true )];
207
+ $ orphaned = $ eventCollector ->getOrphanedEvents ($ this ->getDefaultDispatcher ());
208
+ $ raw = $ orphaned instanceof Data ? $ orphaned ->getValue (true ) : $ orphaned ;
209
+
210
+ /** @var list<string> $events */
211
+ $ events = is_array ($ raw ) ? array_values ($ raw ) : [];
212
+ return $ events ;
192
213
}
193
214
215
+ /**
216
+ * @param string|object|list<string|object>|null $expected
217
+ * @param list<list<string>> $actual
218
+ */
194
219
protected function assertEventTriggered (bool $ assertTrue , array |object |string |null $ expected , array $ actual ): void
195
220
{
196
221
$ actualEvents = array_merge (...$ actual );
197
222
198
- if ($ assertTrue ) $ this ->assertNotEmpty ($ actualEvents , 'No event was triggered ' );
223
+ if ($ assertTrue ) {
224
+ $ this ->assertNotEmpty ($ actualEvents , 'No event was triggered. ' );
225
+ }
199
226
if ($ expected === null ) {
200
227
$ this ->assertEmpty ($ actualEvents );
201
228
return ;
202
229
}
203
230
204
231
$ expected = is_object ($ expected ) ? $ expected ::class : $ expected ;
205
- foreach ((array )$ expected as $ expectedEvent ) {
206
- $ expectedEvent = is_object ($ expectedEvent ) ? $ expectedEvent ::class : $ expectedEvent ;
207
- $ eventTriggered = in_array ($ expectedEvent , $ actualEvents );
232
+ foreach ((array ) $ expected as $ expectedEvent ) {
233
+ $ expectedEvent = is_object ($ expectedEvent ) ? $ expectedEvent ::class : ( string ) $ expectedEvent ;
234
+ $ eventTriggered = in_array ($ expectedEvent , $ actualEvents, true );
208
235
209
236
$ message = $ assertTrue
210
- ? "The ' {$ expectedEvent }' event did not trigger "
211
- : "The ' {$ expectedEvent }' event triggered " ;
237
+ ? sprintf ("The '%s' event did not trigger " , $ expectedEvent )
238
+ : sprintf ("The '%s' event triggered " , $ expectedEvent );
239
+
212
240
$ this ->assertSame ($ assertTrue , $ eventTriggered , $ message );
213
241
}
214
242
}
215
243
244
+ /**
245
+ * @param string|object|list<string|object> $expectedListeners
246
+ * @param string|object|list<string|object>|string[] $expectedEvents
247
+ */
216
248
protected function assertListenerCalled (bool $ assertTrue , array |object |string $ expectedListeners , array |object |string $ expectedEvents ): void
217
249
{
218
250
$ expectedListeners = is_array ($ expectedListeners ) ? $ expectedListeners : [$ expectedListeners ];
219
- $ expectedEvents = is_array ($ expectedEvents ) ? $ expectedEvents : [$ expectedEvents ];
251
+ $ expectedEvents = is_array ($ expectedEvents ) ? $ expectedEvents : [$ expectedEvents ];
220
252
221
- if (empty ( $ expectedEvents) ) {
253
+ if ($ expectedEvents === [] ) {
222
254
$ expectedEvents = [null ];
223
255
} elseif (count ($ expectedListeners ) > 1 ) {
224
256
$ this ->fail ('You cannot check for events when using multiple listeners. Make multiple assertions instead. ' );
225
257
}
226
258
227
- $ actualEvents = $ this ->getCalledListeners ();
228
- if ($ assertTrue && empty ($ actualEvents )) {
229
- $ this ->fail ('No event listener was called ' );
259
+ $ actualEvents = $ this ->getDispatchedEvents ();
260
+
261
+ if ($ assertTrue && $ actualEvents === []) {
262
+ $ this ->fail ('No event listener was called. ' );
230
263
}
231
264
232
265
foreach ($ expectedListeners as $ expectedListener ) {
233
- $ expectedListener = is_object ($ expectedListener ) ? $ expectedListener::class : $ expectedListener ;
266
+ $ expectedListener = is_string ($ expectedListener ) ? $ expectedListener : $ expectedListener::class ;
234
267
235
268
foreach ($ expectedEvents as $ expectedEvent ) {
236
- $ listenerCalled = $ this ->listenerWasCalled ($ expectedListener , $ expectedEvent , $ actualEvents );
237
- $ message = "The ' {$ expectedListener }' listener was called "
238
- . ($ expectedEvent ? " for the ' {$ expectedEvent }' event " : '' );
269
+ $ eventName = is_object ($ expectedEvent ) ? $ expectedEvent ::class : ($ expectedEvent ?: null );
270
+ $ listenerCalled = $ this ->listenerWasCalled ($ expectedListener , $ eventName , $ actualEvents );
271
+
272
+ $ message = sprintf (
273
+ "The '%s' listener was %scalled%s " ,
274
+ $ expectedListener ,
275
+ $ assertTrue ? 'not ' : '' ,
276
+ $ eventName ? " for the ' {$ eventName }' event " : ''
277
+ );
278
+
239
279
$ this ->assertSame ($ assertTrue , $ listenerCalled , $ message );
240
280
}
241
281
}
242
282
}
243
283
284
+ /** @param list<array{event: string, pretty: string}> $actualEvents */
244
285
private function listenerWasCalled (string $ expectedListener , ?string $ expectedEvent , array $ actualEvents ): bool
245
286
{
246
287
foreach ($ actualEvents as $ actualEvent ) {
247
- if (
248
- isset ($ actualEvent ['pretty ' ], $ actualEvent ['event ' ])
249
- && str_starts_with ($ actualEvent ['pretty ' ], $ expectedListener )
288
+ if (str_starts_with ($ actualEvent ['pretty ' ], $ expectedListener )
250
289
&& ($ expectedEvent === null || $ actualEvent ['event ' ] === $ expectedEvent )
251
290
) {
252
291
return true ;
@@ -262,6 +301,8 @@ protected function getDefaultDispatcher(): string
262
301
263
302
protected function grabEventCollector (string $ function ): EventDataCollector
264
303
{
265
- return $ this ->grabCollector ('events ' , $ function );
304
+ /** @var EventDataCollector $collector */
305
+ $ collector = $ this ->grabCollector ('events ' , $ function );
306
+ return $ collector ;
266
307
}
267
308
}
0 commit comments