From 6c20ea988100588a8ae084e0f2441ab3cf7c4d68 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Wed, 4 Jul 2018 19:20:33 -0700 Subject: [PATCH] Add tests for changed controllers --- .../Controllers/Base/AccountController.php | 86 ----------- .../Base/AccountControllerTest.php | 132 ----------------- .../Controllers/Base/IndexControllerTest.php | 2 +- .../Base/SecurityControllerTest.php | 133 +++++++----------- .../Http/Controllers/ControllerTestCase.php | 13 ++ 5 files changed, 62 insertions(+), 304 deletions(-) delete mode 100644 app/Http/Controllers/Base/AccountController.php delete mode 100644 tests/Unit/Http/Controllers/Base/AccountControllerTest.php diff --git a/app/Http/Controllers/Base/AccountController.php b/app/Http/Controllers/Base/AccountController.php deleted file mode 100644 index 90d590ff2..000000000 --- a/app/Http/Controllers/Base/AccountController.php +++ /dev/null @@ -1,86 +0,0 @@ -alert = $alert; - $this->updateService = $updateService; - $this->sessionGuard = $authManager->guard(); - } - - /** - * Display base account information page. - * - * @return \Illuminate\View\View - */ - public function index() - { - return view('base.account'); - } - - /** - * Update details for a user's account. - * - * @param \Pterodactyl\Http\Requests\Base\AccountDataFormRequest $request - * @return \Illuminate\Http\RedirectResponse - * - * @throws \Pterodactyl\Exceptions\Model\DataValidationException - * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException - */ - public function update(AccountDataFormRequest $request) - { - // Prevent logging this specific session out when the password is changed. This will - // automatically update the user's password anyways, so no need to do anything else here. - if ($request->input('do_action') === 'password') { - $this->sessionGuard->logoutOtherDevices($request->input('new_password')); - } else { - if ($request->input('do_action') === 'email') { - $data = ['email' => $request->input('new_email')]; - } elseif ($request->input('do_action') === 'identity') { - $data = $request->only(['name_first', 'name_last', 'username']); - } else { - $data = []; - } - - $this->updateService->setUserLevel(User::USER_LEVEL_USER); - $this->updateService->handle($request->user(), $data); - } - - $this->alert->success(trans('base.account.details_updated'))->flash(); - - return redirect()->route('account'); - } -} diff --git a/tests/Unit/Http/Controllers/Base/AccountControllerTest.php b/tests/Unit/Http/Controllers/Base/AccountControllerTest.php deleted file mode 100644 index 2b3fc674a..000000000 --- a/tests/Unit/Http/Controllers/Base/AccountControllerTest.php +++ /dev/null @@ -1,132 +0,0 @@ -alert = m::mock(AlertsMessageBag::class); - $this->updateService = m::mock(UserUpdateService::class); - $this->authManager = m::mock(AuthManager::class); - $this->sessionGuard = m::mock(SessionGuard::class); - - $this->authManager->shouldReceive('guard')->once()->andReturn($this->sessionGuard); - } - - /** - * Test the index controller. - */ - public function testIndexController() - { - $response = $this->getController()->index(); - - $this->assertIsViewResponse($response); - $this->assertViewNameEquals('base.account', $response); - } - - /** - * Test controller when password is being updated. - */ - public function testUpdateControllerForPassword() - { - $this->setRequestMockClass(AccountDataFormRequest::class); - - $this->request->shouldReceive('input')->with('do_action')->andReturn('password'); - $this->request->shouldReceive('input')->with('new_password')->once()->andReturn('test-password'); - $this->sessionGuard->shouldReceive('logoutOtherDevices')->once()->with('test-password')->andReturnSelf(); - - $this->alert->shouldReceive('success->flash')->once()->andReturnNull(); - - $response = $this->getController()->update($this->request); - $this->assertIsRedirectResponse($response); - $this->assertRedirectRouteEquals('account', $response); - } - - /** - * Test controller when email is being updated. - */ - public function testUpdateControllerForEmail() - { - $this->setRequestMockClass(AccountDataFormRequest::class); - $user = $this->generateRequestUserModel(); - - $this->request->shouldReceive('input')->with('do_action')->andReturn('email'); - $this->request->shouldReceive('input')->with('new_email')->once()->andReturn('test@example.com'); - - $this->updateService->shouldReceive('setUserLevel')->with(User::USER_LEVEL_USER)->once()->andReturnNull(); - $this->updateService->shouldReceive('handle')->with($user, ['email' => 'test@example.com'])->once()->andReturn(collect()); - $this->alert->shouldReceive('success->flash')->once()->andReturnNull(); - - $response = $this->getController()->update($this->request); - $this->assertIsRedirectResponse($response); - $this->assertRedirectRouteEquals('account', $response); - } - - /** - * Test controller when identity is being updated. - */ - public function testUpdateControllerForIdentity() - { - $this->setRequestMockClass(AccountDataFormRequest::class); - $user = $this->generateRequestUserModel(); - - $this->request->shouldReceive('input')->with('do_action')->andReturn('identity'); - $this->request->shouldReceive('only')->with(['name_first', 'name_last', 'username'])->once()->andReturn([ - 'test_data' => 'value', - ]); - - $this->updateService->shouldReceive('setUserLevel')->with(User::USER_LEVEL_USER)->once()->andReturnNull(); - $this->updateService->shouldReceive('handle')->with($user, ['test_data' => 'value'])->once()->andReturn(collect()); - $this->alert->shouldReceive('success->flash')->once()->andReturnNull(); - - $response = $this->getController()->update($this->request); - $this->assertIsRedirectResponse($response); - $this->assertRedirectRouteEquals('account', $response); - } - - /** - * Return an instance of the controller for testing. - * - * @return \Pterodactyl\Http\Controllers\Base\AccountController - */ - private function getController(): AccountController - { - return new AccountController($this->alert, $this->authManager, $this->updateService); - } -} diff --git a/tests/Unit/Http/Controllers/Base/IndexControllerTest.php b/tests/Unit/Http/Controllers/Base/IndexControllerTest.php index 6f18138ad..6e8cd38cf 100644 --- a/tests/Unit/Http/Controllers/Base/IndexControllerTest.php +++ b/tests/Unit/Http/Controllers/Base/IndexControllerTest.php @@ -76,7 +76,7 @@ class IndexControllerTest extends ControllerTestCase ->shouldReceive('filterUserAccessServers')->with($model, User::FILTER_LEVEL_ALL) ->once()->andReturn($paginator); - $response = $this->controller->getIndex($this->request); + $response = $this->controller->index($this->request); $this->assertIsViewResponse($response); $this->assertViewNameEquals('base.index', $response); $this->assertViewHasKey('servers', $response); diff --git a/tests/Unit/Http/Controllers/Base/SecurityControllerTest.php b/tests/Unit/Http/Controllers/Base/SecurityControllerTest.php index 363a59801..5423f0938 100644 --- a/tests/Unit/Http/Controllers/Base/SecurityControllerTest.php +++ b/tests/Unit/Http/Controllers/Base/SecurityControllerTest.php @@ -3,6 +3,8 @@ namespace Tests\Unit\Http\Controllers\Base; use Mockery as m; +use Illuminate\Http\Response; +use Illuminate\Support\Collection; use Prologue\Alerts\AlertsMessageBag; use Illuminate\Contracts\Config\Repository; use Tests\Unit\Http\Controllers\ControllerTestCase; @@ -53,125 +55,86 @@ class SecurityControllerTest extends ControllerTestCase $this->twoFactorSetupService = m::mock(TwoFactorSetupService::class); } - /** - * Test the index controller when using a database driver. - */ - public function testIndexControllerWithDatabaseDriver() - { - $model = $this->generateRequestUserModel(); - - $this->config->shouldReceive('get')->with('session.driver')->once()->andReturn('database'); - $this->repository->shouldReceive('getUserSessions')->with($model->id)->once()->andReturn(collect(['sessions'])); - - $response = $this->getController()->index($this->request); - $this->assertIsViewResponse($response); - $this->assertViewNameEquals('base.security', $response); - $this->assertViewHasKey('sessions', $response); - $this->assertViewKeyEquals('sessions', collect(['sessions']), $response); - } - - /** - * Test the index controller when not using the database driver. - */ - public function testIndexControllerWithoutDatabaseDriver() - { - $this->config->shouldReceive('get')->with('session.driver')->once()->andReturn('redis'); - - $response = $this->getController()->index($this->request); - $this->assertIsViewResponse($response); - $this->assertViewNameEquals('base.security', $response); - $this->assertViewHasKey('sessions', $response); - $this->assertViewKeyEquals('sessions', null, $response); - } - /** * Test TOTP generation controller. */ - public function testGenerateTotpController() + public function testIndexWithout2FactorEnabled() { - $model = $this->generateRequestUserModel(); + $model = $this->generateRequestUserModel(['use_totp' => 0]); - $this->twoFactorSetupService->shouldReceive('handle')->with($model)->once()->andReturn('qrCodeImage'); + $this->twoFactorSetupService->shouldReceive('handle')->with($model)->once()->andReturn(new Collection([ + 'image' => 'test-image', + 'secret' => 'secret-code', + ])); - $response = $this->getController()->generateTotp($this->request); + $response = $this->getController()->index($this->request); $this->assertIsJsonResponse($response); - $this->assertResponseJsonEquals(['qrImage' => 'qrCodeImage'], $response); + $this->assertResponseCodeEquals(Response::HTTP_OK, $response); + $this->assertResponseJsonEquals(['enabled' => false, 'qr_image' => 'test-image', 'secret' => 'secret-code'], $response); } /** * Test TOTP setting controller when no exception is thrown by the service. */ - public function testSetTotpControllerSuccess() + public function testIndexWith2FactorEnabled() { - $model = $this->generateRequestUserModel(); + $this->generateRequestUserModel(['use_totp' => 1]); - $this->request->shouldReceive('input')->with('token')->once()->andReturn('testToken'); - $this->toggleTwoFactorService->shouldReceive('handle')->with($model, 'testToken')->once(); - - $response = $this->getController()->setTotp($this->request); - $this->assertIsResponse($response); - $this->assertSame('true', $response->getContent()); + $response = $this->getController()->index($this->request); + $this->assertIsJsonResponse($response); + $this->assertResponseCodeEquals(Response::HTTP_OK, $response); + $this->assertResponseJsonEquals(['enabled' => true], $response); } /** - * Test TOTP setting controller when an exception is thrown by the service. + * Test that a 2FA token can be stored or deleted. + * + * @param string $func + * @dataProvider functionCallDataProvider */ - public function testSetTotpControllerWhenExceptionIsThrown() + public function testStore(string $func) { $model = $this->generateRequestUserModel(); - $this->request->shouldReceive('input')->with('token')->once()->andReturn('testToken'); - $this->toggleTwoFactorService->shouldReceive('handle')->with($model, 'testToken')->once()->andThrow(new TwoFactorAuthenticationTokenInvalid()); + $this->mockRequestInput('token', 'some-token'); - $response = $this->getController()->setTotp($this->request); - $this->assertIsResponse($response); - $this->assertSame('false', $response->getContent()); + if ($func === 'delete') { + $this->toggleTwoFactorService->shouldReceive('handle')->with($model, 'some-token', false); + } else { + $this->toggleTwoFactorService->shouldReceive('handle')->with($model, 'some-token'); + } + + $response = $this->getController()->{$func}($this->request); + $this->assertIsJsonResponse($response); + $this->assertResponseCodeEquals(Response::HTTP_OK, $response); + $this->assertResponseJsonEquals(['success' => true], $response); } /** - * Test the disable totp controller when no exception is thrown by the service. + * Test an invalid token exception is handled. + * + * @param string $func + * @dataProvider functionCallDataProvider */ - public function testDisableTotpControllerSuccess() + public function testStoreWithInvalidTokenException(string $func) { - $model = $this->generateRequestUserModel(); + $this->generateRequestUserModel(); - $this->request->shouldReceive('input')->with('token')->once()->andReturn('testToken'); - $this->toggleTwoFactorService->shouldReceive('handle')->with($model, 'testToken', false)->once()->andReturn(true); + $this->mockRequestInput('token'); + $this->toggleTwoFactorService->shouldReceive('handle')->andThrow(new TwoFactorAuthenticationTokenInvalid); - $response = $this->getController()->disableTotp($this->request); - $this->assertIsRedirectResponse($response); - $this->assertRedirectRouteEquals('account.security', $response); + $response = $this->getController()->{$func}($this->request); + $this->assertIsJsonResponse($response); + $this->assertResponseCodeEquals(Response::HTTP_OK, $response); + $this->assertResponseJsonEquals(['success' => false], $response); } /** - * Test the disable totp controller when an exception is thrown by the service. + * @return array */ - public function testDisableTotpControllerWhenExceptionIsThrown() + public function functionCallDataProvider() { - $model = $this->generateRequestUserModel(); - - $this->request->shouldReceive('input')->with('token')->once()->andReturn('testToken'); - $this->toggleTwoFactorService->shouldReceive('handle')->with($model, 'testToken', false)->once()->andThrow(new TwoFactorAuthenticationTokenInvalid); - $this->alert->shouldReceive('danger')->with(trans('base.security.2fa_disable_error'))->once()->andReturnSelf(); - $this->alert->shouldReceive('flash')->withNoArgs()->once()->andReturnNull(); - - $response = $this->getController()->disableTotp($this->request); - $this->assertIsRedirectResponse($response); - $this->assertRedirectRouteEquals('account.security', $response); - } - - /** - * Test the revoke controller. - */ - public function testRevokeController() - { - $model = $this->generateRequestUserModel(); - - $this->repository->shouldReceive('deleteUserSession')->with($model->id, 123)->once()->andReturnNull(); - - $response = $this->getController()->revoke($this->request, 123); - $this->assertIsRedirectResponse($response); - $this->assertRedirectRouteEquals('account.security', $response); + return [['store'], ['delete']]; } /** diff --git a/tests/Unit/Http/Controllers/ControllerTestCase.php b/tests/Unit/Http/Controllers/ControllerTestCase.php index 6caf9abda..3a6ea5cb2 100644 --- a/tests/Unit/Http/Controllers/ControllerTestCase.php +++ b/tests/Unit/Http/Controllers/ControllerTestCase.php @@ -66,6 +66,19 @@ abstract class ControllerTestCase extends TestCase } } + /** + * Mocks a request input call. + * + * @param string $param + * @param mixed $return + */ + protected function mockRequestInput(string $param, $return = null) + { + $this->request->shouldReceive('input')->withArgs(function ($k) use ($param) { + return $k === $param; + })->andReturn($return); + } + /** * Build and return a mocked controller instance to use for testing. *