From beb69b4a0e5c03fdeca740c53cae8900fae1b82f Mon Sep 17 00:00:00 2001 From: "Christopher C. Wells" Date: Tue, 6 Apr 2021 11:41:33 -0700 Subject: [PATCH] Update tests for User refactoring --- app/Console/Commands/UserAdd.php | 10 +-- tests/Feature/Console/UserAddTest.php | 83 +++++++++++++++++++ .../Controllers/Auth/AuthenticationTest.php | 37 ++++++++- 3 files changed, 121 insertions(+), 9 deletions(-) create mode 100644 tests/Feature/Console/UserAddTest.php diff --git a/app/Console/Commands/UserAdd.php b/app/Console/Commands/UserAdd.php index 1333c32..4546898 100644 --- a/app/Console/Commands/UserAdd.php +++ b/app/Console/Commands/UserAdd.php @@ -40,6 +40,11 @@ class UserAdd extends Command $arguments['username'] = $this->ask('Enter a username for the user'); } + if (empty($arguments['username'])) { + $this->error('Username is required.'); + return 1; + } + // Check for an existing user. if (User::whereUsername($arguments['username'])->exists()) { $this->error("User `{$arguments['username']}` already exists."); @@ -67,11 +72,6 @@ class UserAdd extends Command $options['name'] = $this->ask('Enter a name for the user (optional)'); } - if (empty($arguments['username']) || empty($arguments['password'])) { - $this->error('Username and password must be provided.'); - return 1; - } - User::create([ 'username' => $arguments['username'], 'password' => Hash::make($arguments['password']), diff --git a/tests/Feature/Console/UserAddTest.php b/tests/Feature/Console/UserAddTest.php new file mode 100644 index 0000000..d8c8f7e --- /dev/null +++ b/tests/Feature/Console/UserAddTest.php @@ -0,0 +1,83 @@ +makeOne(); + $this->artisan('user:add') + ->expectsQuestion('Enter a username for the user', $user->username) + ->expectsQuestion('Enter a password for the user (leave blank for a random password)', 'password') + ->expectsQuestion('Re-type the password to confirm', 'password') + ->expectsQuestion('Enter a name for the user (optional)', $user->name) + ->assertExitCode(0); + /** @var \App\Models\User $new_user */ + $new_user = User::whereUsername($user->username)->get()->first(); + $this->assertEquals($user->username, $new_user->username); + $this->assertEquals($user->name, $new_user->name); + } + + public function testCanAddUserWithArguments(): void + { + /** @var \App\Models\User $user */ + $user = User::factory()->makeOne(); + $parameters = [ + 'username' => $user->username, + 'password' => 'password', + '--name' => $user->name, + ]; + $this->artisan('user:add', $parameters) + ->assertExitCode(0); + /** @var \App\Models\User $new_user */ + $new_user = User::whereUsername($user->username)->get()->first(); + $this->assertEquals($user->username, $new_user->username); + $this->assertEquals($user->name, $new_user->name); + } + + public function testCanNotAddExistingUsername(): void + { + /** @var \App\Models\User $user */ + $user = User::factory()->createOne(['username' => 'test_user']); + $this->artisan('user:add', ['username' => $user->username]) + ->expectsOutput("User `{$user->username}` already exists.") + ->assertExitCode(1); + } + + public function testCanNotLeaveUsernameBlank(): void + { + /** @var \App\Models\User $user */ + $this->artisan('user:add') + ->expectsQuestion('Enter a username for the user', NULL) + ->expectsOutput('Username is required.') + ->assertExitCode(1); + } + + public function testPasswordsMustMatch(): void + { + /** @var \App\Models\User $user */ + $this->artisan('user:add', ['username' => 'test_user']) + ->expectsQuestion('Enter a password for the user (leave blank for a random password)', 'password') + ->expectsQuestion('Re-type the password to confirm', 'password1') + ->expectsOutput('Passwords did not match.') + ->assertExitCode(1); + } + + public function testRandomPasswordCanBeGenerated(): void + { + /** @var \App\Models\User $user */ + $this->artisan('user:add', ['username' => 'test_user', '--name' => 'Test User']) + ->expectsQuestion('Enter a password for the user (leave blank for a random password)', NULL) + ->expectsOutput('User `test_user` added!') + ->assertExitCode(0); + } + +} diff --git a/tests/Feature/Http/Controllers/Auth/AuthenticationTest.php b/tests/Feature/Http/Controllers/Auth/AuthenticationTest.php index 6c08eee..4df44cc 100644 --- a/tests/Feature/Http/Controllers/Auth/AuthenticationTest.php +++ b/tests/Feature/Http/Controllers/Auth/AuthenticationTest.php @@ -4,21 +4,25 @@ namespace Tests\Feature\Http\Controllers\Auth; use App\Models\User; use App\Providers\RouteServiceProvider; +use Illuminate\Auth\Events\Lockout; use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Support\Facades\Event; +use Illuminate\Validation\ValidationException; use Tests\TestCase; class AuthenticationTest extends TestCase { use RefreshDatabase; - public function testLoginScreenCanRendered() + public function testLoginScreenCanRendered(): void { $response = $this->get('/login'); $response->assertStatus(200); } - public function testUserCanAuthenticateUsingLoginScreen() + public function testUserCanAuthenticateUsingLoginScreen(): void { + /** @var \App\Models\User $user */ $user = User::factory()->create(); $response = $this->post('/login', [ 'username' => $user->username, @@ -28,8 +32,9 @@ class AuthenticationTest extends TestCase $response->assertRedirect(RouteServiceProvider::HOME); } - public function testUserCannotAuthenticateWithInvalidPassword() + public function testUserCannotAuthenticateWithInvalidPassword(): void { + /** @var \App\Models\User $user */ $user = User::factory()->create(); $this->post('/login', [ 'username' => $user->username, @@ -38,9 +43,33 @@ class AuthenticationTest extends TestCase $this->assertGuest(); } - public function testUserCanLogout() + public function testUserCanLogout(): void { + /** @var \App\Models\User $user */ + $user = User::factory()->create(); + $this->post('/login', ['username' => $user->username, 'password' => 'password']); + $this->assertAuthenticated(); $this->followingRedirects()->post('/logout'); $this->assertGuest(); } + + public function testExcessiveLoginRequestsAreRateLimited(): void + { + /** @var \App\Models\User $user */ + $user = User::factory()->create(); + + Event::fake(); + + for ($i = 0; $i < 5; $i++) { + $this->post('/login', [ + 'username' => $user->username, + 'password' => 'wrong-password', + ]); + if ($i < 5) { + Event::assertNotDispatched(Lockout::class); + continue; + } + Event::assertDispatched(Lockout::class); + } + } }