I am working on a project using Laravel. I want to use Events and Notifications.
For context: A organization can post a Task ( Can be compared to a Job ). A User can apply for that job. As soon as a User applies for a Task an Email should be sent to the contact email stored with the Task.´
My Event: ApplicationCreated
My Notification: ApplicationCreatedNotification
My Listener: SendApplicationCreatedNotification
My controller function:
public function store(StoreApplicationRequest $request, Task $task)
{
Gate::authorize('store', [Application::class, $task]);
$application = null;
DB::transaction(function () use ($request, $task, &$application) {
$application = $task->applications()->create([
...$request->validated(),
'user_id' => auth()->id(),
]);
$application->load('user');
$application->setRelation('task', $task);
});
ApplicationCreated::dispatch($application);
return response()->json($application, 201);
}
My handle function in the Listener:
public function handle(ApplicationCreated $event): void
{
$recipient = $event->application->task->contact_email;
$name = $event->application->task->contact_firstname . ' ' . $event->application->task->contact_lastname;
Notification::route('mail', [
$recipient => $name,
])
->notify(new ApplicationCreatedNotification($event->application));
// @TODO: Send notification to the applicant as well
// something like this:
// "You successfully applied to the task: $task->title"
}
And My Test:
public function test_user_can_apply_to_task(): void
{
$user = User::factory()->organization()->create();
$orga = Organization::factory()->forUser($user)->create();
$task = Task::factory()->forOrganization($orga)->create();
$basicUser = User::factory()->create();
Event::fake();
Notification::fake();
$response = $this->actingAs($basicUser)->post(route('applications.store', $task->id));
Event::assertDispatched(ApplicationCreated::class);
Notification::assertSentOnDemand(ApplicationCreatedNotification::class, function (ApplicationCreatedNotification $notification, array $channels, object $notifiable) use ($task) {
$recipient = $task->contact_email;
$name = $task->contact_firstname . ' ' . $task->contact_lastname;
return $notifiable->routes['mail'] === [$recipient => $name];
});
$response->assertStatus(201);
$this->assertDatabaseHas('applications', [
'task_id' => $task->id,
'user_id' => $basicUser->id,
]);
}
I get this output:
FAILED TestsFeatureCreateApplicationTest > user can apply to task
The expected [AppNotificationsApplicationCreatedNotification] notification was not sent.
Failed asserting that false is true.
at vendorlaravelframeworksrcIlluminateSupportTestingFakesNotificationFake.php:89
85▕ if (is_numeric($callback)) {
86▕ return $this->assertSentToTimes($notifiable, $notification, $callback);
87▕ }
88▕
➜ 89▕ PHPUnit::assertTrue(
90▕ $this->sent($notifiable, $notification, $callback)->count() > 0,
91▕ "The expected [{$notification}] notification was not sent."
92▕ );
93▕ }
1 vendorlaravelframeworksrcIlluminateSupportTestingFakesNotificationFake.php:89
2 vendorlaravelframeworksrcIlluminateSupportTestingFakesNotificationFake.php:54
I know that the handle function gets called because when I add dd($recipient, $name); exit(0);
the test process stops and I get this output
"[email protected]" // appListenersSendApplicationCreatedNotification.php:33
"Katrin Thomas" // appListenersSendApplicationCreatedNotification.php:33
Does anyone has an Idea why this doesn’t work?