The goal is to test if the administrator to a site can see the administration dashboard. We are using Laravel 8 with Spatie laravel-permission v3.18. Roles work correctly when testing manually in the browser.
My code
// routes/web.php
Route::group(['middleware' => ['role:admin']], function () {
Route::middleware(['auth:sanctum', 'verified'])->get('/administration', function () {
return view('admin.index');
})->name('administration');
});
//tests/Feature/AdministrationTest.php
<?php
namespace Tests\Feature;
use Tests\TestCase;
use App\Models\User;
use Spatie\Permission\Models\Role;
use Spatie\Permission\PermissionRegistrar;
use Illuminate\Foundation\Testing\RefreshDatabase;
class AdministrationTest extends TestCase
{
use RefreshDatabase;
protected $admin;
public function setUp(): void
{
parent::setUp();
$this->setupPermissions();
$this->admin = User::factory()->make();
$this->admin->assignRole('admin');
$this->admin->save();
}
protected function setUpPermissions()
{
Role::create(['name' => 'admin']);
$this->app->make(PermissionRegistrar::class)->registerPermissions();
}
/** @test */
public function an_admin_can_browse_admin_dashboard()
{
$this->withoutExceptionHandling();
$admin = User::find(1);
$response = $this
->actingAs($admin)
->get('/administration');
$response->assertStatus(200);
}
// result of phpunit
There was 1 error:
1) Tests\Feature\AdministrationTest::an_admin_can_browse_admin_dashboard
Spatie\Permission\Exceptions\UnauthorizedException: User does not have the right roles.
Using dd($this->admin->getRoleNames()) after the user has been created and role assigned, shows that the user has no roles, which explains the user
Testing has been done both with saving the user as above and not saving the user. Same result.
Examples above used from this Spatie Permissions Demo here and here
What changes to my code are necessary to allow this test to work successfully?
But how about authorization. I am sure laravel is tested to ensure the logged in user can do something.
I would be more concerned if authorization is ensuring the logged in user can or cannot do the things assigned.
I don't look at how important a role is, like many people make a big deal about admin, I have a system where you have admins and bookkeepers but the admin cannot mess around with bookkeeping or accounting.
That would be of a higher concern to me, the can or cannot do something.
I would guarantee you that authentication out of the box is tested and probably retested by Taylor and the laravel team.
Thinking more about what @jlrdw commented on, I altered my Route::group to be:
Route::group(['middleware' => ['auth:sanctum', 'verified', 'role:admin']], function () {
The problem is now resolved. Though I am tot sure why. If I had to guess, Perhaps having auth:sanctum called before role:admin would be setup the user and roles to be available?