extend(TestCase::class)->in('Unit'); pest()->extend(TestCase::class)->in('Feature/Web'); pest()->extend(TestCase::class)->in('Feature/EnvironmentTemplateTest.php'); pest()->extend(ApiTestCase::class)->in('Feature/Api'); pest()->extend(TestCase::class) ->use(RefreshDatabase::class) ->group('browser') ->in('Browser'); pest()->extend(TestCase::class) ->use(RefreshDatabase::class) ->group('visual') ->in('Visual'); /* |-------------------------------------------------------------------------- | Browser and visual helpers |-------------------------------------------------------------------------- */ /** * Sign a user in through the login form. * * Browser tests cannot use actingAs(): the browser carries its own session * cookie, which the guard in the test process does not share. The password is * assigned in plain text because User::setPasswordAttribute() hashes it. * * Call this inside the test, never from beforeEach. Pest connects the browser * client as the test starts, so a visit() from beforeEach fails with * "WebSocket client is not connected" unless an earlier test happened to * connect first. */ function browserLogin(?User $user = null, string $password = 'password'): User { $user ??= UserFactory::admin()->create(['password' => $password]); visit('/login') ->fill('#username', $user->email) ->fill('#password', $password) ->click('Log In') ->assertPathIs('/'); return $user; } /** * Sign the seeded admin in through the login form. * * Visual tests cannot use browserLogin(): that mints a faker user whose random * name lands in the navbar and the users table, which would change every * capture. UserSeeder creates exactly one deterministic user. */ function visualLogin(): User { visit('/login') ->fill('#username', 'admin') ->fill('#password', 'admin123') ->click('Log In') ->assertPathIs('/'); return User::where('username', 'admin')->firstOrFail(); }