Commit 4bc3f161 authored by Jacob Priddy's avatar Jacob Priddy 👌

Merge branch '14-tests-for-database-implementations' into 'master'

Resolve "tests for database implementations"

Closes #14

See merge request kretschmar/doorcode!18
parents efda7e1e a5411aaf
Pipeline #2595 passed with stages
in 2 minutes and 5 seconds
......@@ -36,15 +36,14 @@ test_web_backend_unit:
- cd src/web/backend
- vendor/bin/phpunit --testsuite Unit
test_web_backend_feature:
stage: test
script:
- cd src/web/backend
- vendor/bin/phpunit --testsuite Feature
test_web_backend_integration:
test_web_backend_database:
stage: test
script:
- cd src/web/backend
- vendor/bin/phpunit --testsuite Integration
- vendor/bin/phpunit --testsuite Database
......@@ -11,3 +11,4 @@ Homestead.yaml
npm-debug.log
yarn-error.log
.php_cs.cache
cov/
......@@ -2,13 +2,10 @@
namespace App;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Door extends Authenticatable
{
use SoftDeletes;
protected $fillable = [
'*'
];
......
......@@ -19,23 +19,24 @@
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
<testsuite name="Integration">
<directory suffix="Test.php">./tests/Integration</directory>
<testsuite name="Database">
<directory suffix="Test.php">./tests/Database</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./app</directory>
<directory suffix=".php">./src</directory>
<exclude>
<directory suffix=".php">./app/Console</directory>
<directory suffix="ServiceProvider.php">./src</directory>
</exclude>
</whitelist>
</filter>
<php>
<server name="APP_ENV" value="testing"/>
<server name="BCRYPT_ROUNDS" value="4"/>
<server name="CACHE_DRIVER" value="array"/>
<!-- <server name="DB_CONNECTION" value="sqlite"/>-->
<!-- <server name="DB_DATABASE" value=":memory:"/>-->
<!-- <server name="MAIL_DRIVER" value="array"/>-->
<!-- <server name="QUEUE_CONNECTION" value="sync"/>-->
<server name="SESSION_DRIVER" value="array"/>
</php>
</phpunit>
......@@ -12,13 +12,13 @@ class DatabaseDoorsRepository implements DoorsRepository
*/
public function create(Door $door): Door
{
$dbDoor = \App\Door::create(
[
'location' => $door->getLocation(),
'name' => $door->getName(),
'token' => hash('sha256', $door->getToken()),
]
);
$dbDoor = new \App\Door();
$dbDoor->location = $door->getLocation();
$dbDoor->name = $door->getName();
$dbDoor->api_token = hash('sha512', $door->getToken());
$dbDoor->save();
return new Door(
$dbDoor->id,
......@@ -35,7 +35,7 @@ class DatabaseDoorsRepository implements DoorsRepository
*/
public function getByToken(string $token): ?Door
{
$dbDoor = \App\Door::where('api_token', hash('sha256', $token))->first();
$dbDoor = \App\Door::where('api_token', hash('sha512', $token))->first();
if (!$dbDoor) {
return null;
......
......@@ -9,7 +9,6 @@ use Source\Exceptions\EntityNotFoundException;
use Source\Gateways\Users\DatabaseUsersRepository;
use Source\Gateways\Groups\DatabaseGroupsRepository;
// TODO: Write tests for this
class DatabaseGroupUserRepository implements GroupUserRepository
{
/**
......@@ -18,7 +17,7 @@ class DatabaseGroupUserRepository implements GroupUserRepository
public function getGroupsForUser(string $userId): array
{
/** @var User|null $user */
$user = User::find($userId);
$user = User::find((int)$userId);
if (!$user) {
throw new EntityNotFoundException();
......@@ -35,7 +34,7 @@ class DatabaseGroupUserRepository implements GroupUserRepository
public function getUsersForGroup(string $groupId): array
{
/** @var Group|null $group */
$group = Group::find($groupId);
$group = Group::find((int)$groupId);
if (!$group) {
throw new EntityNotFoundException();
......@@ -52,9 +51,9 @@ class DatabaseGroupUserRepository implements GroupUserRepository
public function addUserToGroup(string $userId, string $groupId): void
{
/** @var User|null $user */
$user = User::find($userId);
$user = User::find((int)$userId);
/** @var Group|null $group */
$group = Group::find($groupId);
$group = Group::find((int)$groupId);
if (!$user || !$group) {
throw new EntityNotFoundException();
......@@ -69,9 +68,9 @@ class DatabaseGroupUserRepository implements GroupUserRepository
public function removeUserFromGroup(string $userId, string $groupId): void
{
/** @var User|null $user */
$user = User::find($userId);
$user = User::find((int)$userId);
/** @var Group|null $group */
$group = Group::find($groupId);
$group = Group::find((int)$groupId);
if (!$user || !$group) {
throw new EntityNotFoundException();
......
......@@ -5,7 +5,6 @@ namespace Source\Gateways\Groups;
use Source\Entities\Group;
// TODO: Write tests for this
class DatabaseGroupsRepository implements GroupsRepository
{
/**
......@@ -13,7 +12,7 @@ class DatabaseGroupsRepository implements GroupsRepository
*/
public function get(string $groupId): ?Group
{
$group = \App\Group::find($groupId);
$group = \App\Group::find((int)$groupId);
if (!$group) {
return null;
......@@ -22,6 +21,10 @@ class DatabaseGroupsRepository implements GroupsRepository
return self::makeGroupFromDbGroup($group);
}
/**
* @param \App\Group $group
* @return \Source\Entities\Group
*/
public static function makeGroupFromDbGroup(\App\Group $group): Group
{
return new Group(
......@@ -58,7 +61,7 @@ class DatabaseGroupsRepository implements GroupsRepository
return self::makeGroupFromDbGroup($newGroup);
}
public static function fillBasicAttrs(Group $group, \App\Group $dbGroup): \App\Group
protected static function fillBasicAttrs(Group $group, \App\Group $dbGroup): \App\Group
{
$dbGroup->title = $group->getTitle();
$dbGroup->description = $group->getDescription();
......@@ -71,7 +74,7 @@ class DatabaseGroupsRepository implements GroupsRepository
*/
public function update(string $groupId, Group $group): ?Group
{
$dbGroup = \App\Group::find($groupId);
$dbGroup = \App\Group::find((int)$groupId);
if (!$dbGroup) {
return null;
......@@ -89,7 +92,7 @@ class DatabaseGroupsRepository implements GroupsRepository
*/
public function delete(string $groupId): bool
{
\App\Group::destroy($groupId);
return \App\Group::destroy((int)$groupId);
}
/**
......@@ -97,6 +100,6 @@ class DatabaseGroupsRepository implements GroupsRepository
*/
public function exists(string $groupId): bool
{
return \App\Group::find($groupId) !== null;
return $this->get($groupId) !== null;
}
}
......@@ -69,10 +69,11 @@ class DatabaseTokensRepository implements TokensRepository
*/
public function invalidateToken(string $token): void
{
$found = \App\Token::where('api_token', $token)
->where('expires_at', '<', Carbon::now())
->where('expires_at', '!=', null)
->first();
$found = \App\Token::where('api_token', $token)->where('expires_at', '>', Carbon::now())->orWhere(
static function (Builder $query) use ($token) {
$query->where('api_token', $token)->where('expires_at', null);
}
)->first();
if ($found) {
$found->expires_at = Carbon::now();
......
......@@ -5,7 +5,6 @@ namespace Source\Gateways\Users;
use Source\Entities\User;
// TODO: Write tests for this
class DatabaseUsersRepository implements UsersRepository
{
/**
......@@ -13,7 +12,7 @@ class DatabaseUsersRepository implements UsersRepository
*/
public function get(string $userId): ?User
{
$user = \App\User::find($userId);
$user = \App\User::find((int)$userId);
if (!$user) {
return null;
......@@ -22,6 +21,10 @@ class DatabaseUsersRepository implements UsersRepository
return self::makeUserFromDbUser($user);
}
/**
* @param \App\User $user
* @return \Source\Entities\User
*/
public static function makeUserFromDbUser(\App\User $user): User
{
return new User(
......@@ -66,26 +69,40 @@ class DatabaseUsersRepository implements UsersRepository
return self::makeUserFromDbUser($newUser);
}
public function fillBasicUserAttrs(User $user, \App\User $dbUser, bool $includeDoorcode = true): \App\User
/**
* @param \Source\Entities\User $user
* @param \App\User $dbUser
* @return \App\User
*/
protected function fillBasicUserAttrs(User $user, \App\User $dbUser): \App\User
{
$dbUser->first_name = $user->getFirstName();
$dbUser->last_name = $user->getLastName();
$dbUser->display_name = $user->getDisplayName();
$dbUser->emplid = $user->getEmplid();
$dbUser->email = $user->getEmail();
$dbUser->password = bcrypt($user->getPassword());
$dbUser->expires_at = $user->getExpiresAt();
// If the password exists and is the same as provided, don't change
// Else regenerate
if (!isset($dbUser->password) || (isset($dbUser->password) && $dbUser->password !== $user->getPassword())) {
$dbUser->password = bcrypt($user->getPassword());
}
// If the doorcode exists and is the same as provided, don't change
// Else regenerate
if (!isset($dbUser->doorcode) || (isset($dbUser->doorcode) && $dbUser->doorcode !== $user->getDoorcode())) {
$dbUser->doorcode = $this->secureDoorcode($user->getDoorcode());
$dbUser->doorcode = self::secureDoorcode($user->getDoorcode());
}
return $dbUser;
}
protected function secureDoorcode(?string $doorcode): ?string
/**
* @param string|null $doorcode
* @return string|null
*/
public static function secureDoorcode(?string $doorcode): ?string
{
if (!$doorcode) {
return null;
......@@ -105,7 +122,7 @@ class DatabaseUsersRepository implements UsersRepository
*/
public function update(string $userId, User $user): ?User
{
$dbUser = \App\User::find($userId);
$dbUser = \App\User::find((int)$userId);
if (!$dbUser) {
return null;
......@@ -123,7 +140,7 @@ class DatabaseUsersRepository implements UsersRepository
*/
public function delete(string $userId): bool
{
return \App\User::destroy($userId);
return \App\User::destroy((int)$userId);
}
/**
......@@ -131,7 +148,7 @@ class DatabaseUsersRepository implements UsersRepository
*/
public function exists(string $userId): bool
{
return \App\User::find($userId) !== null;
return $this->get($userId) !== null;
}
/**
......@@ -157,7 +174,7 @@ class DatabaseUsersRepository implements UsersRepository
*/
public function findByDoorcode(string $doorcode): ?User
{
$doorcodeSearch = $this->secureDoorcode($doorcode);
$doorcodeSearch = self::secureDoorcode($doorcode);
$user = \App\User::where('doorcode', $doorcodeSearch)->first();
......@@ -176,6 +193,10 @@ class DatabaseUsersRepository implements UsersRepository
{
$user = \App\User::where('email', strtolower($email))->first();
if (!$user) {
return null;
}
return self::makeUserFromDbUser($user);
}
}
<?php
namespace Tests\Database;
use Source\Entities\Door;
use Tests\DatabaseTestCase;
use Source\Gateways\Doors\DatabaseDoorsRepository;
class DoorDatabaseTest extends DatabaseTestCase
{
protected DatabaseDoorsRepository $doors;
public function setUp(): void
{
parent::setUp();
$this->doors = new DatabaseDoorsRepository();
}
/**
* @test
*/
public function it_creates_and_finds_doors(): void
{
$door = $this->doors->create(new Door(0, 'loc', 'name', 'token'));
$this->assertEquals($door, $this->doors->getByToken('token'));
$this->assertNull($this->doors->getByToken('i am autistic'));
}
}
<?php
namespace Tests\Database;
use Source\Entities\Group;
use Tests\DatabaseTestCase;
use Source\Gateways\Groups\DatabaseGroupsRepository;
class GroupDatabaseTest extends DatabaseTestCase
{
/**
* @var \Source\Gateways\Groups\DatabaseGroupsRepository
*/
protected DatabaseGroupsRepository $groups;
public function setUp(): void
{
parent::setUp();
$this->groups = new DatabaseGroupsRepository();
}
/**
* @test
*/
public function it_gets_all_groups(): void
{
$all = $this->groups->all();
$this->assertEquals([], $all);
$this->groups->create(new Group(0, '', ''));
$this->groups->create(new Group(0, '', ''));
$all = $this->groups->all();
$this->assertCount(2, $all);
}
/**
* @test
*/
public function it_gets_a_group(): void
{
$group = $this->groups->get(10);
$this->assertNull($group);
$group = $this->groups->create(new Group(0, '', ''));
$this->assertEquals($group, $this->groups->get(1));
}
/**
* @test
*/
public function it_cannot_get_non_existent_user(): void
{
$this->assertNull($this->groups->get('asdf'));
}
/**
* @test
*/
public function it_creates_a_group(): void
{
$group = $this->groups->create(new Group(0, '', ''));
$this->assertEquals($group, $this->groups->get(1));
}
/**
* @test
*/
public function it_deletes_a_group(): void
{
$this->groups->create(new Group(0, '', ''));
$this->assertTrue($this->groups->delete(1));
$this->assertFalse($this->groups->exists(1));
$this->assertFalse($this->groups->delete(2));
$this->assertFalse($this->groups->delete('asdf'));
}
/**
* @test
*/
public function it_checks_existence_of_groups(): void
{
$this->groups->create(new Group(0, '', ''));
$this->assertTrue($this->groups->exists(1));
$this->assertFalse($this->groups->exists(2));
$this->assertFalse($this->groups->exists('ree'));
}
/**
* @test
*/
public function it_updates_a_group(): void
{
$this->groups->create(new Group(0, 'title', 'description'));
$this->groups->update(1, new Group(0, 'new title', 'new desc'));
$group = $this->groups->get(1);
$this->assertEquals('new title', $group->getTitle());
$this->assertEquals('new desc', $group->getDescription());
}
/**
* @test
*/
public function it_cannot_update_non_existent_group(): void
{
$this->assertNull($this->groups->update(1, new Group(0, 'new title', 'new desc')));
}
}
<?php
namespace Tests\Database;
use Source\Entities\User;
use Source\Entities\Group;
use Tests\DatabaseTestCase;
use Source\Exceptions\EntityNotFoundException;
use Source\Gateways\Users\DatabaseUsersRepository;
use Source\Gateways\Groups\DatabaseGroupsRepository;
use Source\Gateways\GroupUser\DatabaseGroupUserRepository;
class GroupUserDatabaseTest extends DatabaseTestCase
{
/**
* @var \Source\Gateways\Users\DatabaseUsersRepository
*/
protected DatabaseUsersRepository $users;
/**
* @var \Source\Gateways\Groups\DatabaseGroupsRepository
*/
protected DatabaseGroupsRepository $groups;
/**
* @var \Source\Gateways\GroupUser\DatabaseGroupUserRepository
*/
protected DatabaseGroupUserRepository $groupUsers;
public function setUp(): void
{
parent::setUp();
$this->users = new DatabaseUsersRepository();
$this->groups = new DatabaseGroupsRepository();
$this->groupUsers = new DatabaseGroupUserRepository();
$this->users->create(new User(0, '', '', '', null, '', null, null));
$this->groups->create(new Group(0, '', ''));
}
/**
* @test
* @throws \Source\Exceptions\EntityNotFoundException
*/
public function it_cannot_get_groups_for_non_existent_user(): void
{
$this->expectException(EntityNotFoundException::class);
$this->groupUsers->getGroupsForUser('ree');
}
/**
* @test
* @throws \Source\Exceptions\EntityNotFoundException
*/
public function it_cannot_get_users_for_non_existent_group(): void
{
$this->expectException(EntityNotFoundException::class);
$this->groupUsers->getUsersForGroup('ree');
}
/**
* @test
* @throws \Source\Exceptions\EntityNotFoundException
*/
public function it_cannot_add_user_to_non_existent_group(): void
{
$this->expectException(EntityNotFoundException::class);
$this->groupUsers->addUserToGroup('1', 'ree');
}
/**
* @test
* @throws \Source\Exceptions\EntityNotFoundException
*/
public function it_cannot_add_group_to_non_existent_user(): void
{
$this->expectException(EntityNotFoundException::class);
$this->groupUsers->addUserToGroup('re', '1');
}
/**
* @test
* @throws \Source\Exceptions\EntityNotFoundException
*/
public function it_cannot_remove_user_to_non_existent_group(): void
{
$this->expectException(EntityNotFoundException::class);
$this->groupUsers->removeUserFromGroup('1', 'ree');
}