55
66use InvalidArgumentException ;
77use PHPUnit \Framework \Attributes \CoversClass ;
8+ use PHPUnit \Framework \Attributes \Group ;
89use PHPUnit \Framework \TestCase ;
910use Wwwision \DCBEventStore \EventStore ;
1011use Wwwision \DCBEventStore \EventStream ;
@@ -151,6 +152,7 @@ public function test_read_allows_filtering_of_events_by_tags_conjunction(): void
151152 ]);
152153 }
153154
155+ #[Group('feature_onlyLastEvent ' )]
154156 public function test_read_allows_filtering_of_last_event_by_tag (): void
155157 {
156158 $ this ->appendEvents ([
@@ -197,6 +199,7 @@ public function test_read_allows_filtering_of_events_by_multiple_event_types():
197199 ]);
198200 }
199201
202+ #[Group('feature_onlyLastEvent ' )]
200203 public function test_read_allows_filtering_of_last_event_by_event_types (): void
201204 {
202205 $ this ->appendDummyEvents ();
@@ -218,6 +221,7 @@ public function test_read_allows_filtering_of_events_by_tags_and_event_types():
218221 ]);
219222 }
220223
224+ #[Group('feature_onlyLastEvent ' )]
221225 public function test_read_allows_filtering_of_last_event_by_tags_and_event_types (): void
222226 {
223227 $ this ->appendDummyEvents ();
@@ -235,35 +239,36 @@ public function test_read_allows_fetching_no_events(): void
235239 self ::assertEventStream ($ this ->stream ($ query ), []);
236240 }
237241
238- // // NOTE: This test is commented out because that guarantee is currently NOT given (it works on SQLite but not on MariaDB and PostgreSQL)
239- // public function test_read_includes_events_that_where_appended_after_iteration_started(): void
240- // {
241- // $this->appendDummyEvents();
242- // $actualEvents = [];
243- // $index = 0;
244- // $eventStream = $this->getEventStore()->read(StreamQuery::wildcard());
245- // foreach ($eventStream as $eventEnvelope) {
246- // $actualEvents[] = self::eventEnvelopeToArray(isset($expectedEvents[$index]) ? array_keys($expectedEvents[$index]) : ['type', 'data', 'tags', 'sequenceNumber'], $eventEnvelope);
247- // if ($eventEnvelope->sequenceNumber->value === 3) {
248- // $this->appendEvents([
249- // ['data' => 'g', 'type' => 'SomeEventType', 'tags' => ['foo:bar', 'foo:baz']],
250- // ['data' => 'h', 'type' => 'SomeOtherEventType', 'tags' => ['foo:foos', 'bar:baz']],
251- // ]);
252- // }
253- // $index ++;
254- // }
255- // $expectedEvents = [
256- // ['data' => 'a', 'type' => 'SomeEventType', 'tags' => ['baz:foos', 'foo:bar'], 'sequenceNumber' => 1],
257- // ['data' => 'b', 'type' => 'SomeOtherEventType', 'tags' => ['foo:bar'], 'sequenceNumber' => 2],
258- // ['data' => 'c', 'type' => 'SomeEventType', 'tags' => ['foo:bar'], 'sequenceNumber' => 3],
259- // ['data' => 'd', 'type' => 'SomeOtherEventType', 'tags' => ['baz:foos', 'foo:bar'], 'sequenceNumber' => 4],
260- // ['data' => 'e', 'type' => 'SomeEventType', 'tags' => ['baz:foos', 'foo:bar'], 'sequenceNumber' => 5],
261- // ['data' => 'f', 'type' => 'SomeOtherEventType', 'tags' => ['baz:foos', 'foo:bar'], 'sequenceNumber' => 6],
262- // ['data' => 'g', 'type' => 'SomeEventType', 'tags' => ['foo:bar', 'foo:baz'], 'sequenceNumber' => 7],
263- // ['data' => 'h', 'type' => 'SomeOtherEventType', 'tags' => ['bar:baz', 'foo:foos'], 'sequenceNumber' => 8],
264- // ];
265- // self::assertEquals($expectedEvents, $actualEvents);
266- // }
242+ #[Group('feature_liveStream ' )]
243+ public function test_read_includes_events_that_where_appended_after_iteration_started (): void
244+ {
245+ $ this ->appendDummyEvents ();
246+ $ expectedEvents = [
247+ ['data ' => 'a ' , 'type ' => 'SomeEventType ' , 'tags ' => ['baz:foos ' , 'foo:bar ' ], 'sequenceNumber ' => 1 ],
248+ ['data ' => 'b ' , 'type ' => 'SomeOtherEventType ' , 'tags ' => ['foo:bar ' ], 'sequenceNumber ' => 2 ],
249+ ['data ' => 'c ' , 'type ' => 'SomeEventType ' , 'tags ' => ['foo:bar ' ], 'sequenceNumber ' => 3 ],
250+ ['data ' => 'd ' , 'type ' => 'SomeOtherEventType ' , 'tags ' => ['baz:foos ' , 'foo:bar ' ], 'sequenceNumber ' => 4 ],
251+ ['data ' => 'e ' , 'type ' => 'SomeEventType ' , 'tags ' => ['baz:foos ' , 'foo:bar ' ], 'sequenceNumber ' => 5 ],
252+ ['data ' => 'f ' , 'type ' => 'SomeOtherEventType ' , 'tags ' => ['baz:foos ' , 'foo:bar ' ], 'sequenceNumber ' => 6 ],
253+ ['data ' => 'g ' , 'type ' => 'SomeEventType ' , 'tags ' => ['foo:bar ' , 'foo:baz ' ], 'sequenceNumber ' => 7 ],
254+ ['data ' => 'h ' , 'type ' => 'SomeOtherEventType ' , 'tags ' => ['bar:baz ' , 'foo:foos ' ], 'sequenceNumber ' => 8 ],
255+ ];
256+ $ actualEvents = [];
257+ $ index = 0 ;
258+ $ eventStream = $ this ->getEventStore ()->read (StreamQuery::wildcard ());
259+ foreach ($ eventStream as $ eventEnvelope ) {
260+ $ actualEvents [] = self ::eventEnvelopeToArray (isset ($ expectedEvents [$ index ]) ? array_keys ($ expectedEvents [$ index ]) : ['type ' , 'data ' , 'tags ' , 'sequenceNumber ' ], $ eventEnvelope );
261+ if ($ eventEnvelope ->sequenceNumber ->value === 3 ) {
262+ $ this ->appendEvents ([
263+ ['data ' => 'g ' , 'type ' => 'SomeEventType ' , 'tags ' => ['foo:bar ' , 'foo:baz ' ]],
264+ ['data ' => 'h ' , 'type ' => 'SomeOtherEventType ' , 'tags ' => ['foo:foos ' , 'bar:baz ' ]],
265+ ]);
266+ }
267+ $ index ++;
268+ }
269+
270+ self ::assertEquals ($ expectedEvents , $ actualEvents );
271+ }
267272
268273 public function test_read_backwards_returns_all_events_in_descending_order (): void
269274 {
@@ -297,6 +302,8 @@ public function test_read_backwards_returns_single_event_if_maximum_sequenceNumb
297302 ]);
298303 }
299304
305+ #[Group('feature_onlyLastEvent ' )]
306+ #[Group('feature_onlyLastEventCombined ' )]
300307 public function test_read_options_dont_affect_matching_events (): void
301308 {
302309 $ this ->appendEvents ([
@@ -346,11 +353,21 @@ public function test_append_appends_event_if_expectedHighestSequenceNumber_match
346353 ]);
347354 }
348355
356+ #[Group('feature_appendConditionWithoutMatchingEvent ' )]
357+ public function test_append_appends_event_if_expected_highest_sequence_number_matches_no_events (): void
358+ {
359+ $ query = StreamQuery::create (Criteria::create (EventTypesAndTagsCriterion::create (eventTypes: 'SomeEventTypeThatDidNotOccur ' , tags: 'baz:foos ' )));
360+ $ this ->conditionalAppendEvent (['type ' => 'SomeEventType ' , 'data ' => 'new event ' ], $ query , ExpectedHighestSequenceNumber::fromInteger (123 ));
361+ self ::assertEventStream ($ this ->getEventStore ()->read (StreamQuery::wildcard ()), [
362+ ['data ' => 'new event ' ],
363+ ]);
364+ }
365+
349366 public function test_append_fails_if_new_events_match_the_specified_query (): void
350367 {
351368 $ this ->appendDummyEvents ();
352369
353- $ query = StreamQuery::create (Criteria::create (EventTypesAndTagsCriterion::create (eventTypes: ' SomeEventType ' , tags: 'baz:foos ' )));
370+ $ query = StreamQuery::create (Criteria::create (EventTypesAndTagsCriterion::create (tags: 'baz:foos ' )));
354371 $ stream = $ this ->getEventStore ()->read ($ query , ReadOptions::create (backwards: true ));
355372 $ lastEvent = $ stream ->first ();
356373 self ::assertInstanceOf (EventEnvelope::class, $ lastEvent );
@@ -362,7 +379,7 @@ public function test_append_fails_if_new_events_match_the_specified_query(): voi
362379 $ this ->conditionalAppendEvent (['type ' => 'DoesNotMatter ' ], $ query , ExpectedHighestSequenceNumber::fromSequenceNumber ($ lastSequenceNumber ));
363380 }
364381
365- public function test_append_fails_if_no_last_event_id_was_expected_but_query_matches_events (): void
382+ public function test_append_fails_if_no_highest_sequence_number_was_expected_but_query_matches_events (): void
366383 {
367384 $ this ->appendDummyEvents ();
368385
@@ -372,14 +389,6 @@ public function test_append_fails_if_no_last_event_id_was_expected_but_query_mat
372389 $ this ->conditionalAppendEvent (['type ' => 'DoesNotMatter ' ], $ query , ExpectedHighestSequenceNumber::none ());
373390 }
374391
375- public function test_append_fails_if_last_event_id_was_expected_but_query_matches_no_events (): void
376- {
377- $ query = StreamQuery::create (Criteria::create (EventTypesAndTagsCriterion::create (eventTypes: 'SomeEventTypeThatDidNotOccur ' , tags: 'baz:foos ' )));
378-
379- $ this ->expectException (ConditionalAppendFailed::class);
380- $ this ->conditionalAppendEvent (['type ' => 'DoesNotMatter ' ], $ query , ExpectedHighestSequenceNumber::fromInteger (123 ));
381- }
382-
383392 // --- Helpers ---
384393
385394 final protected function streamAll (): EventStream
0 commit comments