Skip to content

Commit

Permalink
Add tests for login mutation
Browse files Browse the repository at this point in the history
  • Loading branch information
wimski committed Apr 21, 2021
1 parent 4ea7945 commit 4acf396
Show file tree
Hide file tree
Showing 11 changed files with 254 additions and 74 deletions.
5 changes: 4 additions & 1 deletion src/GraphQL/Mutations/Login.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ public function __invoke($_, array $args): array
{
$userProvider = $this->createUserProvider();

$user = $userProvider->retrieveByCredentials($args);
$user = $userProvider->retrieveByCredentials([
'email' => $args['email'],
'password' => $args['password'],
]);

if (! $user) {
throw new AuthenticationException('The provided credentials are incorrect.');
Expand Down
2 changes: 2 additions & 0 deletions tests/Integration/AbstractIntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace DanielDeWit\LighthouseSanctum\Tests\Integration;

use DanielDeWit\LighthouseSanctum\Providers\LighthouseSanctumServiceProvider;
use DanielDeWit\LighthouseSanctum\Tests\stubs\Users\UserHasApiTokens;
use DanielDeWit\LighthouseSanctum\Tests\Traits\AssertsGraphQLErrorMessage;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Testing\RefreshDatabase;
Expand Down Expand Up @@ -46,6 +47,7 @@ protected function defineDatabaseMigrations(): void
*/
protected function defineEnvironment($app): void
{
$app['config']->set('auth.providers.users.model', UserHasApiTokens::class);
$app['config']->set('lighthouse.schema.register', $this->getStubsPath('schema.graphql'));
$app['config']->set('lighthouse.guard', 'sanctum');
}
Expand Down
30 changes: 3 additions & 27 deletions tests/Integration/GraphQL/Mutations/ForgotPasswordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,24 @@

namespace DanielDeWit\LighthouseSanctum\Tests\Integration\GraphQL\Mutations;

use DanielDeWit\LighthouseSanctum\Contracts\Services\ResetPasswordServiceInterface;
use DanielDeWit\LighthouseSanctum\GraphQL\Mutations\ForgotPassword;
use DanielDeWit\LighthouseSanctum\Tests\Integration\AbstractIntegrationTest;
use DanielDeWit\LighthouseSanctum\Tests\stubs\Users\UserCanResetPassword;
use DanielDeWit\LighthouseSanctum\Tests\stubs\Users\UserHasApiTokens;
use Illuminate\Auth\Notifications\ResetPassword;
use Illuminate\Auth\Notifications\ResetPassword as ResetPasswordNotification;
use Illuminate\Contracts\Auth\PasswordBroker;
use Illuminate\Contracts\Translation\Translator;
use Illuminate\Support\Facades\Notification;
use Laravel\Sanctum\Sanctum;

class ForgotPasswordTest extends AbstractIntegrationTest
{
protected ForgotPassword $mutation;

protected function setUp(): void
{
parent::setUp();

$this->app['config']->set('auth.providers', [
'users' => [
'driver' => 'eloquent',
'model' => UserCanResetPassword::class,
],
]);

$this->mutation = new ForgotPassword(
$this->app->make(PasswordBroker::class),
$this->app->make(ResetPasswordServiceInterface::class),
$this->app->make(Translator::class),
);
}

/**
* @test
*/
public function it_sends_a_reset_password_notification(): void
{
Notification::fake();

/** @var UserCanResetPassword $user */
$user = UserCanResetPassword::factory()->create([
/** @var UserHasApiTokens $user */
$user = UserHasApiTokens::factory()->create([
'email' => 'john.doe@gmail.com',
]);

Expand Down
56 changes: 56 additions & 0 deletions tests/Integration/GraphQL/Mutations/LoginTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

declare(strict_types=1);

namespace DanielDeWit\LighthouseSanctum\Tests\Integration\GraphQL\Mutations;

use DanielDeWit\LighthouseSanctum\Tests\Integration\AbstractIntegrationTest;
use DanielDeWit\LighthouseSanctum\Tests\stubs\Users\UserHasApiTokens;
use Illuminate\Support\Facades\Hash;
use Illuminate\Testing\TestResponse;

class LoginTest extends AbstractIntegrationTest
{
/**
* @test
*/
public function it_logs_a_user_in(): void
{
UserHasApiTokens::factory()->create([
'email' => 'foo@bar.com',
'password' => Hash::make('supersecret'),
]);

$this->makeRequest()->assertJsonStructure([
'data' => [
'login' => [
'token',
],
],
]);
}

/**
* @test
*/
public function it_returns_an_error_if_the_credentials_are_incorrect(): void
{
$response = $this->makeRequest();

$this->assertGraphQLErrorMessage($response, 'The provided credentials are incorrect.');
}

protected function makeRequest(): TestResponse
{
return $this->graphQL(/** @lang GraphQL */'
mutation {
login(input: {
email: "foo@bar.com",
password: "supersecret"
}) {
token
}
}
');
}
}
15 changes: 0 additions & 15 deletions tests/Integration/GraphQL/Mutations/LogoutTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,12 @@

namespace DanielDeWit\LighthouseSanctum\Tests\Integration\GraphQL\Mutations;

use DanielDeWit\LighthouseSanctum\GraphQL\Mutations\Logout;
use DanielDeWit\LighthouseSanctum\Tests\Integration\AbstractIntegrationTest;
use DanielDeWit\LighthouseSanctum\Tests\stubs\Users\UserHasApiTokens;
use Illuminate\Contracts\Auth\Factory as AuthFactory;
use Illuminate\Contracts\Translation\Translator;
use Laravel\Sanctum\Sanctum;

class LogoutTest extends AbstractIntegrationTest
{
protected Logout $mutation;

protected function setUp(): void
{
parent::setUp();

$this->mutation = new Logout(
$this->app->make(AuthFactory::class),
$this->app->make(Translator::class),
);
}

/**
* @test
*/
Expand Down
50 changes: 50 additions & 0 deletions tests/Traits/MocksUserProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace DanielDeWit\LighthouseSanctum\Tests\Traits;

use Illuminate\Auth\AuthManager;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Config\Repository as Config;
use Illuminate\Foundation\Auth\User;
use Mockery;
use Mockery\MockInterface;

trait MocksUserProvider
{
/**
* @return AuthManager|MockInterface
*/
protected function mockAuthManager(?UserProvider $userProvider)
{
/** @var AuthManager|MockInterface $authManager */
$authManager = Mockery::mock(AuthManager::class)
->shouldReceive('createUserProvider')
->with('sanctum-provider')
->andReturn($userProvider)
->getMock();

return $authManager;
}

/**
* @return Config|MockInterface
*/
protected function mockConfig()
{
/** @var Config|MockInterface $config */
$config = Mockery::mock(Config::class)
->shouldReceive('get')
->with('lighthouse-sanctum.provider')
->andReturn('sanctum-provider')
->getMock();

return $config;
}

/**
* @return UserProvider|MockInterface
*/
abstract protected function mockUserProvider(?User $user);
}
136 changes: 136 additions & 0 deletions tests/Unit/GraphQL/Mutations/LoginTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
<?php

declare(strict_types=1);

namespace DanielDeWit\LighthouseSanctum\Tests\Unit\GraphQL\Mutations;

use DanielDeWit\LighthouseSanctum\Exceptions\HasApiTokensException;
use DanielDeWit\LighthouseSanctum\GraphQL\Mutations\Login;
use DanielDeWit\LighthouseSanctum\Tests\stubs\Users\UserHasApiTokens;
use DanielDeWit\LighthouseSanctum\Tests\Traits\MocksUserProvider;
use DanielDeWit\LighthouseSanctum\Tests\Unit\AbstractUnitTest;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Foundation\Auth\User;
use Laravel\Sanctum\NewAccessToken;
use Mockery;
use Mockery\MockInterface;
use RuntimeException;

class LoginTest extends AbstractUnitTest
{
use MocksUserProvider;

/**
* @test
*/
public function it_logs_a_user_in(): void
{
$token = Mockery::mock(NewAccessToken::class);
$token->plainTextToken = '1234567890';

/** @var UserHasApiTokens|MockInterface $user */
$user = Mockery::mock(UserHasApiTokens::class)
->shouldReceive('createToken')
->with('default')
->andReturn($token)
->getMock();

$userProvider = $this->mockUserProvider($user);

$mutation = new Login(
$this->mockAuthManager($userProvider),
$this->mockConfig(),
);

$result = $mutation(null, [
'email' => 'foo@bar.com',
'password' => 'supersecret',
]);

static::assertIsArray($result);
static::assertCount(1, $result);
static::assertSame('1234567890', $result['token']);
}

/**
* @test
*/
public function it_throws_an_exception_if_the_user_provider_is_not_found(): void
{
static::expectException(RuntimeException::class);
static::expectExceptionMessage('User provider not found.');

$mutation = new Login(
$this->mockAuthManager(null),
$this->mockConfig(),
);

$mutation(null, [
'email' => 'foo@bar.com',
'password' => 'supersecret',
]);
}

/**
* @test
*/
public function it_throws_an_exception_if_the_credentials_are_incorrect(): void
{
static::expectException(AuthenticationException::class);
static::expectExceptionMessage('The provided credentials are incorrect.');

$userProvider = $this->mockUserProvider(null);

$mutation = new Login(
$this->mockAuthManager($userProvider),
$this->mockConfig(),
);

$mutation(null, [
'email' => 'foo@bar.com',
'password' => 'supersecret',
]);
}

/**
* @test
*/
public function it_throws_an_exception_if_the_user_does_not_have_the_has_api_tokens_trait(): void
{
$user = Mockery::mock(User::class);

static::expectException(HasApiTokensException::class);
static::expectExceptionMessage('"' . get_class($user) . '" must implement "Laravel\Sanctum\Contracts\HasApiTokens".');

$userProvider = $this->mockUserProvider($user);

$mutation = new Login(
$this->mockAuthManager($userProvider),
$this->mockConfig(),
);

$mutation(null, [
'email' => 'foo@bar.com',
'password' => 'supersecret',
]);
}

/**
* @return UserProvider|MockInterface
*/
protected function mockUserProvider(?User $user)
{
/** @var UserProvider|MockInterface $userProvider */
$userProvider = Mockery::mock(UserProvider::class)
->shouldReceive('retrieveByCredentials')
->with([
'email' => 'foo@bar.com',
'password' => 'supersecret',
])
->andReturn($user)
->getMock();

return $userProvider;
}
}
2 changes: 1 addition & 1 deletion tests/Unit/GraphQL/Mutations/LogoutTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class LogoutTest extends AbstractUnitTest
/**
* @test
*/
public function it_log_a_user_out(): void
public function it_logs_a_user_out(): void
{
/** @var PersonalAccessToken|MockInterface $token */
$token = Mockery::mock(PersonalAccessToken::class)
Expand Down
18 changes: 0 additions & 18 deletions tests/stubs/Users/UserCanResetPassword.php

This file was deleted.

12 changes: 0 additions & 12 deletions tests/stubs/Users/UserCanResetPasswordFactory.php

This file was deleted.

0 comments on commit 4acf396

Please sign in to comment.