Skip to content

Commit ed9defe

Browse files
committed
Add event tests and bugs fix
1 parent 1e6c3f9 commit ed9defe

5 files changed

Lines changed: 265 additions & 68 deletions

File tree

src/Database/Barry/Traits/EventTrait.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ private function fireEvent(string $event): void
1717
{
1818
$env = static::formatEventName($event);
1919

20-
if (event()->bound($env)) {
21-
event()->emit($env, $this);
22-
}
20+
event()->emit($env, $this);
2321
}
2422

2523
/**

src/Event/Contracts/AppEvent.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
interface AppEvent
88
{
99
/**
10-
* Get the name of the event
10+
* Dispatch the event
1111
*
12-
* @return string
12+
* @return mixed
1313
*/
14-
public function getName(): string;
14+
public static function dispatch(): mixed;
1515
}

src/Event/Event.php

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public function on(string $event, callable|string $fn, int $priority = 0): void
7878
uasort(
7979
static::$events[$event],
8080
function (Listener $first_listener, Listener $second_listener) {
81-
return $first_listener->getPriority() < $second_listener->getPriority();
81+
return $second_listener->getPriority() <=> $first_listener->getPriority();
8282
}
8383
);
8484
}
@@ -105,14 +105,8 @@ public function bound(string|AppEvent $event): bool
105105
{
106106
$onces = static::$events['__bow.once.event'] ?? [];
107107

108-
if (is_string($event)) {
109-
return array_key_exists($event, static::$events) ||
110-
array_key_exists($event, $onces);
111-
}
112-
113-
$event = $event->getName();
114-
115-
return array_key_exists($event, $onces) || array_key_exists($event, static::$events);
108+
return array_key_exists($event, static::$events) ||
109+
array_key_exists($event, $onces);
116110
}
117111

118112
/**
@@ -135,7 +129,15 @@ public function once(string $event, callable|array|string $fn, int $priority = 0
135129
*/
136130
public function getEventListeners(string $event_name): array
137131
{
138-
return (array) (static::$events['__bow.once.event'][$event_name] ?? static::$events[$event_name]);
132+
$once_event = static::$events['__bow.once.event'][$event_name] ?? null;
133+
134+
if ($once_event) {
135+
return [$once_event];
136+
}
137+
138+
$regular_events = static::$events[$event_name] ?? [];
139+
140+
return (array) $regular_events;
139141
}
140142

