diff --git a/tests/Classes/UnexpectedEvent.php b/tests/Classes/UnexpectedEvent.php index eacc3dc0..21e509db 100644 --- a/tests/Classes/UnexpectedEvent.php +++ b/tests/Classes/UnexpectedEvent.php @@ -2,7 +2,7 @@ namespace Tests\Classes; -class unexpectedEvent +class UnexpectedEvent { // } diff --git a/tests/Feature/RouteTest.php b/tests/Feature/RouteTest.php index 387b3605..f6ff353e 100644 --- a/tests/Feature/RouteTest.php +++ b/tests/Feature/RouteTest.php @@ -28,28 +28,20 @@ public function test_exception_handler_with_web_route() #[Test] public function test_all_api_routes_are_behind_apiv1_middleware() { - Artisan::call('route:clear'); Artisan::call('route:cache'); $this->get('/'); $routes = Route::getRoutes(); foreach ($routes as $route) { - $middlewares = []; - - try { - $uri = $route->uri; - $middlewares = Route::gatherRouteMiddleware($route); - } - catch (\Exception $ex) - { - $uri = $route->uri; - //return; - } - if (Str::startsWith($route->uri(), self::API_ROUTE_PREFIX)) { + // Route middlewares can be set via action or controllers. + // Using $route->middleware() fetches middlewares from action only. + // Route::gatherRouteMiddleware($route) would have fetch middlewares from + // both action & controllers but the "Route is not bound" exception is thrown then. + // $route->middleware() is acceptable as no middleware is set from controllers in 2FAuth. $this->assertEquals(self::API_ROUTE_PREFIX, $route->getPrefix()); - $this->assertTrue(in_array(self::API_MIDDLEWARE, $middlewares)); + $this->assertTrue(in_array(self::API_MIDDLEWARE, $route->middleware())); } } } diff --git a/tests/Feature/Services/QrCodeServiceTest.php b/tests/Feature/Services/QrCodeServiceTest.php index 603d7b73..36b38adf 100644 --- a/tests/Feature/Services/QrCodeServiceTest.php +++ b/tests/Feature/Services/QrCodeServiceTest.php @@ -3,6 +3,7 @@ namespace Tests\Feature\Services; use App\Facades\QrCode; +use App\Providers\TwoFAuthServiceProvider; use App\Services\QrCodeService; use Exception; use PHPUnit\Framework\Attributes\CoversClass; @@ -20,6 +21,7 @@ */ #[CoversClass(QrCodeService::class)] #[CoversClass(QrCode::class)] +#[CoversClass(TwoFAuthServiceProvider::class)] class QrCodeServiceTest extends FeatureTestCase { private const STRING_TO_ENCODE = 'stringToEncode'; diff --git a/tests/Unit/Listeners/Authentication/FailedLoginListenerTest.php b/tests/Unit/Listeners/Authentication/FailedLoginListenerTest.php index 3ffbac24..b4c22555 100644 --- a/tests/Unit/Listeners/Authentication/FailedLoginListenerTest.php +++ b/tests/Unit/Listeners/Authentication/FailedLoginListenerTest.php @@ -10,7 +10,7 @@ use Mockery; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Test; -use Tests\Classes\unexpectedEvent; +use Tests\Classes\UnexpectedEvent; use Tests\TestCase; use TypeError; @@ -37,7 +37,7 @@ public function test_handle_throws_exception_with_unexpected_event_type() $this->expectException(TypeError::class); $request = Mockery::mock(Request::class); - $event = Mockery::mock(unexpectedEvent::class); + $event = Mockery::mock(UnexpectedEvent::class); $listener = new FailedLoginListener($request); $listener->handle($event); diff --git a/tests/Unit/Listeners/Authentication/LoginListenerTest.php b/tests/Unit/Listeners/Authentication/LoginListenerTest.php index 3b9f1999..9cc6437e 100644 --- a/tests/Unit/Listeners/Authentication/LoginListenerTest.php +++ b/tests/Unit/Listeners/Authentication/LoginListenerTest.php @@ -9,7 +9,7 @@ use Mockery; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Test; -use Tests\Classes\unexpectedEvent; +use Tests\Classes\UnexpectedEvent; use Tests\TestCase; use TypeError; @@ -36,7 +36,7 @@ public function test_handle_throws_exception_with_unexpected_event_type() $this->expectException(TypeError::class); $request = Mockery::mock(Request::class); - $event = Mockery::mock(unexpectedEvent::class); + $event = Mockery::mock(UnexpectedEvent::class); $listener = new LoginListener($request); $listener->handle($event); diff --git a/tests/Unit/Listeners/Authentication/LogoutListenerTest.php b/tests/Unit/Listeners/Authentication/LogoutListenerTest.php index a867dc45..32600db9 100644 --- a/tests/Unit/Listeners/Authentication/LogoutListenerTest.php +++ b/tests/Unit/Listeners/Authentication/LogoutListenerTest.php @@ -9,7 +9,7 @@ use Mockery; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Test; -use Tests\Classes\unexpectedEvent; +use Tests\Classes\UnexpectedEvent; use Tests\TestCase; use TypeError; @@ -36,7 +36,7 @@ public function test_handle_throws_exception_with_unexpected_event_type() $this->expectException(TypeError::class); $request = Mockery::mock(Request::class); - $event = Mockery::mock(unexpectedEvent::class); + $event = Mockery::mock(UnexpectedEvent::class); $listener = new LogoutListener($request); $listener->handle($event); diff --git a/tests/Unit/Listeners/Authentication/VisitedByProxyUserListenerTest.php b/tests/Unit/Listeners/Authentication/VisitedByProxyUserListenerTest.php index 1032d4a6..14f5b78f 100644 --- a/tests/Unit/Listeners/Authentication/VisitedByProxyUserListenerTest.php +++ b/tests/Unit/Listeners/Authentication/VisitedByProxyUserListenerTest.php @@ -9,7 +9,7 @@ use Mockery; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Test; -use Tests\Classes\unexpectedEvent; +use Tests\Classes\UnexpectedEvent; use Tests\TestCase; use TypeError; @@ -36,7 +36,7 @@ public function test_handle_throws_exception_with_unexpected_event_type() $this->expectException(TypeError::class); $request = Mockery::mock(Request::class); - $event = Mockery::mock(unexpectedEvent::class); + $event = Mockery::mock(UnexpectedEvent::class); $listener = new VisitedByProxyUserListener($request); $listener->handle($event); diff --git a/tests/Unit/Providers/Socialite/OpenIdProviderStub.php b/tests/Unit/Providers/Socialite/OpenIdProviderStub.php new file mode 100644 index 00000000..fc3b274c --- /dev/null +++ b/tests/Unit/Providers/Socialite/OpenIdProviderStub.php @@ -0,0 +1,61 @@ +buildAuthUrlFromBase('http://auth.url', $state); + } + + protected function getTokenUrl() + { + return 'http://token.url'; + } + + /** + * Get the access token response for the given code. + * + * @param string $code + * @return array + */ + public function getAccessTokenResponse($code) + { + return ['access_token' => 'access_token']; + } + + // protected function getUserByToken($token) + // { + // return ['id' => 'foo']; + // } + + // protected function mapUserToObject(array $user) + // { + // return (new User)->map(['id' => $user['id']]); + // } + + /** + * Get a fresh instance of the Guzzle HTTP client. + * + * @return \GuzzleHttp\Client|\Mockery\MockInterface + */ + protected function getHttpClient() + { + if ($this->http) { + return $this->http; + } + + return $this->http = Mockery::mock(stdClass::class); + } +} diff --git a/tests/Unit/Providers/Socialite/OpenIdProviderTest.php b/tests/Unit/Providers/Socialite/OpenIdProviderTest.php new file mode 100644 index 00000000..3c1f55ad --- /dev/null +++ b/tests/Unit/Providers/Socialite/OpenIdProviderTest.php @@ -0,0 +1,80 @@ +stateless(); + + $provider->http = Mockery::mock(stdClass::class); + $provider->http->expects('get')->with(NULL, [ + RequestOptions::HEADERS => [ + 'Authorization' => 'Bearer access_token', + ], + ])->andReturns($response = Mockery::mock(stdClass::class)); + + $response->expects('getBody')->andReturns('{ "sub": "248289761001", "name": "Jane Doe", "given_name": "Jane", "family_name": "Doe", "preferred_username": "j.doe", "nickname": "jado", "email": "janedoe@example.com", "email_verified": "true", "groups": "myGroup" }'); + $user = $provider->user(); + + $this->assertInstanceOf(User::class, $user); + $this->assertSame('248289761001', $user->id); + $this->assertSame('Jane Doe', $user->name); + $this->assertSame('Jane', $user->given_name); + $this->assertSame('Doe', $user->family_name); + $this->assertSame('j.doe', $user->preferred_username); + $this->assertSame('jado', $user->nickname); + $this->assertSame('janedoe@example.com', $user->email); + $this->assertSame('true', $user->email_verified); + $this->assertSame('myGroup', $user->groups); + } + + #[Test] + public function test_it_can_map_a_user_from_an_access_token_with_missing_fields() + { + $request = Request::create('/'); + + $provider = new OpenIdProviderStub($request, 'client_id', 'client_secret', 'redirect_uri'); + $provider->stateless(); + + $provider->http = Mockery::mock(stdClass::class); + $provider->http->expects('get')->with(NULL, [ + RequestOptions::HEADERS => [ + 'Authorization' => 'Bearer access_token', + ], + ])->andReturns($response = Mockery::mock(stdClass::class)); + + $response->expects('getBody')->andReturns('{ "sub": "248289761001" }'); + $user = $provider->user(); + + $this->assertInstanceOf(User::class, $user); + $this->assertSame('248289761001', $user->id); + $this->assertSame(null, $user->name); + $this->assertSame(null, $user->given_name); + $this->assertSame(null, $user->family_name); + $this->assertSame(null, $user->preferred_username); + $this->assertSame(null, $user->nickname); + $this->assertSame(null, $user->email); + $this->assertSame(null, $user->email_verified); + $this->assertSame(null, $user->groups); + } +} diff --git a/tests/Unit/Rules/IsValidRegexTest.php b/tests/Unit/Rules/IsValidRegexTest.php new file mode 100644 index 00000000..352d0821 --- /dev/null +++ b/tests/Unit/Rules/IsValidRegexTest.php @@ -0,0 +1,71 @@ + [new IsValidRegex]]); + + $this->assertFalse($validator->fails()); + } + + /** + * Provide Valid data for validation test + */ + public static function provideValidData() : array + { + return [ + [[ + 'value' => '^[\w\.=-]+@[\w\.-]+\.[\w]{2,3}$', + ]], + [[ + 'value' => '^\d{1,3}[.]\d{1,3}[.]\d{1,3}[.]\d{1,3}$', + ]], + [[ + 'value' => '\b([4]\d{3}[\s]\d{4}[\s]\d{4}[\s]\d{4}|[4]\d{3}[-]\d{4}[-]\d{4}[-]\d{4}|[4]\d{3}[.]\d{4}[.]\d{4}[.]\d{4}|[4]\d{3}\d{4}\d{4}\d{4})\b', + ]], + [[ + 'value' => '(?i)\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'".,<>?«»“”‘’]))', + ]], + ]; + } + + #[Test] + #[DataProvider('provideInvalidData')] + public function test_invalid_data(array $data) : void + { + $validator = Validator::make($data, ['value' => [new IsValidRegex]]); + + $this->assertTrue($validator->fails()); + } + + /** + * Provide Valid data for validation test + */ + public static function provideInvalidData() : array + { + return [ + [[ + 'value' => 'HOHI\\', + ]], + ]; + } +} diff --git a/tests/Unit/UserModelTest.php b/tests/Unit/UserModelTest.php index 8c5ff87b..492e0aa5 100644 --- a/tests/Unit/UserModelTest.php +++ b/tests/Unit/UserModelTest.php @@ -59,4 +59,89 @@ public function test_groups_relation() $groups = $user->groups(); $this->assertHasManyRelation($groups, $user, new Group()); } + + #[Test] + public function test_equals_is_true() + { + $user = User::factory()->make([ + 'oauth_id' => 'fake_id', + 'oauth_provider' => 'fake_provider', + ]); + $anotherUser = User::factory()->make([ + 'name' => $user->name, + 'email ' => $user->email, + 'oauth_id' => $user->oauth_id, + 'oauth_provider' => $user->oauth_provider, + ]); + + $this->assertTrue($user->equals($anotherUser)); + } + + #[Test] + public function test_equals_is_false_if_name_differs() + { + $user = User::factory()->make([ + 'oauth_id' => 'fake_id', + 'oauth_provider' => 'fake_provider', + ]); + $anotherUser = User::factory()->make([ + 'name' => 'another name', + 'email ' => $user->email, + 'oauth_id' => $user->oauth_id, + 'oauth_provider' => $user->oauth_provider, + ]); + + $this->assertFalse($user->equals($anotherUser)); + } + + #[Test] + public function test_equals_is_false_if_email_differs() + { + $user = User::factory()->make([ + 'oauth_id' => 'fake_id', + 'oauth_provider' => 'fake_provider', + ]); + $anotherUser = User::factory()->make([ + 'name' => $user->name, + 'email ' => 'another@email.com', + 'oauth_id' => $user->oauth_id, + 'oauth_provider' => $user->oauth_provider, + ]); + + $this->assertFalse($user->equals($anotherUser)); + } + + #[Test] + public function test_equals_is_false_if_oauthid_differs() + { + $user = User::factory()->make([ + 'oauth_id' => 'fake_id', + 'oauth_provider' => 'fake_provider', + ]); + $anotherUser = User::factory()->make([ + 'name' => $user->name, + 'email ' => $user->email, + 'oauth_id' => 'another_fake_id', + 'oauth_provider' => $user->oauth_provider, + ]); + + $this->assertFalse($user->equals($anotherUser)); + } + + #[Test] + public function test_equals_is_false_if_oauth_provider_differs() + { + $user = User::factory()->make([ + 'oauth_id' => 'fake_id', + 'oauth_provider' => 'fake_provider', + ]); + $anotherUser = User::factory()->make([ + 'name' => $user->name, + 'email ' => $user->email, + 'oauth_id' => $user->oauth_id, + 'oauth_provider' => 'another_provider', + ]); + + $this->assertFalse($user->equals($anotherUser)); + } }