From 284a9f75b2d1911f776647d428da4210fec82794 Mon Sep 17 00:00:00 2001 From: Bubka <858858+Bubka@users.noreply.github.com> Date: Tue, 3 Mar 2020 17:06:40 +0100 Subject: [PATCH] Enhance unit tests coverage --- tests/Feature/AuthTest.php | 174 +++++++++++++++++++++++++++++++++ tests/Unit/QrcodeTest.php | 69 ++++++------- tests/Unit/TwoFAccountTest.php | 80 ++++++++++++++- tests/Unit/UserTest.php | 5 + 4 files changed, 289 insertions(+), 39 deletions(-) create mode 100644 tests/Feature/AuthTest.php diff --git a/tests/Feature/AuthTest.php b/tests/Feature/AuthTest.php new file mode 100644 index 00000000..b65e2dd7 --- /dev/null +++ b/tests/Feature/AuthTest.php @@ -0,0 +1,174 @@ +json('POST', '/api/password/email', [ + 'email' => '' + ]); + + $response->assertStatus(422) + ->assertJsonValidationErrors(['email']); + } + + /** + * Testing submitting the email password request with an invalid + * email address. + */ + public function testSubmitEmailPasswordRequestWithInvalidEmail() + { + $response = $this->json('POST', '/api/password/email', [ + 'email' => 'nametest.com' + ]); + + $response->assertStatus(422) + ->assertJsonValidationErrors(['email']); + } + + /** + * Testing submitting the email password request with an unknown + * email address. + */ + public function testSubmitEmailPasswordRequestWithUnknownEmail() + { + $response = $this->json('POST', '/api/password/email', [ + 'email' => 'name@test.com' + ]); + + $response->assertStatus(422) + ->assertJsonValidationErrors(['email']); + } + + /** + * Testing submitting the email password request with a valid email address. + */ + public function testSubmitEmailPasswordRequest() + { + Notification::fake(); + + $this->user = factory(User::class)->create([ + 'name' => 'user', + 'email' => 'user@example.org', + 'password' => bcrypt('password'), + 'email_verified_at' => now(), + 'remember_token' => \Illuminate\Support\Str::random(10), + ]); + + //$this->expectsNotification($this->user, ResetPassword::class); + + $response = $this->json('POST', '/api/password/email', [ + 'email' => $this->user->email + ]); + + $response->assertStatus(200); + + $token = \Illuminate\Support\Facades\DB::table('password_resets')->first(); + $this->assertNotNull($token); + + // Notification::assertSentTo($this->user, ResetPassword::class, function ($notification, $channels) use ($token) { + // return Hash::check($notification->token, $token->token) === true; + // }); + } + + + + /** + * Testing submitting the reset password without + * email address. + */ + public function testSubmitResetPasswordWithoutInput() + { + $response = $this->json('POST', '/api/password/reset', [ + 'email' => '', + 'password' => '', + 'password_confirmation' => '', + 'token' => '' + ]); + + $response->assertStatus(422) + ->assertJsonValidationErrors(['email', 'password', 'token']); + } + + /** + * Testing submitting the reset password with + * invalid input. + */ + public function testSubmitResetPasswordWithInvalidInput() + { + $response = $this->json('POST', '/api/password/reset', [ + 'email' => 'qsdqsdqsd', + 'password' => 'foofoofoo', + 'password_confirmation' => 'barbarbar', + 'token' => 'token' + ]); + + $response->assertStatus(422) + ->assertJsonValidationErrors(['email', 'password']); + } + + /** + * Testing submitting the reset password with + * invalid input. + */ + public function testSubmitResetPasswordWithTooShortPasswords() + { + $response = $this->json('POST', '/api/password/reset', [ + 'email' => 'foo@bar.com', + 'password' => 'foo', + 'password_confirmation' => 'foo', + 'token' => 'token' + ]); + + $response->assertStatus(422) + ->assertJsonValidationErrors(['password']); + } + + /** + * Testing submitting the rest password. + */ + public function testSubmitResetPassword() + { + Notification::fake(); + + $this->user = factory(User::class)->create([ + 'name' => 'user', + 'email' => 'user@example.org', + 'password' => bcrypt('password'), + 'email_verified_at' => now(), + 'remember_token' => \Illuminate\Support\Str::random(10) + ]); + + $token = Password::broker()->createToken($this->user); + + $response = $this->json('POST', '/api/password/reset', [ + 'email' => $this->user->email, + 'password' => 'newpassword', + 'password_confirmation' => 'newpassword', + 'token' => $token + ]); + + $this->user->refresh(); + + $response->assertStatus(200); + $this->assertTrue(Hash::check('newpassword', $this->user->password)); + + } + +} diff --git a/tests/Unit/QrcodeTest.php b/tests/Unit/QrcodeTest.php index 08119099..3a7201c1 100644 --- a/tests/Unit/QrcodeTest.php +++ b/tests/Unit/QrcodeTest.php @@ -7,6 +7,7 @@ use Illuminate\Http\UploadedFile; use Illuminate\Support\Facades\Storage; use Illuminate\Foundation\Testing\WithoutMiddleware; use Tests\TestCase; +use Tests\Classes\LocalFile; class QrcodeTest extends TestCase { @@ -15,7 +16,7 @@ class QrcodeTest extends TestCase /** - * test upload icon with no missing image resource via API + * test Decode a qrcode without providing a file resource via API * * @test */ @@ -29,53 +30,53 @@ class QrcodeTest extends TestCase } - /** - * test Qrcode decode with an invalid image resource via API - * - * @test - */ - // public function testQrcodeDecodeWithInvalidImage() - // { - - // Storage::fake('qrcodes'); - - // $file = UploadedFile::fake()->image('qrcode.jpg'); - - // $this->expectException(\Illuminate\Validation\ValidationException::class); - - // $response = $this->json('POST', '/api/qrcode/decode', [ - // 'qrcode' => $file, - // ]); - // } - - /** * test delete an uploaded icon via API * * @test */ - public function testDecodeQrcode() + public function testDecodeInvalidQrcode() { - //Storage::fake('qrcodes'); - - $image = 'data:image/png;base64,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'; - - - //Storage::put('tests/qrcodeTest.png', base64_decode($image)); - - //$this->assertFileExists('storage/app/tests/qrcodeTest.png'); + $file = LocalFile::fake()->invalidQrcode(); $response = $this->withHeaders([ 'Content-Type' => 'multipart/form-data', ]) ->json('POST', '/api/qrcode/decode', [ - 'qrcode' => $image + 'qrcode' => $file ]); - $response->dump(); - $response->dumpHeaders(); + $response->assertStatus(422); + } - $response->assertStatus(200); + + /** + * test Decode a qrcode via API + * + * @test + */ + public function testDecodeValidQrcode() + { + $file = LocalFile::fake()->validQrcode(); + + $response = $this->withHeaders(['Content-Type' => 'multipart/form-data']) + ->json('POST', '/api/qrcode/decode', [ + 'qrcode' => $file + ]); + + $response->assertStatus(200) + ->assertJsonFragment([ + 'service' => 'test@test.com', + 'account' => '', + 'options' => [ + 'algorithm' => 'sha1', + 'digits' => 6, + 'epoch' => 0, + 'period' => 30, + 'secret' => 'A4GRFHVIRBGY7UIW' + ], + 'uri' => 'otpauth://totp/test@test.com?secret=A4GRFHVIRBGY7UIW' + ]); } } \ No newline at end of file diff --git a/tests/Unit/TwoFAccountTest.php b/tests/Unit/TwoFAccountTest.php index 22eb5c04..3d06ab79 100644 --- a/tests/Unit/TwoFAccountTest.php +++ b/tests/Unit/TwoFAccountTest.php @@ -127,11 +127,11 @@ class TwoFAccountTest extends TestCase /** - * test TOTP generation via API + * test TOTP generation for a given existing account via API * * @test */ - public function testTOTPgeneration() + public function testTOTPgenerationWithProvidedAccountId() { $twofaccount = factory(TwoFAccount::class)->create([ 'service' => 'testTOTP', @@ -149,11 +149,29 @@ class TwoFAccountTest extends TestCase /** - * test TwoFAccount update via API + * test TOTP generation as preview via API * * @test */ - public function testTwoFAccountUpdate() + public function testTOTPgenerationPreview() + { + $uri = 'otpauth://totp/test@test.com?secret=A4GRFHVVRBGY7UIW&issuer=test'; + + $response = $this->actingAs($this->user, 'api') + ->json('POST', '/api/twofaccounts/otp', ['data' => $uri]) + ->assertStatus(200) + ->assertJsonStructure([ + 'otp', + ]); + } + + + /** + * test TwoFAccount TOTP update via API + * + * @test + */ + public function testTwoFAccountTOTPUpdate() { $twofaccount = factory(TwoFAccount::class)->create(); @@ -174,6 +192,37 @@ class TwoFAccountTest extends TestCase } + /** + * test TwoFAccount HOTP update via API + * + * @test + */ + public function testTwoFAccountHOTPUpdate() + { + $twofaccount = factory(TwoFAccount::class)->create([ + 'service' => 'test.com', + 'account' => 'test', + 'uri' => 'otpauth://hotp/service?counter=1&secret=A4GRFHVVRBGY7UIW' + ]); + + $response = $this->actingAs($this->user, 'api') + ->json('PUT', '/api/twofaccounts/' . $twofaccount->id, [ + 'service' => 'testUpdate.com', + 'account' => 'testUpdate', + 'icon' => 'testUpdate.png', + 'counter' => '5' + ]) + ->assertStatus(200) + ->assertJson([ + 'id' => 1, + 'service' => 'testUpdate.com', + 'account' => 'testUpdate', + 'uri' => 'otpauth://hotp/service?counter=5&secret=A4GRFHVVRBGY7UIW', + 'icon' => 'testUpdate.png', + ]); + } + + /** * test TwoFAccount update via API * @@ -187,7 +236,8 @@ class TwoFAccountTest extends TestCase $response = $this->actingAs($this->user, 'api') ->json('PUT', '/api/twofaccounts/' . $id, [ - 'service' => 'testUpdate' + 'service' => 'testUpdate', + 'icon' => 'name.png' ]) ->assertStatus(404); } @@ -235,4 +285,24 @@ class TwoFAccountTest extends TestCase ->assertStatus(204); } + + /** + * test TwoFAccounts batch deletion via API + * + * @test + */ + public function testTwoFAccountBatchDestroy() + { + $twofaccount = factory(TwoFAccount::class)->create(); + $twofaccount = factory(TwoFAccount::class)->create(); + $twofaccount = factory(TwoFAccount::class)->create(); + + $ids = \Illuminate\Support\Facades\DB::table('twofaccounts')->value('id'); + + $response = $this->actingAs($this->user, 'api') + ->json('DELETE', '/api/twofaccounts/batch', [ + 'data' => $ids]) + ->assertStatus(204); + } + } diff --git a/tests/Unit/UserTest.php b/tests/Unit/UserTest.php index 197ffccc..c71edb64 100644 --- a/tests/Unit/UserTest.php +++ b/tests/Unit/UserTest.php @@ -6,6 +6,7 @@ use App\User; use Tests\TestCase; use Illuminate\Auth\Authenticatable; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Hash; class UserTest extends TestCase { @@ -277,6 +278,10 @@ class UserTest extends TestCase $response->assertStatus(200) ->assertJsonStructure(['message']); + + $user->refresh(); + + $this->assertTrue(Hash::check('passwordUpdated', $user->password)); }