141143
/**
@@ -156,7 +158,7 @@ public function emit(string|AppEvent $event): ?bool
156158
$data = array_slice(func_get_args(), 1);
157159
}
158160

159-
if (!$this->bound($event_name) || !$this->bound($event)) {
161+
if (!$this->bound($event_name)) {
160162
return null;
161163
}
162164

tests/Events/EventTest.php

Lines changed: 248 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,67 +13,284 @@
1313
class EventTest extends \PHPUnit\Framework\TestCase
1414
{
1515
private static string $cache_filename;
16+
private Event $event;
1617

1718
public static function setUpBeforeClass(): void
1819
{
1920
$config = TestingConfiguration::getConfig();
21+
2022
Database::configure($config["database"]);
2123
Database::connection("mysql");
2224
Database::connection("mysql")->statement('drop table if exists events');
2325
Database::connection("mysql")->statement('create table if not exists events (id int primary key, name varchar(255))');
2426
Database::connection("mysql")->statement("insert into events values (1, 'fluffy'), (2, 'dolly')");
27+
2528
static::$cache_filename = TESTING_RESOURCE_BASE_DIRECTORY . '/event.txt';
29+
}
2630

27-
Event::on(UserEventStub::class, UserEventListenerStub::class);
28-
Event::on('user.destroy', function (string $name) {
29-
Assert::assertEquals($name, 'destroy');
31+
protected function setUp(): void
32+
{
33+
$this->event = Event::getInstance();
34+
35+
// Clear previous event registrations
36+
$this->event->off('user.destroy');
37+
$this->event->off('user.created');
38+
$this->event->off('user.updated');
39+
$this->event->off(UserEventStub::class);
40+
41+
// Clean cache file
42+
if (file_exists(static::$cache_filename)) {
43+
file_put_contents(static::$cache_filename, '');
44+
}
45+
}
46+
47+
public function test_event_can_be_registered_with_closure()
48+
{
49+
$called = false;
50+
51+
$this->event->on('user.created', function () use (&$called) {
52+
$called = true;
3053
});
31-
Event::on('user.created', function (string $name) {
32-
Assert::assertEquals($name, 'created');
54+
55+
$this->assertTrue($this->event->bound('user.created'));
56+
$this->event->emit('user.created');
57+
$this->assertTrue($called);
58+
}
59+
60+
public function test_event_can_be_registered_with_listener_class()
61+
{
62+
$this->event->on(UserEventStub::class, UserEventListenerStub::class);
63+
64+
$this->assertTrue($this->event->bound(UserEventStub::class));
65+
}
66+
67+
public function test_event_can_emit_with_closure()
68+
{
69+
$result = null;
70+
71+
$this->event->on('user.destroy', function (string $name) use (&$result) {
72+
$result = $name;
3373
});
34-
Event::emit('user.created', 'created');
35-
Event::emit('user.destroy', 'destroy');
74+
75+
$this->event->emit('user.destroy', 'destroy');
76+
$this->assertEquals('destroy', $result);
3677
}
3778

38-
public function test_event_binding_and_email()
79+
public function test_event_can_emit_with_app_event()
3980
{
40-
$this->assertTrue(Event::bound('user.destroy'));
41-
$this->assertTrue(Event::bound('user.created'));
42-
$this->assertTrue(Event::bound(UserEventStub::class));
43-
$this->assertFalse(Event::bound('user.updated'));
81+
$this->event->on(UserEventStub::class, UserEventListenerStub::class);
82+
83+
$this->assertTrue($this->event->bound(UserEventStub::class), "Event should be bound");
84+
85+
$result = UserEventStub::dispatch("papac");
86+
87+
$this->assertNotNull($result, "Dispatch should return a result");
88+
89+
$content = file_get_contents(static::$cache_filename);
90+
$this->assertEquals("papac", $content, "File should contain 'papac', got: '$content'");
4491
}
4592

46-
public function test_model_created_event_emited()
93+
public function test_event_bound_returns_false_for_unregistered_event()
4794
{
95+
$this->assertFalse($this->event->bound('user.updated'));
96+
$this->assertFalse($this->event->bound('nonexistent.event'));
97+
}
98+
99+
public function test_event_listener_alias_works()
100+
{
101+
$called = false;
102+
103+
$this->event->listener('user.test', function () use (&$called) {
104+
$called = true;
105+
});
106+
107+
$this->assertTrue($this->event->bound('user.test'));
108+
$this->event->emit('user.test');
109+
$this->assertTrue($called);
110+
}
111+
112+
public function test_event_once_registers_one_time_listener()
113+
{
114+
file_put_contents(static::$cache_filename, 'initial');
115+
116+
$this->event->once('user.once', function () {
117+
file_put_contents(TESTING_RESOURCE_BASE_DIRECTORY . '/event.txt', 'once-called');
118+
});
119+
120+
$this->assertTrue($this->event->bound('user.once'));
121+
$this->event->emit('user.once');
122+
$this->assertEquals('once-called', file_get_contents(static::$cache_filename));
123+
}
124+
125+
public function test_event_off_removes_listener()
126+
{
127+
$this->event->on('user.test', function () {});
128+
$this->assertTrue($this->event->bound('user.test'));
129+
130+
$this->event->off('user.test');
131+
$this->assertFalse($this->event->bound('user.test'));
132+
}
133+
134+
public function test_event_off_works_with_app_event()
135+
{
136+
$this->event->on(UserEventStub::class, UserEventListenerStub::class);
137+
$this->assertTrue($this->event->bound(UserEventStub::class));
138+
139+
$this->event->off(UserEventStub::class);
140+
$this->assertFalse($this->event->bound(UserEventStub::class));
141+
}
142+
143+
public function test_event_dispatch_is_alias_for_emit()
144+
{
145+
$called = false;
146+
147+
$this->event->on('user.dispatch', function () use (&$called) {
148+
$called = true;
149+
});
150+
151+
$this->event->dispatch('user.dispatch');
152+
$this->assertTrue($called);
153+
}
154+
155+
public function test_event_priority_orders_listeners_correctly()
156+
{
157+
$order = [];
158+
159+
$this->event->on('user.priority', function () use (&$order) {
160+
$order[] = 'low';
161+
}, 1);
162+
163+
$this->event->on('user.priority', function () use (&$order) {
164+
$order[] = 'high';
165+
}, 10);
166+
167+
$this->event->on('user.priority', function () use (&$order) {
168+
$order[] = 'medium';
169+
}, 5);
170+
171+
$this->event->emit('user.priority');
172+
173+
$this->assertEquals(['high', 'medium', 'low'], $order);
174+
}
175+
176+
public function test_event_can_pass_multiple_arguments()
177+
{
178+
$receivedArgs = [];
179+
180+
$this->event->on('user.args', function ($arg1, $arg2, $arg3) use (&$receivedArgs) {
181+
$receivedArgs = [$arg1, $arg2, $arg3];
182+
});
183+
184+
$this->event->emit('user.args', 'first', 'second', 'third');
185+
186+
$this->assertEquals(['first', 'second', 'third'], $receivedArgs);
187+
}
188+
189+
public function test_event_emit_returns_null_for_unbound_event()
190+
{
191+
$result = $this->event->emit('nonexistent.event');
192+
193+
$this->assertNull($result);
194+
}
195+
196+
public function test_event_emit_returns_true_for_successful_emission()
197+
{
198+
$this->event->on('user.success', function () {});
199+
200+
$result = $this->event->emit('user.success');
201+
202+
$this->assertTrue($result);
203+
}
204+
205+
public function test_multiple_listeners_on_same_event()
206+
{
207+
$count = 0;
208+
209+
$this->event->on('user.multiple', function () use (&$count) {
210+
$count++;
211+
});
212+
213+
$this->event->on('user.multiple', function () use (&$count) {
214+
$count++;
215+
});
216+
217+
$this->event->on('user.multiple', function () use (&$count) {
218+
$count++;
219+
});
220+
221+
$this->event->emit('user.multiple');
222+
223+
$this->assertEquals(3, $count);
224+
}
225+
226+
public function test_get_event_listeners_returns_array()
227+
{
228+
$this->event->on('user.listeners', function () {});
229+
230+
$listeners = $this->event->getEventListeners('user.listeners');
231+
232+
$this->assertIsArray($listeners);
233+
$this->assertCount(1, $listeners);
234+
}
235+
236+
public function test_get_event_listeners_returns_empty_array_for_unbound()
237+
{
238+
$listeners = $this->event->getEventListeners('nonexistent.event');
239+
240+
$this->assertIsArray($listeners);
241+
$this->assertCount(0, $listeners);
242+
}
243+
244+
public function test_model_created_event_is_emitted()
245+
{
246+
file_put_contents(static::$cache_filename, '');
247+
248+
EventModelStub::created(function ($model) {
249+
file_put_contents(TESTING_RESOURCE_BASE_DIRECTORY . '/event.txt', 'created');
250+
});
251+
48252
$event = EventModelStub::connection("mysql");
49253
$event->setAttributes([
50254
'id' => 3,
51255
'name' => 'Filou'
52256
]);
53-
$this->assertEquals($event->persist(), 1);
257+
258+
$this->assertEquals(1, $event->persist());
54259
$this->assertEquals('created', file_get_contents(static::$cache_filename));
55260
}
56261

57-
public function test_model_updated_event_emited()
58-
{
59-
$pet = EventModelStub::connection("mysql")->first();
60-
$pet->name = 'Loulou';
61-
$this->assertEquals($pet->persist(), 1);
62-
$this->assertEquals('updated', file_get_contents(static::$cache_filename));
63-
}
64-
65-
public function test_model_deleted_event_emited()
262+
public function test_model_updated_event_is_emitted()
66263
{
67-
$pet = EventModelStub::connection("mysql")->first();
68-
69-
$this->assertEquals($pet->delete(), 1);
70-
$this->assertEquals('deleted', file_get_contents(static::$cache_filename));
264+
file_put_contents(static::$cache_filename, '');
265+
266+
EventModelStub::updated(function ($model) {
267+
file_put_contents(TESTING_RESOURCE_BASE_DIRECTORY . '/event.txt', 'updated');
268+
});
269+
270+
$pet = EventModelStub::connection("mysql")->where('id', 1)->first();
271+
if ($pet) {
272+
$pet->name = 'Loulou';
273+
$this->assertEquals(1, $pet->persist());
274+
$this->assertEquals('updated', file_get_contents(static::$cache_filename));
275+
} else {
276+
$this->markTestSkipped('No model found to update');
277+
}
71278
}
72279

73-
public function test_directly_from_event()
280+
public function test_model_deleted_event_is_emitted()
74281
{
75-
UserEventStub::dispatch("papac");
76-
77-
$this->assertEquals("papac", file_get_contents(static::$cache_filename));
282+
file_put_contents(static::$cache_filename, '');
283+
284+
EventModelStub::deleted(function ($model) {
285+
file_put_contents(TESTING_RESOURCE_BASE_DIRECTORY . '/event.txt', 'deleted');
286+
});
287+
288+
$pet = EventModelStub::connection("mysql")->where('id', 2)->first();
289+
if ($pet) {
290+
$this->assertEquals(1, $pet->delete());
291+
$this->assertEquals('deleted', file_get_contents(static::$cache_filename));
292+
} else {
293+
$this->markTestSkipped('No model found to delete');
294+
}
78295
}
79296
}

0 commit comments

Comments
 (0)