Search code examples
laravelintegration-testinglaravel-testinglaravel-notification

Laravel Notification asserting the data passed down to mail markdown view


I am working on a Laravel project. I am writing integration/ feature tests for my application. I am now writing a test where I need to assert the data passed to the email notification and the data passed to its view. I found this link to do it, https://medium.com/@vivekdhumal/how-to-test-mail-notifications-in-laravel-345528917494.

This is my notification class

class NotifyAdminForHelpCenterCreated extends Notification
{
    use Queueable;

    private $helpCenter;

    public function __construct(HelpCenter $helpCenter)
    {
        $this->helpCenter = $helpCenter;
    }

    public function via($notifiable)
    {
        return ['mail'];
    }

    public function toMail($notifiable)
    {
        return (new MailMessage())
            ->subject("Help Center registration")
            ->markdown('mail.admin.helpcenter.created-admin', [
                'helpCenter' => $this->helpCenter,
                'user' => $notifiable
            ]);
    }
}

As you can see in the code, I am passing data to mail.admin.helpcenter.created-admin blade view.

This is my test method.

/** @test */
public function myTest()
{
    $body = $this->requestBody();
    $this->actingAsSuperAdmin()
        ->post(route('admin.help-center.store'), $body)
        ->assertRedirect();

    $admin = User::where('email', $body['admin_email'])->first();
    $helpCenter = HelpCenter::first();

    Notification::assertSentTo(
        $admin,
        NotifyAdminForHelpCenterCreated::class,
        function ($notification, $channels) use ($admin, $helpCenter) {
            $mailData = $notification->toMail($admin)->toArray();
            //here I can do some assertions with the $mailData
            return true;
        }
    );
}

As you can see my comment in the test, I can do some assertions with the $mailData variable. But that does not include the data passed to the view. How can I assert or get the data or variables passed to the blade view/ template?


Solution

  • As you can see here, there is a viewData property on the MailMessage class which contains all the data passed to the view, no need to turn the notification into an array.

    $notification->toMail($admin)->viewData
    

    So it would be something like this in your case:

    /** @test */
    public function myTest()
    {
        $body = $this->requestBody();
        $this->actingAsSuperAdmin()
            ->post(route('admin.help-center.store'), $body)
            ->assertRedirect();
    
        $admin = User::where('email', $body['admin_email'])->first();
        $helpCenter = HelpCenter::first();
    
        Notification::assertSentTo(
            $admin,
            NotifyAdminForHelpCenterCreated::class,
            function ($notification, $channels) use ($admin, $helpCenter) {
                $viewData = $notification->toMail($admin)->viewData;
    
                return $admin->is($viewData['user']) && $helpCenter->is($viewData['helpCenter']);
            }
        );
    }