skip to Main Content

The client wants the layouts.sidebar.blade.php to have a link for users with a certain role.
The AppServiceProvider boots a NotificationComposer for all (*) views.
The NotificationComposer has the following code
$view->with('unreadNotificationCount', count(request()->user()->unreadNotifications));
I want to write a test like the below, but recieve an error exception ‘Attempt to read property "unreadNotifications" on null’:

/** @test */
public function user_with_role_can_see_link_in_the_sidebar()
{
    $link = route('my-web.new-page');
    $response = $this->actingAs($this->userRole)->blade('layouts.sidebar');
    $response-assertSee($link);
}
/** @test */
public function normal_user_cannot_see_link_in_the_sidebar()
{
    $link = route('my-web.new-page');
    $response = $this->actingAs($this->user)->blade('layouts.sidebar');
    $response-assertDontSee($link);
}

I’ve rewritten to use http ->get() tests on only the homepage instead, but I’m not sure what the best way would be to test this? I know it’s unlikely the homepage route will change, but wanted the test to be more specific.

2

Answers


  1. To avoid the "unreadNotifications" error in your test, you can temporarily disable the view composer in your tests like this:

    View::composer('*', function ($view) {
        // Do nothing or mock composer data
    });
    

    This prevents the NotificationComposer from running during the test, allowing you to focus on testing the sidebar view. Alternatively, you can mock the composer data:

    View::composer('*', function ($view) {
        $view->with('unreadNotificationCount', 0);
    });
    

    This ensures the test runs without the exception.

    Login or Signup to reply.
  2. If you want to test Blade views directly, either disabling the view composer or mocking the composer data would be a good way to go. If you’re okay with testing via HTTP requests, you can stick with the HTTP route-based tests but focus the assertions on the specific sidebar content

    1. Disable View Composer in the Test

    You can disable the NotificationComposer during the test to avoid the error related to unreadNotifications. One way to do this is by overriding the AppServiceProvider registration of the view composer for this test.

    /** @test */
    public function user_with_role_can_see_link_in_the_sidebar()
    {
        // Disable the NotificationComposer for this test
        View::composer('*', function ($view) {
            // No-op, no unreadNotifications handling
        });
    
        $link = route('my-web.new-page');
        $response = $this->actingAs($this->userRole)->blade('layouts.sidebar');
        $response->assertSee($link);
    }
    
    /** @test */
    public function normal_user_cannot_see_link_in_the_sidebar()
    {
        // Disable the NotificationComposer for this test
        View::composer('*', function ($view) {
            // No-op
        });
    
        $link = route('my-web.new-page');
        $response = $this->actingAs($this->user)->blade('layouts.sidebar');
        $response->assertDontSee($link);
    }
    

    2. Mock the View Composer

    Another approach is to mock the unreadNotificationCount data that the view composer provides, so the view can be rendered without causing the error.

    /** @test */
    public function user_with_role_can_see_link_in_the_sidebar()
    {
        // Mock the NotificationComposer data
        View::composer('*', function ($view) {
            $view->with('unreadNotificationCount', 0);
        });
    
        $link = route('my-web.new-page');
        $response = $this->actingAs($this->userRole)->blade('layouts.sidebar');
        $response->assertSee($link);
    }
    
    /** @test */
    public function normal_user_cannot_see_link_in_the_sidebar()
    {
        // Mock the NotificationComposer data
        View::composer('*', function ($view) {
            $view->with('unreadNotificationCount', 0);
        });
    
        $link = route('my-web.new-page');
        $response = $this->actingAs($this->user)->blade('layouts.sidebar');
        $response->assertDontSee($link);
    }
    

    3. Use HTTP Test but Keep the View Specific

    /** @test */
    public function user_with_role_can_see_link_in_the_sidebar()
    {
        $link = route('my-web.new-page');
        $response = $this->actingAs($this->userRole)->get(route('homepage'));
    
        // Assert that the sidebar contains the link for the user with the role
        $response->assertSee($link);
    }
    
    /** @test */
    public function normal_user_cannot_see_link_in_the_sidebar()
    {
        $link = route('my-web.new-page');
        $response = $this->actingAs($this->user)->get(route('homepage'));
    
        // Assert that the sidebar does not contain the link for the normal user
        $response->assertDontSee($link);
    }
    

    This method tests the actual route but remains tied to the sidebar content. It ensures that the link visibility works correctly based on the user’s role.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search