From d1b566c32942d47fb2559d34610ff18675c611ae Mon Sep 17 00:00:00 2001 From: dakriy Date: Tue, 16 Jun 2020 14:15:57 -0700 Subject: [PATCH 01/38] add tests for doors index --- .../Feature/Api/Doors/DoorsGetApiTest.php | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/backend/tests/Feature/Api/Doors/DoorsGetApiTest.php diff --git a/src/backend/tests/Feature/Api/Doors/DoorsGetApiTest.php b/src/backend/tests/Feature/Api/Doors/DoorsGetApiTest.php new file mode 100644 index 00000000..1af2348a --- /dev/null +++ b/src/backend/tests/Feature/Api/Doors/DoorsGetApiTest.php @@ -0,0 +1,62 @@ +authenticate(); + } + + protected function handleTest(string $query = ''): void + { + $this->response = $this->getJson('api/doors?api_token=' . $this->authToken . '&' . $query); + } + + /** + * @test + * @throws \Source\Exceptions\EntityExistsException + */ + public function it_paginates_all_doors(): void + { + for ($i = 0; $i < 100; $i++) { + $this->doorsRepository->create(new Door($i, '', '', new HashedSearchable(''))); + } + + $this->handleTest(); + $this->response->assertJson(['total' => 100]); + } + + /** + * @test + * @throws \Source\Exceptions\EntityExistsException + */ + public function it_filters_doors(): void + { + $this->doorsRepository->create(new Door(1, 'location', 'name', new HashedSearchable(''))); + $this->doorsRepository->create(new Door(2, 'hue hue', 'nan', new HashedSearchable(''))); + + $this->handleTest('query=location'); + + $this->response->assertJsonCount(1, 'data'); + } +} -- GitLab From 37ba505a36f1e25e9629dfcc4775f8c4a2736707 Mon Sep 17 00:00:00 2001 From: dakriy Date: Tue, 16 Jun 2020 14:17:03 -0700 Subject: [PATCH 02/38] let query be nullable --- src/backend/app/Http/Controllers/DoorsController.php | 2 +- src/backend/tests/Feature/Api/Doors/DoorsGetApiTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backend/app/Http/Controllers/DoorsController.php b/src/backend/app/Http/Controllers/DoorsController.php index 985f38f4..f8830f6e 100644 --- a/src/backend/app/Http/Controllers/DoorsController.php +++ b/src/backend/app/Http/Controllers/DoorsController.php @@ -51,7 +51,7 @@ class DoorsController extends ApiController $this->authorizer->protect(Permissions::MANAGE_DOORS); $this->validate($this->request, [ - 'query' => 'string', + 'query' => 'nullable|string', ]); $presenter = new GetAllDoorsAPIPresenter(); diff --git a/src/backend/tests/Feature/Api/Doors/DoorsGetApiTest.php b/src/backend/tests/Feature/Api/Doors/DoorsGetApiTest.php index 1af2348a..0f2305b4 100644 --- a/src/backend/tests/Feature/Api/Doors/DoorsGetApiTest.php +++ b/src/backend/tests/Feature/Api/Doors/DoorsGetApiTest.php @@ -29,7 +29,7 @@ class DoorsGetApiTest extends AuthenticatesWithApplicationTestCase protected function handleTest(string $query = ''): void { - $this->response = $this->getJson('api/doors?api_token=' . $this->authToken . '&' . $query); + $this->response = $this->getJson('api/doors?api_token=' . $this->authToken . '&query=' . $query); } /** @@ -55,7 +55,7 @@ class DoorsGetApiTest extends AuthenticatesWithApplicationTestCase $this->doorsRepository->create(new Door(1, 'location', 'name', new HashedSearchable(''))); $this->doorsRepository->create(new Door(2, 'hue hue', 'nan', new HashedSearchable(''))); - $this->handleTest('query=location'); + $this->handleTest('location'); $this->response->assertJsonCount(1, 'data'); } -- GitLab From c764e757f5a326e7083ee1ecccd8b17b1e6109b1 Mon Sep 17 00:00:00 2001 From: dakriy Date: Tue, 16 Jun 2020 14:22:21 -0700 Subject: [PATCH 03/38] Add tests for getting a door --- .../Feature/Api/Doors/DoorGetApiTest.php | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/backend/tests/Feature/Api/Doors/DoorGetApiTest.php diff --git a/src/backend/tests/Feature/Api/Doors/DoorGetApiTest.php b/src/backend/tests/Feature/Api/Doors/DoorGetApiTest.php new file mode 100644 index 00000000..848373a5 --- /dev/null +++ b/src/backend/tests/Feature/Api/Doors/DoorGetApiTest.php @@ -0,0 +1,62 @@ +authenticate(); + } + + protected function handleTest(string $id): void + { + $this->response = $this->getJson('api/doors/' . $id . '?api_token=' . $this->authToken); + } + + /** + * @test + * @throws \Source\Exceptions\EntityExistsException + */ + public function it_gets_a_door(): void + { + $this->doorsRepository->create(new Door(0, '', '', new HashedSearchable(''))); + + $this->handleTest('0'); + + $this->response->assertJson(['door' => [ + 'id' => 0, + 'location' => '', + 'name' => '', + ]]); + } + + /** + * @test + */ + public function it_handles_non_existent_doors(): void + { + $this->handleTest('asdf'); + + $this->response->assertStatus(404); + } +} -- GitLab From 753ca983aede493e94f05c1279486915e884834a Mon Sep 17 00:00:00 2001 From: dakriy Date: Tue, 16 Jun 2020 14:34:32 -0700 Subject: [PATCH 04/38] Add test for door create --- .../Doors/DatabaseDoorsRepository.php | 2 +- .../src/Gateways/Doors/DoorsRepository.php | 2 +- .../Doors/InMemoryDoorsRepository.php | 2 +- .../UseCases/Doors/CreateDoor/CreateDoor.php | 4 +- .../Doors/CreateDoor/CreateDoorUseCase.php | 1 - .../Feature/Api/Doors/DoorsCreateApiTest.php | 60 +++++++++++++++++++ 6 files changed, 64 insertions(+), 7 deletions(-) create mode 100644 src/backend/tests/Feature/Api/Doors/DoorsCreateApiTest.php diff --git a/src/backend/src/Gateways/Doors/DatabaseDoorsRepository.php b/src/backend/src/Gateways/Doors/DatabaseDoorsRepository.php index 8c63939a..2cac0666 100644 --- a/src/backend/src/Gateways/Doors/DatabaseDoorsRepository.php +++ b/src/backend/src/Gateways/Doors/DatabaseDoorsRepository.php @@ -20,7 +20,7 @@ class DatabaseDoorsRepository implements DoorsRepository /** * @inheritDoc */ - public function create(Door $door): ?Door + public function create(Door $door): Door { $dbDoor = new \App\Door(); diff --git a/src/backend/src/Gateways/Doors/DoorsRepository.php b/src/backend/src/Gateways/Doors/DoorsRepository.php index c1e60cb7..3518ae4f 100644 --- a/src/backend/src/Gateways/Doors/DoorsRepository.php +++ b/src/backend/src/Gateways/Doors/DoorsRepository.php @@ -16,7 +16,7 @@ interface DoorsRepository * @return \Source\Entities\Door|null * @throws \Source\Exceptions\EntityExistsException */ - public function create(Door $door): ?Door; + public function create(Door $door): Door; /** * Queries doors, if query is empty or null it gets all doors. diff --git a/src/backend/src/Gateways/Doors/InMemoryDoorsRepository.php b/src/backend/src/Gateways/Doors/InMemoryDoorsRepository.php index 79339e54..10bfe560 100644 --- a/src/backend/src/Gateways/Doors/InMemoryDoorsRepository.php +++ b/src/backend/src/Gateways/Doors/InMemoryDoorsRepository.php @@ -16,7 +16,7 @@ class InMemoryDoorsRepository implements DoorsRepository /** * @inheritDoc */ - public function create(Door $door): ?Door + public function create(Door $door): Door { if ($this->findByName($door->getName())) { throw new EntityExistsException(); diff --git a/src/backend/src/UseCases/Doors/CreateDoor/CreateDoor.php b/src/backend/src/UseCases/Doors/CreateDoor/CreateDoor.php index 60920f61..cc08ae75 100644 --- a/src/backend/src/UseCases/Doors/CreateDoor/CreateDoor.php +++ b/src/backend/src/UseCases/Doors/CreateDoor/CreateDoor.php @@ -48,9 +48,7 @@ class CreateDoor implements CreateDoorUseCase HashedSearchable::hash($this->salt, $token) ); - if (!($door = $this->doors->create($door))) { - throw new EntityExistsException(); - } + $door = $this->doors->create($door); $response = new ResponseModel($door, $token); diff --git a/src/backend/src/UseCases/Doors/CreateDoor/CreateDoorUseCase.php b/src/backend/src/UseCases/Doors/CreateDoor/CreateDoorUseCase.php index 6bcbafcd..34998f59 100644 --- a/src/backend/src/UseCases/Doors/CreateDoor/CreateDoorUseCase.php +++ b/src/backend/src/UseCases/Doors/CreateDoor/CreateDoorUseCase.php @@ -11,7 +11,6 @@ interface CreateDoorUseCase * Required attributes: * location * name - * salt (For hashing api key, application key is a good choice) * * @param array $attributes * @param Presenter $presenter diff --git a/src/backend/tests/Feature/Api/Doors/DoorsCreateApiTest.php b/src/backend/tests/Feature/Api/Doors/DoorsCreateApiTest.php new file mode 100644 index 00000000..dfc9633f --- /dev/null +++ b/src/backend/tests/Feature/Api/Doors/DoorsCreateApiTest.php @@ -0,0 +1,60 @@ +authenticate(); + } + + /** + * @param array $data + */ + protected function handleTest(array $data): void + { + $this->response = $this->postJson( + 'api/doors', + array_merge( + ['api_token' => $this->authToken], + $data + ) + ); + } + + /** + * @test + */ + public function it_creates_a_door(): void + { + $this->handleTest(['name' => 'new door', 'location' => 'your moms house']); + + $this->response->assertStatus(200); + $door = $this->doorsRepository->findByName('new door'); + $this->assertNotNull($door); + $this->response->assertJson(['door' => ['name' => 'new door', 'location' => 'your moms house']]); + $this->assertEquals( + HashedSearchable::hash(config('app.key'), $this->response->json('door_token')), + $door->getToken() + ); + } +} -- GitLab From c4a696e2ac8162546e866abee06fbce43b77644e Mon Sep 17 00:00:00 2001 From: dakriy Date: Tue, 16 Jun 2020 14:53:20 -0700 Subject: [PATCH 05/38] update doors tests --- .../Doors/DatabaseDoorsRepository.php | 5 +- .../src/Gateways/Doors/DoorsRepository.php | 3 +- .../Doors/InMemoryDoorsRepository.php | 5 +- .../GenerateDoorToken/GenerateDoorToken.php | 2 - .../Doors/UpdateDoor/ResponseModel.php | 12 ++-- .../UseCases/Doors/UpdateDoor/UpdateDoor.php | 8 +-- .../Feature/Api/Doors/DoorsUpdateApiTest.php | 69 +++++++++++++++++++ .../Feature/Api/Groups/UpdateGroupApiTest.php | 12 +++- 8 files changed, 93 insertions(+), 23 deletions(-) create mode 100644 src/backend/tests/Feature/Api/Doors/DoorsUpdateApiTest.php diff --git a/src/backend/src/Gateways/Doors/DatabaseDoorsRepository.php b/src/backend/src/Gateways/Doors/DatabaseDoorsRepository.php index 2cac0666..6cadb7e6 100644 --- a/src/backend/src/Gateways/Doors/DatabaseDoorsRepository.php +++ b/src/backend/src/Gateways/Doors/DatabaseDoorsRepository.php @@ -10,6 +10,7 @@ use Illuminate\Support\Facades\Log; use Source\Entities\HashedSearchable; use Illuminate\Database\QueryException; use Source\Exceptions\EntityExistsException; +use Source\Exceptions\EntityNotFoundException; class DatabaseDoorsRepository implements DoorsRepository { @@ -154,13 +155,13 @@ class DatabaseDoorsRepository implements DoorsRepository /** * @inheritDoc */ - public function update(string $doorId, Door $door): ?Door + public function update(string $doorId, Door $door): Door { /** @var \App\Door|null $dbDoor */ $dbDoor = \App\Door::query()->find($this->castToInt($doorId)); if (!$dbDoor) { - return null; + throw new EntityNotFoundException('Could not update door. Door not found.'); } if ($dbDoor->getAttribute('name') !== $door->getName() && $this->findByName($door->getName())) { diff --git a/src/backend/src/Gateways/Doors/DoorsRepository.php b/src/backend/src/Gateways/Doors/DoorsRepository.php index 3518ae4f..0b17eba1 100644 --- a/src/backend/src/Gateways/Doors/DoorsRepository.php +++ b/src/backend/src/Gateways/Doors/DoorsRepository.php @@ -60,8 +60,9 @@ interface DoorsRepository * @param \Source\Entities\Door $door * @return \Source\Entities\Door|null * @throws \Source\Exceptions\EntityExistsException + * @throws \Source\Exceptions\EntityNotFoundException */ - public function update(string $doorId, Door $door): ?Door; + public function update(string $doorId, Door $door): Door; /** * Deletes a door diff --git a/src/backend/src/Gateways/Doors/InMemoryDoorsRepository.php b/src/backend/src/Gateways/Doors/InMemoryDoorsRepository.php index 10bfe560..6ee26deb 100644 --- a/src/backend/src/Gateways/Doors/InMemoryDoorsRepository.php +++ b/src/backend/src/Gateways/Doors/InMemoryDoorsRepository.php @@ -7,6 +7,7 @@ use Carbon\Carbon; use Source\Entities\Door; use Source\Entities\HashedSearchable; use Source\Exceptions\EntityExistsException; +use Source\Exceptions\EntityNotFoundException; class InMemoryDoorsRepository implements DoorsRepository { @@ -103,7 +104,7 @@ class InMemoryDoorsRepository implements DoorsRepository /** * @inheritDoc */ - public function update(string $doorId, Door $door): ?Door + public function update(string $doorId, Door $door): Door { foreach ($this->doors as &$doorBase) { if ($doorBase->hasIdOf($doorId)) { @@ -115,7 +116,7 @@ class InMemoryDoorsRepository implements DoorsRepository } } - return null; + throw new EntityNotFoundException('Door not found.'); } /** diff --git a/src/backend/src/UseCases/Doors/GenerateDoorToken/GenerateDoorToken.php b/src/backend/src/UseCases/Doors/GenerateDoorToken/GenerateDoorToken.php index d714bede..fd7f96d6 100644 --- a/src/backend/src/UseCases/Doors/GenerateDoorToken/GenerateDoorToken.php +++ b/src/backend/src/UseCases/Doors/GenerateDoorToken/GenerateDoorToken.php @@ -53,9 +53,7 @@ class GenerateDoorToken implements GenerateDoorTokenUseCase ); $returnedDoor = $this->doors->update($doorId, $door); - $response = new ResponseModel($returnedDoor, $token); - $presenter->present($response); } } diff --git a/src/backend/src/UseCases/Doors/UpdateDoor/ResponseModel.php b/src/backend/src/UseCases/Doors/UpdateDoor/ResponseModel.php index c1e60b57..8c2b6ad3 100644 --- a/src/backend/src/UseCases/Doors/UpdateDoor/ResponseModel.php +++ b/src/backend/src/UseCases/Doors/UpdateDoor/ResponseModel.php @@ -7,9 +7,9 @@ use Source\Entities\Door; class ResponseModel { /** - * @var \Source\Entities\Door|null + * @var \Source\Entities\Door */ - protected ?Door $door = null; + protected Door $door; /** * @var string @@ -17,17 +17,17 @@ class ResponseModel protected string $message = ''; /** - * @param \Source\Entities\Door|null $door + * @param \Source\Entities\Door $door */ - public function __construct(?Door $door) + public function __construct(Door $door) { $this->door = $door; } /** - * @return \Source\Entities\Door|null + * @return \Source\Entities\Door */ - public function getDoor(): ?Door + public function getDoor(): Door { return $this->door; } diff --git a/src/backend/src/UseCases/Doors/UpdateDoor/UpdateDoor.php b/src/backend/src/UseCases/Doors/UpdateDoor/UpdateDoor.php index 028057ce..b2c9aaac 100644 --- a/src/backend/src/UseCases/Doors/UpdateDoor/UpdateDoor.php +++ b/src/backend/src/UseCases/Doors/UpdateDoor/UpdateDoor.php @@ -44,13 +44,7 @@ class UpdateDoor implements UpdateDoorUseCase $returnedDoor = $this->doors->update($door->getId(), $newDoor); $response = new ResponseModel($returnedDoor); - - if (!$returnedDoor) { - $response->setMessage('Unable to update door.'); - } else { - $response->setMessage('Successfully updated door.'); - } - + $response->setMessage('Successfully updated door.'); $presenter->present($response); } } diff --git a/src/backend/tests/Feature/Api/Doors/DoorsUpdateApiTest.php b/src/backend/tests/Feature/Api/Doors/DoorsUpdateApiTest.php new file mode 100644 index 00000000..f4626aa9 --- /dev/null +++ b/src/backend/tests/Feature/Api/Doors/DoorsUpdateApiTest.php @@ -0,0 +1,69 @@ +authenticate(); + } + + /** + * @param string $doorId + * @param array $data + */ + protected function handleTest(string $doorId, array $data): void + { + $this->response = $this->patchJson( + 'api/doors/' . $doorId, + array_merge(['api_token' => $this->authToken], $data) + ); + } + + /** + * @test + * @throws \Source\Exceptions\EntityExistsException + */ + public function it_updates_a_door(): void + { + $door = new Door(self::VALID_DOOR_ID, 'loc', 'name', new HashedSearchable('')); + + $this->doorsRepository->create($door); + + $this->handleTest(self::VALID_DOOR_ID, ['location' => 'new', 'name' => 'also new']); + $this->response->assertStatus(200); + $d = $this->doorsRepository->findByName('also new'); + $this->assertNotNull($d); + $this->assertEquals('also new', $d->getName()); + $this->assertEquals('new', $d->getLocation()); + $this->response->assertJson(['door' => ['name' => 'also new', 'location' => 'new']]); + } + + /** + * @test + */ + public function it_cannot_update_invalid_door(): void + { + $this->handleTest('asdfasd', []); + + $this->response->assertStatus(404); + } +} diff --git a/src/backend/tests/Feature/Api/Groups/UpdateGroupApiTest.php b/src/backend/tests/Feature/Api/Groups/UpdateGroupApiTest.php index 4f337763..5a946b0e 100644 --- a/src/backend/tests/Feature/Api/Groups/UpdateGroupApiTest.php +++ b/src/backend/tests/Feature/Api/Groups/UpdateGroupApiTest.php @@ -13,7 +13,7 @@ use Tests\Feature\AuthenticatesWithApplicationTestCase; class UpdateGroupApiTest extends AuthenticatesWithApplicationTestCase { /** - * @var \Illuminate\Foundation\Testing\TestResponse + * @var \Illuminate\Testing\TestResponse */ protected TestResponse $response; @@ -53,6 +53,7 @@ class UpdateGroupApiTest extends AuthenticatesWithApplicationTestCase /** * @test + * @throws \Source\Exceptions\EntityExistsException * @throws \Source\Exceptions\EntityNotFoundException */ public function it_protects_the_route(): void @@ -91,6 +92,8 @@ class UpdateGroupApiTest extends AuthenticatesWithApplicationTestCase * @param array $message * @dataProvider invalidGroupProvider * @throws EntityNotFoundException + * @throws \Source\Exceptions\EntityExistsException + * @throws \Source\Exceptions\EntityNotFoundException */ public function it_tests_the_validation_rules(array $data, array $message): void { @@ -101,7 +104,8 @@ class UpdateGroupApiTest extends AuthenticatesWithApplicationTestCase /** * @test - * @throws EntityNotFoundException + * @throws \Source\Exceptions\EntityExistsException + * @throws \Source\Exceptions\EntityNotFoundException */ public function it_updates_a_group(): void { @@ -125,7 +129,8 @@ class UpdateGroupApiTest extends AuthenticatesWithApplicationTestCase /** * @test - * @throws EntityNotFoundException + * @throws \Source\Exceptions\EntityExistsException + * @throws \Source\Exceptions\EntityNotFoundException */ public function it_cannot_update_non_existent_group(): void { @@ -140,6 +145,7 @@ class UpdateGroupApiTest extends AuthenticatesWithApplicationTestCase /** * @test + * @throws \Source\Exceptions\EntityExistsException * @throws \Source\Exceptions\EntityNotFoundException */ public function it_presents_error(): void -- GitLab From a8bfb699eed4098e5cbc72f0a286c011931dc6f0 Mon Sep 17 00:00:00 2001 From: dakriy Date: Tue, 16 Jun 2020 15:02:45 -0700 Subject: [PATCH 06/38] Add tests for door delete --- .../Doors/DatabaseDoorsRepository.php | 2 +- .../src/Gateways/Doors/DoorsRepository.php | 4 +- .../Doors/InMemoryDoorsRepository.php | 8 ++- .../UseCases/Doors/DeleteDoor/DeleteDoor.php | 10 +--- .../tests/Database/DoorDatabaseTest.php | 4 +- .../Feature/Api/Doors/DoorsDeleteApiTest.php | 60 +++++++++++++++++++ 6 files changed, 73 insertions(+), 15 deletions(-) create mode 100644 src/backend/tests/Feature/Api/Doors/DoorsDeleteApiTest.php diff --git a/src/backend/src/Gateways/Doors/DatabaseDoorsRepository.php b/src/backend/src/Gateways/Doors/DatabaseDoorsRepository.php index 6cadb7e6..e1c32b9a 100644 --- a/src/backend/src/Gateways/Doors/DatabaseDoorsRepository.php +++ b/src/backend/src/Gateways/Doors/DatabaseDoorsRepository.php @@ -193,7 +193,7 @@ class DatabaseDoorsRepository implements DoorsRepository /** * @inheritDoc */ - public function delete(string $doorId): bool + public function delete(string $doorId): int { return \App\Door::destroy($this->castToInt($doorId)); } diff --git a/src/backend/src/Gateways/Doors/DoorsRepository.php b/src/backend/src/Gateways/Doors/DoorsRepository.php index 0b17eba1..49b366c1 100644 --- a/src/backend/src/Gateways/Doors/DoorsRepository.php +++ b/src/backend/src/Gateways/Doors/DoorsRepository.php @@ -68,9 +68,9 @@ interface DoorsRepository * Deletes a door * * @param string $doorId - * @return bool + * @return int number of doors deleted */ - public function delete(string $doorId): bool; + public function delete(string $doorId): int; /** * Checks a door for existence. diff --git a/src/backend/src/Gateways/Doors/InMemoryDoorsRepository.php b/src/backend/src/Gateways/Doors/InMemoryDoorsRepository.php index 6ee26deb..6582372e 100644 --- a/src/backend/src/Gateways/Doors/InMemoryDoorsRepository.php +++ b/src/backend/src/Gateways/Doors/InMemoryDoorsRepository.php @@ -122,13 +122,15 @@ class InMemoryDoorsRepository implements DoorsRepository /** * @inheritDoc */ - public function delete(string $doorId): bool + public function delete(string $doorId): int { - $this->doors = array_values(array_filter($this->doors, static function (Door $door) use ($doorId) { + $doors = 0; + $this->doors = array_values(array_filter($this->doors, static function (Door $door) use ($doorId, &$doors) { + $doors++; return !$door->hasIdOf($doorId); })); - return true; + return $doors; } /** diff --git a/src/backend/src/UseCases/Doors/DeleteDoor/DeleteDoor.php b/src/backend/src/UseCases/Doors/DeleteDoor/DeleteDoor.php index ac0bea78..098e7ef2 100644 --- a/src/backend/src/UseCases/Doors/DeleteDoor/DeleteDoor.php +++ b/src/backend/src/UseCases/Doors/DeleteDoor/DeleteDoor.php @@ -25,14 +25,10 @@ class DeleteDoor implements DeleteDoorUseCase */ public function delete(string $doorId, Presenter $presenter) { - if (!($door = $this->doors->get($doorId))) { - throw new EntityNotFoundException(); - } - - if (!$this->doors->delete($door->getId())) { - $text = 'Unable to delete door'; - } else { + if ($this->doors->delete($doorId) > 0) { $text = 'Door deleted.'; + } else { + throw new EntityNotFoundException(); } $response = new ResponseModel($text); diff --git a/src/backend/tests/Database/DoorDatabaseTest.php b/src/backend/tests/Database/DoorDatabaseTest.php index b33de8b1..34c54ae0 100644 --- a/src/backend/tests/Database/DoorDatabaseTest.php +++ b/src/backend/tests/Database/DoorDatabaseTest.php @@ -50,9 +50,9 @@ class DoorDatabaseTest extends DatabaseTestCase public function it_deletes_doors(): void { $d = $this->doors->create(new Door(0, 'loc', 'name', new HashedSearchable('token'))); - $this->assertFalse($this->doors->delete('ah idk if im gonna finish this project. Im sorry')); + $this->assertEquals(0, $this->doors->delete('ah idk if im gonna finish this project. Im sorry')); $this->assertCount(1, $this->doors->search()); - $this->assertTrue($this->doors->delete($d->getId())); + $this->assertEquals(1, $this->doors->delete($d->getId())); $this->assertCount(0, $this->doors->search()); } diff --git a/src/backend/tests/Feature/Api/Doors/DoorsDeleteApiTest.php b/src/backend/tests/Feature/Api/Doors/DoorsDeleteApiTest.php new file mode 100644 index 00000000..b8c5b62b --- /dev/null +++ b/src/backend/tests/Feature/Api/Doors/DoorsDeleteApiTest.php @@ -0,0 +1,60 @@ +authenticate(); + } + + protected function handleTest(string $id): void + { + $this->response = $this->deleteJson('api/doors/' . $id . '?api_token=' . $this->authToken); + } + + /** + * @test + */ + public function it_cannot_delete_non_existent_door(): void + { + $this->handleTest('asdf'); + + $this->response->assertStatus(404); + } + + /** + * @test + * @throws \Source\Exceptions\EntityExistsException + */ + public function it_can_delete_a_door(): void + { + $this->doorsRepository->create(new Door(0, '', '', new HashedSearchable(''))); + + $this->handleTest('0'); + + $this->response->assertStatus(200); + $this->response->assertJson(['message' => 'Door deleted.']); + $this->assertCount(0, $this->doorsRepository->search()); + } +} -- GitLab From b2f8075e8e477d80b3974fb819a8998c1553d90e Mon Sep 17 00:00:00 2001 From: dakriy Date: Tue, 16 Jun 2020 15:14:42 -0700 Subject: [PATCH 07/38] door token regeneration tests, also remove documentation files from cov as they cover themselves when generating documentation. --- src/backend/phpunit.xml | 1 + .../src/Gateways/Doors/DoorsRepository.php | 2 +- .../Api/Doors/DoorsTokenRegenerateApiTest.php | 58 +++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/backend/tests/Feature/Api/Doors/DoorsTokenRegenerateApiTest.php diff --git a/src/backend/phpunit.xml b/src/backend/phpunit.xml index 85c670a3..9f457c90 100644 --- a/src/backend/phpunit.xml +++ b/src/backend/phpunit.xml @@ -31,6 +31,7 @@ ./app/Console ./src ./src + ./app/Documentation/Strategies diff --git a/src/backend/src/Gateways/Doors/DoorsRepository.php b/src/backend/src/Gateways/Doors/DoorsRepository.php index 49b366c1..cf1851ac 100644 --- a/src/backend/src/Gateways/Doors/DoorsRepository.php +++ b/src/backend/src/Gateways/Doors/DoorsRepository.php @@ -58,7 +58,7 @@ interface DoorsRepository /** * @param string $doorId * @param \Source\Entities\Door $door - * @return \Source\Entities\Door|null + * @return \Source\Entities\Door * @throws \Source\Exceptions\EntityExistsException * @throws \Source\Exceptions\EntityNotFoundException */ diff --git a/src/backend/tests/Feature/Api/Doors/DoorsTokenRegenerateApiTest.php b/src/backend/tests/Feature/Api/Doors/DoorsTokenRegenerateApiTest.php new file mode 100644 index 00000000..8a7ac2f0 --- /dev/null +++ b/src/backend/tests/Feature/Api/Doors/DoorsTokenRegenerateApiTest.php @@ -0,0 +1,58 @@ +authenticate(); + } + + protected function handleTest(string $id): void + { + $this->response = $this->postJson('api/doors/' . $id . '/regenerate-token', ['api_token' => $this->authToken]); + } + + /** + * @test + */ + public function it_cannot_regenerate_tokens_of_nonexistent_doors(): void + { + $this->handleTest('lol'); + + $this->response->assertStatus(404); + } + + /** + * @test + * @throws \Source\Exceptions\EntityExistsException + */ + public function it_regenerates_door_tokens(): void + { + $this->doorsRepository->create(new Door(1, 'loc', 'yey', new HashedSearchable(''))); + $this->handleTest('1'); + $this->response->assertStatus(200); + $door = $this->doorsRepository->get(1); + $this->assertEquals( + HashedSearchable::hash(config('app.key'), $this->response->json('door_token')), + $door->getToken() + ); + } +} -- GitLab From 68032fe5b82e07042bed41bf4da8255daceec009 Mon Sep 17 00:00:00 2001 From: dakriy Date: Tue, 16 Jun 2020 15:17:40 -0700 Subject: [PATCH 08/38] fix code styles --- src/backend/src/UseCases/Doors/CreateDoor/CreateDoor.php | 1 - src/backend/tests/Feature/Api/Doors/DoorGetApiTest.php | 1 - src/backend/tests/Feature/Api/Doors/DoorsCreateApiTest.php | 1 - src/backend/tests/Feature/Api/Doors/DoorsDeleteApiTest.php | 1 - .../tests/Feature/Api/Doors/DoorsTokenRegenerateApiTest.php | 1 - 5 files changed, 5 deletions(-) diff --git a/src/backend/src/UseCases/Doors/CreateDoor/CreateDoor.php b/src/backend/src/UseCases/Doors/CreateDoor/CreateDoor.php index cc08ae75..6e710925 100644 --- a/src/backend/src/UseCases/Doors/CreateDoor/CreateDoor.php +++ b/src/backend/src/UseCases/Doors/CreateDoor/CreateDoor.php @@ -5,7 +5,6 @@ namespace Source\UseCases\Doors\CreateDoor; use Source\Entities\Door; use Source\Entities\HashedSearchable; use Source\Gateways\Doors\DoorsRepository; -use Source\Exceptions\EntityExistsException; use Source\Gateways\Tokens\TokensRepository; class CreateDoor implements CreateDoorUseCase diff --git a/src/backend/tests/Feature/Api/Doors/DoorGetApiTest.php b/src/backend/tests/Feature/Api/Doors/DoorGetApiTest.php index 848373a5..621be4a6 100644 --- a/src/backend/tests/Feature/Api/Doors/DoorGetApiTest.php +++ b/src/backend/tests/Feature/Api/Doors/DoorGetApiTest.php @@ -3,7 +3,6 @@ namespace Tests\Feature\Api\Doors; - use Source\Entities\Door; use Illuminate\Testing\TestResponse; use Source\Entities\HashedSearchable; diff --git a/src/backend/tests/Feature/Api/Doors/DoorsCreateApiTest.php b/src/backend/tests/Feature/Api/Doors/DoorsCreateApiTest.php index dfc9633f..48dd1b9f 100644 --- a/src/backend/tests/Feature/Api/Doors/DoorsCreateApiTest.php +++ b/src/backend/tests/Feature/Api/Doors/DoorsCreateApiTest.php @@ -3,7 +3,6 @@ namespace Tests\Feature\Api\Doors; - use Illuminate\Testing\TestResponse; use Source\Entities\HashedSearchable; use Tests\Feature\AuthenticatesWithApplicationTestCase; diff --git a/src/backend/tests/Feature/Api/Doors/DoorsDeleteApiTest.php b/src/backend/tests/Feature/Api/Doors/DoorsDeleteApiTest.php index b8c5b62b..877a9f42 100644 --- a/src/backend/tests/Feature/Api/Doors/DoorsDeleteApiTest.php +++ b/src/backend/tests/Feature/Api/Doors/DoorsDeleteApiTest.php @@ -3,7 +3,6 @@ namespace Tests\Feature\Api\Doors; - use Source\Entities\Door; use Illuminate\Testing\TestResponse; use Source\Entities\HashedSearchable; diff --git a/src/backend/tests/Feature/Api/Doors/DoorsTokenRegenerateApiTest.php b/src/backend/tests/Feature/Api/Doors/DoorsTokenRegenerateApiTest.php index 8a7ac2f0..f4dc2924 100644 --- a/src/backend/tests/Feature/Api/Doors/DoorsTokenRegenerateApiTest.php +++ b/src/backend/tests/Feature/Api/Doors/DoorsTokenRegenerateApiTest.php @@ -3,7 +3,6 @@ namespace Tests\Feature\Api\Doors; - use Source\Entities\Door; use Illuminate\Testing\TestResponse; use Source\Entities\HashedSearchable; -- GitLab From 52b0201f6e36f8eb0fa6e6f3d071a23fcb3f5ac0 Mon Sep 17 00:00:00 2001 From: dakriy Date: Tue, 16 Jun 2020 15:22:59 -0700 Subject: [PATCH 09/38] public function setUp -> protected function setUp --- src/backend/tests/Database/AttemptDatabaseTest.php | 2 +- src/backend/tests/Database/DoorDatabaseTest.php | 2 +- src/backend/tests/Database/DoorGroupDatabaseTest.php | 2 +- .../tests/Database/DoorScheduleDatabaseTest.php | 2 +- src/backend/tests/Database/DoorUserDatabaseTest.php | 2 +- src/backend/tests/Database/EntriesDatabaseTest.php | 2 +- src/backend/tests/Database/GroupDatabaseTest.php | 2 +- src/backend/tests/Database/GroupUserDatabaseTest.php | 2 +- src/backend/tests/Database/OverrideDatabaseTest.php | 2 +- src/backend/tests/Database/ScheduleDatabaseTest.php | 2 +- src/backend/tests/Database/TokenDatabaseTest.php | 2 +- src/backend/tests/Database/UserDatabaseTest.php | 2 +- .../tests/Feature/Api/Attempts/AttemptsGetApiTest.php | 11 +++++++++++ .../tests/Feature/Api/Auth/AuthControllerTest.php | 2 +- .../tests/Feature/Api/Doors/DoorGetApiTest.php | 2 +- .../tests/Feature/Api/Doors/DoorsCreateApiTest.php | 2 +- .../tests/Feature/Api/Doors/DoorsDeleteApiTest.php | 2 +- .../tests/Feature/Api/Doors/DoorsGetApiTest.php | 2 +- .../Feature/Api/Doors/DoorsTokenRegenerateApiTest.php | 2 +- .../tests/Feature/Api/Doors/DoorsUpdateApiTest.php | 2 +- .../tests/Feature/Api/Groups/CreateGroupApiTest.php | 2 +- .../tests/Feature/Api/Groups/DeleteGroupApiTest.php | 2 +- .../tests/Feature/Api/Groups/GetAllGroupsApiTest.php | 2 +- .../tests/Feature/Api/Groups/GetGroupApiTest.php | 2 +- .../Feature/Api/Groups/GetUsersForGroupApiTest.php | 2 +- .../tests/Feature/Api/Groups/UpdateGroupApiTest.php | 2 +- .../Feature/Api/Me/GetCurrentUserGroupsApiTest.php | 2 +- .../tests/Feature/Api/Me/UpdateCurrentUserApiTest.php | 2 +- .../tests/Feature/Api/Users/AddUserToGroupApiTest.php | 2 +- .../Feature/Api/Users/GetGroupsForUserApiTest.php | 2 +- .../Feature/Api/Users/RemoveUserFromGroupApiTest.php | 2 +- .../Feature/AuthenticatesWithApplicationTestCase.php | 2 +- src/backend/tests/Feature/Door/DoorAccessTest.php | 2 +- src/backend/tests/Feature/Door/DoorStatusTest.php | 2 +- src/backend/tests/Feature/Door/DoorUpdateTest.php | 2 +- src/backend/tests/Unit/Guards/ApiGuardTest.php | 2 +- src/backend/tests/Unit/Guards/DoorGuardTest.php | 2 +- .../Repository/RecurrenceSetLibraryConnectorTest.php | 2 +- .../Unit/Repository/SimpleSamlIntegrationTest.php | 2 +- .../tests/Unit/Source/Authorizer/AuthorizerTest.php | 2 +- .../Door/Access/Authorizers/CommandAuthorizerTest.php | 2 +- .../Access/Authorizers/CommanderAuthorizerTest.php | 2 +- .../Access/Authorizers/OpenModeAuthorizerTest.php | 2 +- .../Access/Authorizers/OverrideAuthorizerTest.php | 2 +- .../Access/Authorizers/ScheduleAuthorizerTest.php | 2 +- .../Unit/Source/UseCases/Door/Access/UseCaseTest.php | 2 +- .../UseCases/Door/Authenticate/PresenterTest.php | 2 +- .../Source/UseCases/Door/Authenticate/UseCaseTest.php | 2 +- .../UseCases/Door/Commands/DoorCommandHandlerTest.php | 2 +- .../UseCases/Door/Commands/OverrideCommandTest.php | 2 +- .../StatusResponse/StatusResponsePresenterTest.php | 2 +- .../Door/StatusResponse/StatusResponseTest.php | 2 +- .../UseCases/Door/UpdateBinary/UpdateBinaryTest.php | 2 +- .../Source/UseCases/Doors/GetDoor/PresenterTest.php | 2 +- .../Source/UseCases/Doors/GetDoor/UseCaseTest.php | 2 +- .../GroupUser/AddUserToGroup/PresenterTest.php | 2 +- .../UseCases/GroupUser/AddUserToGroup/UseCaseTest.php | 2 +- .../GroupUser/GetGroupUsers/PresenterTest.php | 2 +- .../UseCases/GroupUser/GetGroupUsers/UseCaseTest.php | 2 +- .../GroupUser/GetUserGroups/PresenterTest.php | 2 +- .../UseCases/GroupUser/GetUserGroups/UseCaseTest.php | 2 +- .../GroupUser/RemoveUserFromGroup/PresenterTest.php | 2 +- .../GroupUser/RemoveUserFromGroup/UseCaseTest.php | 2 +- .../UseCases/Groups/CreateGroup/PresenterTest.php | 2 +- .../UseCases/Groups/CreateGroup/UseCaseTest.php | 2 +- .../UseCases/Groups/DeleteGroup/PresenterTest.php | 2 +- .../UseCases/Groups/DeleteGroup/UseCaseTest.php | 2 +- .../UseCases/Groups/GetAllGroups/PresenterTest.php | 2 +- .../UseCases/Groups/GetAllGroups/UseCaseTest.php | 2 +- .../Source/UseCases/Groups/GetGroup/PresenterTest.php | 2 +- .../Source/UseCases/Groups/GetGroup/UseCaseTest.php | 2 +- .../UseCases/Groups/UpdateGroup/PresenterTest.php | 2 +- .../UseCases/Groups/UpdateGroup/UseCaseTest.php | 2 +- .../Source/UseCases/Schedules/ScheduleCreateTest.php | 2 +- .../Source/UseCases/Schedules/ScheduleGetTest.php | 2 +- .../Source/UseCases/Schedules/ScheduleUpdateTest.php | 2 +- .../Schedules/SchedulesGet/SchedulesGetTest.php | 2 +- .../UseCases/Users/Authenticate/PresenterTest.php | 2 +- .../UseCases/Users/Authenticate/UseCaseBaseTest.php | 2 +- .../UseCases/Users/CreateUser/PresenterTest.php | 2 +- .../Source/UseCases/Users/CreateUser/UseCaseTest.php | 2 +- .../UseCases/Users/DeleteUser/PresenterTest.php | 2 +- .../Source/UseCases/Users/DeleteUser/UseCaseTest.php | 2 +- .../UseCases/Users/GetAllUsers/PresenterTest.php | 2 +- .../Source/UseCases/Users/GetAllUsers/UseCaseTest.php | 2 +- .../Source/UseCases/Users/GetUser/PresenterTest.php | 2 +- .../Source/UseCases/Users/GetUser/UseCaseTest.php | 2 +- .../Users/UpdateUser/CurrentUserUpdateUseCaseTest.php | 2 +- .../UseCases/Users/UpdateUser/PresenterTest.php | 2 +- .../Source/UseCases/Users/UpdateUser/UseCaseTest.php | 2 +- 90 files changed, 100 insertions(+), 89 deletions(-) create mode 100644 src/backend/tests/Feature/Api/Attempts/AttemptsGetApiTest.php diff --git a/src/backend/tests/Database/AttemptDatabaseTest.php b/src/backend/tests/Database/AttemptDatabaseTest.php index 73594b36..f2ccdbfe 100644 --- a/src/backend/tests/Database/AttemptDatabaseTest.php +++ b/src/backend/tests/Database/AttemptDatabaseTest.php @@ -22,7 +22,7 @@ class AttemptDatabaseTest extends DatabaseTestCase */ protected DatabaseDoorsRepository $doors; - public function setUp(): void + protected function setUp(): void { parent::setUp(); $this->repository = new DatabaseAttemptsRepository(); diff --git a/src/backend/tests/Database/DoorDatabaseTest.php b/src/backend/tests/Database/DoorDatabaseTest.php index 34c54ae0..e187666d 100644 --- a/src/backend/tests/Database/DoorDatabaseTest.php +++ b/src/backend/tests/Database/DoorDatabaseTest.php @@ -14,7 +14,7 @@ class DoorDatabaseTest extends DatabaseTestCase { protected DatabaseDoorsRepository $doors; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Database/DoorGroupDatabaseTest.php b/src/backend/tests/Database/DoorGroupDatabaseTest.php index ed20b558..eb73a326 100644 --- a/src/backend/tests/Database/DoorGroupDatabaseTest.php +++ b/src/backend/tests/Database/DoorGroupDatabaseTest.php @@ -29,7 +29,7 @@ class DoorGroupDatabaseTest extends DatabaseTestCase */ protected DatabaseGroupsRepository $groups; - public function setUp(): void + protected function setUp(): void { parent::setUp(); $this->doors = new DatabaseDoorsRepository(); diff --git a/src/backend/tests/Database/DoorScheduleDatabaseTest.php b/src/backend/tests/Database/DoorScheduleDatabaseTest.php index 52d7dd26..006c5f8a 100644 --- a/src/backend/tests/Database/DoorScheduleDatabaseTest.php +++ b/src/backend/tests/Database/DoorScheduleDatabaseTest.php @@ -49,7 +49,7 @@ class DoorScheduleDatabaseTest extends DatabaseTestCase */ protected DatabaseDoorScheduleRepository $doorSchedules; - public function setUp(): void + protected function setUp(): void { parent::setUp(); $this->doors = new DatabaseDoorsRepository(); diff --git a/src/backend/tests/Database/DoorUserDatabaseTest.php b/src/backend/tests/Database/DoorUserDatabaseTest.php index 6d57b117..5dcccb12 100644 --- a/src/backend/tests/Database/DoorUserDatabaseTest.php +++ b/src/backend/tests/Database/DoorUserDatabaseTest.php @@ -48,7 +48,7 @@ class DoorUserDatabaseTest extends DatabaseTestCase */ protected DatabaseGroupUserRepository $groupUsers; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Database/EntriesDatabaseTest.php b/src/backend/tests/Database/EntriesDatabaseTest.php index 05f64276..0020733b 100644 --- a/src/backend/tests/Database/EntriesDatabaseTest.php +++ b/src/backend/tests/Database/EntriesDatabaseTest.php @@ -30,7 +30,7 @@ class EntriesDatabaseTest extends DatabaseTestCase */ protected DatabaseEntriesRepository $repository; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Database/GroupDatabaseTest.php b/src/backend/tests/Database/GroupDatabaseTest.php index b63f34aa..d901b5b2 100644 --- a/src/backend/tests/Database/GroupDatabaseTest.php +++ b/src/backend/tests/Database/GroupDatabaseTest.php @@ -15,7 +15,7 @@ class GroupDatabaseTest extends DatabaseTestCase */ protected DatabaseGroupsRepository $groups; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Database/GroupUserDatabaseTest.php b/src/backend/tests/Database/GroupUserDatabaseTest.php index b4950725..f993f0cd 100644 --- a/src/backend/tests/Database/GroupUserDatabaseTest.php +++ b/src/backend/tests/Database/GroupUserDatabaseTest.php @@ -38,7 +38,7 @@ class GroupUserDatabaseTest extends DatabaseTestCase */ protected Group $group; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Database/OverrideDatabaseTest.php b/src/backend/tests/Database/OverrideDatabaseTest.php index 60ffdc81..1df03cc9 100644 --- a/src/backend/tests/Database/OverrideDatabaseTest.php +++ b/src/backend/tests/Database/OverrideDatabaseTest.php @@ -31,7 +31,7 @@ class OverrideDatabaseTest extends DatabaseTestCase */ protected DatabaseDoorsRepository $doors; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Database/ScheduleDatabaseTest.php b/src/backend/tests/Database/ScheduleDatabaseTest.php index 57e20c74..3a048adc 100644 --- a/src/backend/tests/Database/ScheduleDatabaseTest.php +++ b/src/backend/tests/Database/ScheduleDatabaseTest.php @@ -22,7 +22,7 @@ class ScheduleDatabaseTest extends DatabaseTestCase */ protected DatabaseGroupsRepository $groups; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Database/TokenDatabaseTest.php b/src/backend/tests/Database/TokenDatabaseTest.php index 9096365c..aada9b66 100644 --- a/src/backend/tests/Database/TokenDatabaseTest.php +++ b/src/backend/tests/Database/TokenDatabaseTest.php @@ -37,7 +37,7 @@ class TokenDatabaseTest extends DatabaseTestCase /** * @throws \Source\Exceptions\EntityExistsException */ - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Database/UserDatabaseTest.php b/src/backend/tests/Database/UserDatabaseTest.php index 8f22e558..b0883d03 100644 --- a/src/backend/tests/Database/UserDatabaseTest.php +++ b/src/backend/tests/Database/UserDatabaseTest.php @@ -17,7 +17,7 @@ class UserDatabaseTest extends DatabaseTestCase */ protected DatabaseUsersRepository $users; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Feature/Api/Attempts/AttemptsGetApiTest.php b/src/backend/tests/Feature/Api/Attempts/AttemptsGetApiTest.php new file mode 100644 index 00000000..05b42001 --- /dev/null +++ b/src/backend/tests/Feature/Api/Attempts/AttemptsGetApiTest.php @@ -0,0 +1,11 @@ +doorSchedules = $this->app->make(DoorScheduleRepository::class); diff --git a/src/backend/tests/Feature/Door/DoorStatusTest.php b/src/backend/tests/Feature/Door/DoorStatusTest.php index 9365609b..db75534f 100644 --- a/src/backend/tests/Feature/Door/DoorStatusTest.php +++ b/src/backend/tests/Feature/Door/DoorStatusTest.php @@ -19,7 +19,7 @@ class DoorStatusTest extends AuthenticatesWithApplicationTestCase protected TestResponse $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Feature/Door/DoorUpdateTest.php b/src/backend/tests/Feature/Door/DoorUpdateTest.php index 539fc17b..83718415 100644 --- a/src/backend/tests/Feature/Door/DoorUpdateTest.php +++ b/src/backend/tests/Feature/Door/DoorUpdateTest.php @@ -25,7 +25,7 @@ class DoorUpdateTest extends AuthenticatesWithApplicationTestCase */ protected Filesystem $disk; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Guards/ApiGuardTest.php b/src/backend/tests/Unit/Guards/ApiGuardTest.php index c280b641..be5cd971 100644 --- a/src/backend/tests/Unit/Guards/ApiGuardTest.php +++ b/src/backend/tests/Unit/Guards/ApiGuardTest.php @@ -38,7 +38,7 @@ class ApiGuardTest extends TestCase */ protected TokenPresenterStub $presenter; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Guards/DoorGuardTest.php b/src/backend/tests/Unit/Guards/DoorGuardTest.php index d2467b57..834c3771 100644 --- a/src/backend/tests/Unit/Guards/DoorGuardTest.php +++ b/src/backend/tests/Unit/Guards/DoorGuardTest.php @@ -39,7 +39,7 @@ class DoorGuardTest extends TestCase */ protected DoorPresenterStub $presenter; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Repository/RecurrenceSetLibraryConnectorTest.php b/src/backend/tests/Unit/Repository/RecurrenceSetLibraryConnectorTest.php index d9f8b5ca..c238a0a7 100644 --- a/src/backend/tests/Unit/Repository/RecurrenceSetLibraryConnectorTest.php +++ b/src/backend/tests/Unit/Repository/RecurrenceSetLibraryConnectorTest.php @@ -19,7 +19,7 @@ class RecurrenceSetLibraryConnectorTest extends TestCase protected string $beginString; - public function setUp(): void + protected function setUp(): void { parent::setUp(); $this->begin = Carbon::parse('2020-05-17 17:49:10', 'America/Los_Angeles'); diff --git a/src/backend/tests/Unit/Repository/SimpleSamlIntegrationTest.php b/src/backend/tests/Unit/Repository/SimpleSamlIntegrationTest.php index ecd574bc..0d92d87a 100644 --- a/src/backend/tests/Unit/Repository/SimpleSamlIntegrationTest.php +++ b/src/backend/tests/Unit/Repository/SimpleSamlIntegrationTest.php @@ -18,7 +18,7 @@ class SimpleSamlIntegrationTest extends TestCase */ protected SimpleSamlPhpSamlRepository $saml; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/Authorizer/AuthorizerTest.php b/src/backend/tests/Unit/Source/Authorizer/AuthorizerTest.php index b03c55f0..6d9737e6 100644 --- a/src/backend/tests/Unit/Source/Authorizer/AuthorizerTest.php +++ b/src/backend/tests/Unit/Source/Authorizer/AuthorizerTest.php @@ -41,7 +41,7 @@ class AuthorizerTest extends TestCase */ protected ?string $currentUserId; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Door/Access/Authorizers/CommandAuthorizerTest.php b/src/backend/tests/Unit/Source/UseCases/Door/Access/Authorizers/CommandAuthorizerTest.php index 0d1600a2..690a41e9 100644 --- a/src/backend/tests/Unit/Source/UseCases/Door/Access/Authorizers/CommandAuthorizerTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Door/Access/Authorizers/CommandAuthorizerTest.php @@ -30,7 +30,7 @@ class CommandAuthorizerTest extends TestCase protected int $status; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Door/Access/Authorizers/CommanderAuthorizerTest.php b/src/backend/tests/Unit/Source/UseCases/Door/Access/Authorizers/CommanderAuthorizerTest.php index b284a777..e5bf2b2b 100644 --- a/src/backend/tests/Unit/Source/UseCases/Door/Access/Authorizers/CommanderAuthorizerTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Door/Access/Authorizers/CommanderAuthorizerTest.php @@ -24,7 +24,7 @@ class CommanderAuthorizerTest extends TestCase protected int $status; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Door/Access/Authorizers/OpenModeAuthorizerTest.php b/src/backend/tests/Unit/Source/UseCases/Door/Access/Authorizers/OpenModeAuthorizerTest.php index 6e645b68..85649fac 100644 --- a/src/backend/tests/Unit/Source/UseCases/Door/Access/Authorizers/OpenModeAuthorizerTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Door/Access/Authorizers/OpenModeAuthorizerTest.php @@ -34,7 +34,7 @@ class OpenModeAuthorizerTest extends TestCase */ protected RecurrenceSetStub $recurrenceSet; - public function setUp(): void + protected function setUp(): void { parent::setUp(); $this->date = new Carbon('2020-05-15 14:46:25'); diff --git a/src/backend/tests/Unit/Source/UseCases/Door/Access/Authorizers/OverrideAuthorizerTest.php b/src/backend/tests/Unit/Source/UseCases/Door/Access/Authorizers/OverrideAuthorizerTest.php index ec0a432d..234bd62b 100644 --- a/src/backend/tests/Unit/Source/UseCases/Door/Access/Authorizers/OverrideAuthorizerTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Door/Access/Authorizers/OverrideAuthorizerTest.php @@ -24,7 +24,7 @@ class OverrideAuthorizerTest extends TestCase protected int $status; - public function setUp(): void + protected function setUp(): void { parent::setUp(); $this->overrides = new InMemoryOverridesRepository(); diff --git a/src/backend/tests/Unit/Source/UseCases/Door/Access/Authorizers/ScheduleAuthorizerTest.php b/src/backend/tests/Unit/Source/UseCases/Door/Access/Authorizers/ScheduleAuthorizerTest.php index d9f2b9c9..586914e8 100644 --- a/src/backend/tests/Unit/Source/UseCases/Door/Access/Authorizers/ScheduleAuthorizerTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Door/Access/Authorizers/ScheduleAuthorizerTest.php @@ -43,7 +43,7 @@ class ScheduleAuthorizerTest extends TestCase */ protected InMemoryDoorUserRepository $doorUsers; - public function setUp(): void + protected function setUp(): void { parent::setUp(); $this->date = new Carbon('2020-05-15 14:46:25'); diff --git a/src/backend/tests/Unit/Source/UseCases/Door/Access/UseCaseTest.php b/src/backend/tests/Unit/Source/UseCases/Door/Access/UseCaseTest.php index 7bdf8d27..1a870878 100644 --- a/src/backend/tests/Unit/Source/UseCases/Door/Access/UseCaseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Door/Access/UseCaseTest.php @@ -47,7 +47,7 @@ class UseCaseTest extends TestCase */ protected InMemoryUsersRepository $users; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Door/Authenticate/PresenterTest.php b/src/backend/tests/Unit/Source/UseCases/Door/Authenticate/PresenterTest.php index 07124fac..4992211a 100644 --- a/src/backend/tests/Unit/Source/UseCases/Door/Authenticate/PresenterTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Door/Authenticate/PresenterTest.php @@ -26,7 +26,7 @@ class PresenterTest extends TestCase */ protected ?\App\Door $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Door/Authenticate/UseCaseTest.php b/src/backend/tests/Unit/Source/UseCases/Door/Authenticate/UseCaseTest.php index 1edf19f5..fd995265 100644 --- a/src/backend/tests/Unit/Source/UseCases/Door/Authenticate/UseCaseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Door/Authenticate/UseCaseTest.php @@ -29,7 +29,7 @@ class UseCaseTest extends TestCase protected Authenticate $useCase; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Door/Commands/DoorCommandHandlerTest.php b/src/backend/tests/Unit/Source/UseCases/Door/Commands/DoorCommandHandlerTest.php index 9541088b..ad6512cf 100644 --- a/src/backend/tests/Unit/Source/UseCases/Door/Commands/DoorCommandHandlerTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Door/Commands/DoorCommandHandlerTest.php @@ -22,7 +22,7 @@ class DoorCommandHandlerTest extends TestCase protected bool $success = false; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Door/Commands/OverrideCommandTest.php b/src/backend/tests/Unit/Source/UseCases/Door/Commands/OverrideCommandTest.php index 9d0050db..203d6f35 100644 --- a/src/backend/tests/Unit/Source/UseCases/Door/Commands/OverrideCommandTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Door/Commands/OverrideCommandTest.php @@ -27,7 +27,7 @@ class OverrideCommandTest extends TestCase protected bool $success = false; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Door/StatusResponse/StatusResponsePresenterTest.php b/src/backend/tests/Unit/Source/UseCases/Door/StatusResponse/StatusResponsePresenterTest.php index 779e607c..d1836f9a 100644 --- a/src/backend/tests/Unit/Source/UseCases/Door/StatusResponse/StatusResponsePresenterTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Door/StatusResponse/StatusResponsePresenterTest.php @@ -26,7 +26,7 @@ class StatusResponsePresenterTest extends TestCase */ protected array $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); $this->responseModel = new ResponseModel(); diff --git a/src/backend/tests/Unit/Source/UseCases/Door/StatusResponse/StatusResponseTest.php b/src/backend/tests/Unit/Source/UseCases/Door/StatusResponse/StatusResponseTest.php index 7b021671..f77cf078 100644 --- a/src/backend/tests/Unit/Source/UseCases/Door/StatusResponse/StatusResponseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Door/StatusResponse/StatusResponseTest.php @@ -45,7 +45,7 @@ class StatusResponseTest extends TestCase */ protected RecurrenceSetStub $rset; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Door/UpdateBinary/UpdateBinaryTest.php b/src/backend/tests/Unit/Source/UseCases/Door/UpdateBinary/UpdateBinaryTest.php index d4e34807..5d57f5a3 100644 --- a/src/backend/tests/Unit/Source/UseCases/Door/UpdateBinary/UpdateBinaryTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Door/UpdateBinary/UpdateBinaryTest.php @@ -26,7 +26,7 @@ class UpdateBinaryTest extends TestCase protected string $returnedPath; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Doors/GetDoor/PresenterTest.php b/src/backend/tests/Unit/Source/UseCases/Doors/GetDoor/PresenterTest.php index 17a5db8c..b7deca82 100644 --- a/src/backend/tests/Unit/Source/UseCases/Doors/GetDoor/PresenterTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Doors/GetDoor/PresenterTest.php @@ -27,7 +27,7 @@ class PresenterTest extends TestCase */ protected array $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Doors/GetDoor/UseCaseTest.php b/src/backend/tests/Unit/Source/UseCases/Doors/GetDoor/UseCaseTest.php index 4cf7fbd0..96d6aee3 100644 --- a/src/backend/tests/Unit/Source/UseCases/Doors/GetDoor/UseCaseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Doors/GetDoor/UseCaseTest.php @@ -33,7 +33,7 @@ class UseCaseTest extends TestCase */ protected PresenterStub $presenter; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/GroupUser/AddUserToGroup/PresenterTest.php b/src/backend/tests/Unit/Source/UseCases/GroupUser/AddUserToGroup/PresenterTest.php index 239208b9..17fbc652 100644 --- a/src/backend/tests/Unit/Source/UseCases/GroupUser/AddUserToGroup/PresenterTest.php +++ b/src/backend/tests/Unit/Source/UseCases/GroupUser/AddUserToGroup/PresenterTest.php @@ -15,7 +15,7 @@ class PresenterTest extends TestCase protected array $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/GroupUser/AddUserToGroup/UseCaseTest.php b/src/backend/tests/Unit/Source/UseCases/GroupUser/AddUserToGroup/UseCaseTest.php index 5eccef72..691c328b 100644 --- a/src/backend/tests/Unit/Source/UseCases/GroupUser/AddUserToGroup/UseCaseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/GroupUser/AddUserToGroup/UseCaseTest.php @@ -50,7 +50,7 @@ class UseCaseTest extends TestCase protected AuthorizerStub $authorizer; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/GroupUser/GetGroupUsers/PresenterTest.php b/src/backend/tests/Unit/Source/UseCases/GroupUser/GetGroupUsers/PresenterTest.php index 1aa1fdef..1ae99723 100644 --- a/src/backend/tests/Unit/Source/UseCases/GroupUser/GetGroupUsers/PresenterTest.php +++ b/src/backend/tests/Unit/Source/UseCases/GroupUser/GetGroupUsers/PresenterTest.php @@ -16,7 +16,7 @@ class PresenterTest extends TestCase protected array $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/GroupUser/GetGroupUsers/UseCaseTest.php b/src/backend/tests/Unit/Source/UseCases/GroupUser/GetGroupUsers/UseCaseTest.php index 8a708fa9..a22a5235 100644 --- a/src/backend/tests/Unit/Source/UseCases/GroupUser/GetGroupUsers/UseCaseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/GroupUser/GetGroupUsers/UseCaseTest.php @@ -30,7 +30,7 @@ class UseCaseTest extends TestCase protected GroupsRepository $groups; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/GroupUser/GetUserGroups/PresenterTest.php b/src/backend/tests/Unit/Source/UseCases/GroupUser/GetUserGroups/PresenterTest.php index 503e985b..a32d8abb 100644 --- a/src/backend/tests/Unit/Source/UseCases/GroupUser/GetUserGroups/PresenterTest.php +++ b/src/backend/tests/Unit/Source/UseCases/GroupUser/GetUserGroups/PresenterTest.php @@ -16,7 +16,7 @@ class PresenterTest extends TestCase protected array $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/GroupUser/GetUserGroups/UseCaseTest.php b/src/backend/tests/Unit/Source/UseCases/GroupUser/GetUserGroups/UseCaseTest.php index 5f603181..e05c8382 100644 --- a/src/backend/tests/Unit/Source/UseCases/GroupUser/GetUserGroups/UseCaseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/GroupUser/GetUserGroups/UseCaseTest.php @@ -30,7 +30,7 @@ class UseCaseTest extends TestCase protected GroupsRepository $groups; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/GroupUser/RemoveUserFromGroup/PresenterTest.php b/src/backend/tests/Unit/Source/UseCases/GroupUser/RemoveUserFromGroup/PresenterTest.php index 8e3508c5..c48f1315 100644 --- a/src/backend/tests/Unit/Source/UseCases/GroupUser/RemoveUserFromGroup/PresenterTest.php +++ b/src/backend/tests/Unit/Source/UseCases/GroupUser/RemoveUserFromGroup/PresenterTest.php @@ -15,7 +15,7 @@ class PresenterTest extends TestCase protected array $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/GroupUser/RemoveUserFromGroup/UseCaseTest.php b/src/backend/tests/Unit/Source/UseCases/GroupUser/RemoveUserFromGroup/UseCaseTest.php index 1418eaec..fae2bba5 100644 --- a/src/backend/tests/Unit/Source/UseCases/GroupUser/RemoveUserFromGroup/UseCaseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/GroupUser/RemoveUserFromGroup/UseCaseTest.php @@ -50,7 +50,7 @@ class UseCaseTest extends TestCase */ protected AuthorizerStub $authorizer; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Groups/CreateGroup/PresenterTest.php b/src/backend/tests/Unit/Source/UseCases/Groups/CreateGroup/PresenterTest.php index 4404b63d..b5279815 100644 --- a/src/backend/tests/Unit/Source/UseCases/Groups/CreateGroup/PresenterTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Groups/CreateGroup/PresenterTest.php @@ -17,7 +17,7 @@ class PresenterTest extends TestCase protected array $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Groups/CreateGroup/UseCaseTest.php b/src/backend/tests/Unit/Source/UseCases/Groups/CreateGroup/UseCaseTest.php index 26b97209..9f9b758b 100644 --- a/src/backend/tests/Unit/Source/UseCases/Groups/CreateGroup/UseCaseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Groups/CreateGroup/UseCaseTest.php @@ -33,7 +33,7 @@ class UseCaseTest extends TestCase */ protected PresenterStub $presenter; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Groups/DeleteGroup/PresenterTest.php b/src/backend/tests/Unit/Source/UseCases/Groups/DeleteGroup/PresenterTest.php index 33777113..6a1fbf64 100644 --- a/src/backend/tests/Unit/Source/UseCases/Groups/DeleteGroup/PresenterTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Groups/DeleteGroup/PresenterTest.php @@ -15,7 +15,7 @@ class PresenterTest extends TestCase protected array $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Groups/DeleteGroup/UseCaseTest.php b/src/backend/tests/Unit/Source/UseCases/Groups/DeleteGroup/UseCaseTest.php index 90e11820..2b8539f4 100644 --- a/src/backend/tests/Unit/Source/UseCases/Groups/DeleteGroup/UseCaseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Groups/DeleteGroup/UseCaseTest.php @@ -22,7 +22,7 @@ class UseCaseTest extends TestCase protected PresenterStub $presenter; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Groups/GetAllGroups/PresenterTest.php b/src/backend/tests/Unit/Source/UseCases/Groups/GetAllGroups/PresenterTest.php index 49c950d2..736a86b2 100644 --- a/src/backend/tests/Unit/Source/UseCases/Groups/GetAllGroups/PresenterTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Groups/GetAllGroups/PresenterTest.php @@ -17,7 +17,7 @@ class PresenterTest extends TestCase protected array $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Groups/GetAllGroups/UseCaseTest.php b/src/backend/tests/Unit/Source/UseCases/Groups/GetAllGroups/UseCaseTest.php index a5801904..8d3a5576 100644 --- a/src/backend/tests/Unit/Source/UseCases/Groups/GetAllGroups/UseCaseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Groups/GetAllGroups/UseCaseTest.php @@ -31,7 +31,7 @@ class UseCaseTest extends TestCase */ protected PresenterStub $presenter; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Groups/GetGroup/PresenterTest.php b/src/backend/tests/Unit/Source/UseCases/Groups/GetGroup/PresenterTest.php index 998057c4..93923cee 100644 --- a/src/backend/tests/Unit/Source/UseCases/Groups/GetGroup/PresenterTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Groups/GetGroup/PresenterTest.php @@ -17,7 +17,7 @@ class PresenterTest extends TestCase protected array $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Groups/GetGroup/UseCaseTest.php b/src/backend/tests/Unit/Source/UseCases/Groups/GetGroup/UseCaseTest.php index 9f5e8cda..98e980d4 100644 --- a/src/backend/tests/Unit/Source/UseCases/Groups/GetGroup/UseCaseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Groups/GetGroup/UseCaseTest.php @@ -20,7 +20,7 @@ class UseCaseTest extends TestCase protected PresenterStub $presenter; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Groups/UpdateGroup/PresenterTest.php b/src/backend/tests/Unit/Source/UseCases/Groups/UpdateGroup/PresenterTest.php index c58c809b..14904aad 100644 --- a/src/backend/tests/Unit/Source/UseCases/Groups/UpdateGroup/PresenterTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Groups/UpdateGroup/PresenterTest.php @@ -17,7 +17,7 @@ class PresenterTest extends TestCase protected array $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Groups/UpdateGroup/UseCaseTest.php b/src/backend/tests/Unit/Source/UseCases/Groups/UpdateGroup/UseCaseTest.php index 28be9ce3..73bdbef7 100644 --- a/src/backend/tests/Unit/Source/UseCases/Groups/UpdateGroup/UseCaseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Groups/UpdateGroup/UseCaseTest.php @@ -22,7 +22,7 @@ class UseCaseTest extends TestCase protected PresenterStub $presenter; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Schedules/ScheduleCreateTest.php b/src/backend/tests/Unit/Source/UseCases/Schedules/ScheduleCreateTest.php index 855d5bfd..7a6f89fe 100644 --- a/src/backend/tests/Unit/Source/UseCases/Schedules/ScheduleCreateTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Schedules/ScheduleCreateTest.php @@ -44,7 +44,7 @@ class ScheduleCreateTest extends TestCase */ protected ResponseModel $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Schedules/ScheduleGetTest.php b/src/backend/tests/Unit/Source/UseCases/Schedules/ScheduleGetTest.php index a5f8b5c3..21d033d0 100644 --- a/src/backend/tests/Unit/Source/UseCases/Schedules/ScheduleGetTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Schedules/ScheduleGetTest.php @@ -32,7 +32,7 @@ class ScheduleGetTest extends TestCase */ protected ResponseModel $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Schedules/ScheduleUpdateTest.php b/src/backend/tests/Unit/Source/UseCases/Schedules/ScheduleUpdateTest.php index fc8fb220..f23348cf 100644 --- a/src/backend/tests/Unit/Source/UseCases/Schedules/ScheduleUpdateTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Schedules/ScheduleUpdateTest.php @@ -49,7 +49,7 @@ class ScheduleUpdateTest extends TestCase */ protected ScheduleUpdate $useCase; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Schedules/SchedulesGet/SchedulesGetTest.php b/src/backend/tests/Unit/Source/UseCases/Schedules/SchedulesGet/SchedulesGetTest.php index 84e9337f..e8c3337d 100644 --- a/src/backend/tests/Unit/Source/UseCases/Schedules/SchedulesGet/SchedulesGetTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Schedules/SchedulesGet/SchedulesGetTest.php @@ -32,7 +32,7 @@ class SchedulesGetTest extends TestCase */ protected ResponseModel $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Users/Authenticate/PresenterTest.php b/src/backend/tests/Unit/Source/UseCases/Users/Authenticate/PresenterTest.php index f590e7f8..83ee81a3 100644 --- a/src/backend/tests/Unit/Source/UseCases/Users/Authenticate/PresenterTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Users/Authenticate/PresenterTest.php @@ -29,7 +29,7 @@ class PresenterTest extends TestCase */ protected array $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Users/Authenticate/UseCaseBaseTest.php b/src/backend/tests/Unit/Source/UseCases/Users/Authenticate/UseCaseBaseTest.php index d4292b95..9be4d40c 100644 --- a/src/backend/tests/Unit/Source/UseCases/Users/Authenticate/UseCaseBaseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Users/Authenticate/UseCaseBaseTest.php @@ -57,7 +57,7 @@ abstract class UseCaseBaseTest extends TestCase public const VALID_TOKEN = '97055'; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Users/CreateUser/PresenterTest.php b/src/backend/tests/Unit/Source/UseCases/Users/CreateUser/PresenterTest.php index e522f59d..5b9b5a2d 100644 --- a/src/backend/tests/Unit/Source/UseCases/Users/CreateUser/PresenterTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Users/CreateUser/PresenterTest.php @@ -19,7 +19,7 @@ class PresenterTest extends TestCase protected array $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Users/CreateUser/UseCaseTest.php b/src/backend/tests/Unit/Source/UseCases/Users/CreateUser/UseCaseTest.php index 131c38d0..6d4f5296 100644 --- a/src/backend/tests/Unit/Source/UseCases/Users/CreateUser/UseCaseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Users/CreateUser/UseCaseTest.php @@ -21,7 +21,7 @@ class UseCaseTest extends TestCase protected PresenterStub $presenter; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Users/DeleteUser/PresenterTest.php b/src/backend/tests/Unit/Source/UseCases/Users/DeleteUser/PresenterTest.php index 7af62b82..b4c6acd0 100644 --- a/src/backend/tests/Unit/Source/UseCases/Users/DeleteUser/PresenterTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Users/DeleteUser/PresenterTest.php @@ -15,7 +15,7 @@ class PresenterTest extends TestCase protected array $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Users/DeleteUser/UseCaseTest.php b/src/backend/tests/Unit/Source/UseCases/Users/DeleteUser/UseCaseTest.php index d853e7a3..59ff3b9b 100644 --- a/src/backend/tests/Unit/Source/UseCases/Users/DeleteUser/UseCaseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Users/DeleteUser/UseCaseTest.php @@ -24,7 +24,7 @@ class UseCaseTest extends TestCase protected AuthorizerStub $authorizer; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Users/GetAllUsers/PresenterTest.php b/src/backend/tests/Unit/Source/UseCases/Users/GetAllUsers/PresenterTest.php index 8fe72f0b..8bb98164 100644 --- a/src/backend/tests/Unit/Source/UseCases/Users/GetAllUsers/PresenterTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Users/GetAllUsers/PresenterTest.php @@ -19,7 +19,7 @@ class PresenterTest extends TestCase protected array $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Users/GetAllUsers/UseCaseTest.php b/src/backend/tests/Unit/Source/UseCases/Users/GetAllUsers/UseCaseTest.php index d3ae459b..36f911d8 100644 --- a/src/backend/tests/Unit/Source/UseCases/Users/GetAllUsers/UseCaseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Users/GetAllUsers/UseCaseTest.php @@ -28,7 +28,7 @@ class UseCaseTest extends TestCase protected PresenterStub $presenter; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Users/GetUser/PresenterTest.php b/src/backend/tests/Unit/Source/UseCases/Users/GetUser/PresenterTest.php index 4bfde978..faa02700 100644 --- a/src/backend/tests/Unit/Source/UseCases/Users/GetUser/PresenterTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Users/GetUser/PresenterTest.php @@ -28,7 +28,7 @@ class PresenterTest extends TestCase */ protected array $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Users/GetUser/UseCaseTest.php b/src/backend/tests/Unit/Source/UseCases/Users/GetUser/UseCaseTest.php index ec412bad..3650ec54 100644 --- a/src/backend/tests/Unit/Source/UseCases/Users/GetUser/UseCaseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Users/GetUser/UseCaseTest.php @@ -20,7 +20,7 @@ class UseCaseTest extends TestCase protected PresenterStub $presenter; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Users/UpdateUser/CurrentUserUpdateUseCaseTest.php b/src/backend/tests/Unit/Source/UseCases/Users/UpdateUser/CurrentUserUpdateUseCaseTest.php index 63b89399..f292920f 100644 --- a/src/backend/tests/Unit/Source/UseCases/Users/UpdateUser/CurrentUserUpdateUseCaseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Users/UpdateUser/CurrentUserUpdateUseCaseTest.php @@ -41,7 +41,7 @@ class CurrentUserUpdateUseCaseTest extends TestCase */ protected AuthorizerStub $authorizer; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Users/UpdateUser/PresenterTest.php b/src/backend/tests/Unit/Source/UseCases/Users/UpdateUser/PresenterTest.php index e9fb23bf..75019845 100644 --- a/src/backend/tests/Unit/Source/UseCases/Users/UpdateUser/PresenterTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Users/UpdateUser/PresenterTest.php @@ -19,7 +19,7 @@ class PresenterTest extends TestCase protected array $response; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/src/backend/tests/Unit/Source/UseCases/Users/UpdateUser/UseCaseTest.php b/src/backend/tests/Unit/Source/UseCases/Users/UpdateUser/UseCaseTest.php index a60f5268..eeaf6f5b 100644 --- a/src/backend/tests/Unit/Source/UseCases/Users/UpdateUser/UseCaseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Users/UpdateUser/UseCaseTest.php @@ -27,7 +27,7 @@ class UseCaseTest extends TestCase protected AuthorizerStub $authorizer; - public function setUp(): void + protected function setUp(): void { parent::setUp(); -- GitLab From 73b08a29f7d456e38da2a68090ccae67e18b03c9 Mon Sep 17 00:00:00 2001 From: dakriy Date: Tue, 16 Jun 2020 15:35:12 -0700 Subject: [PATCH 10/38] attempts test --- .../Api/Attempts/AttemptsGetApiTest.php | 82 ++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/src/backend/tests/Feature/Api/Attempts/AttemptsGetApiTest.php b/src/backend/tests/Feature/Api/Attempts/AttemptsGetApiTest.php index 05b42001..20944651 100644 --- a/src/backend/tests/Feature/Api/Attempts/AttemptsGetApiTest.php +++ b/src/backend/tests/Feature/Api/Attempts/AttemptsGetApiTest.php @@ -3,9 +3,89 @@ namespace Tests\Feature\Api\Attempts; - +use Carbon\Carbon; +use Source\Entities\Attempt; +use Illuminate\Testing\TestResponse; +use Source\Gateways\Attempts\AttemptsRepository; use Tests\Feature\AuthenticatesWithApplicationTestCase; +use Source\Gateways\Attempts\InMemoryAttemptsRepository; class AttemptsGetApiTest extends AuthenticatesWithApplicationTestCase { + /** + * @var \Illuminate\Testing\TestResponse + */ + protected TestResponse $response; + + /** + * @var \Source\Gateways\Attempts\InMemoryAttemptsRepository + */ + protected InMemoryAttemptsRepository $attempts; + + /** + * @throws \Illuminate\Contracts\Container\BindingResolutionException + * @throws \Source\Exceptions\EntityExistsException + * @throws \Source\Exceptions\EntityNotFoundException + */ + protected function setUp(): void + { + parent::setUp(); + + $this->attempts = new InMemoryAttemptsRepository(); + $this->instance(AttemptsRepository::class, $this->attempts); + + $this->authenticate(); + } + + protected function handleTest(?string $door_id = null, ?string $start = null, ?string $end = null): void + { + $this->response = $this->getJson( + 'api/attempts?api_token=' . $this->authToken + . '&door_id=' . $door_id + . '&start=' . $start + . '&end=' . $end + ); + } + + /** + * @test + */ + public function it_scopes_to_start_date(): void + { + $this->attempts->add(new Attempt(1, 1, new Carbon('2020-05-13'))); + $this->attempts->add(new Attempt(1, 2, new Carbon('2020-05-15'))); + + $this->handleTest(null, '2020-05-14', null); + + $this->response->assertJsonCount(1, 'data'); + $this->assertEquals(2, $this->response->json('data')[0]['door_id']); + } + + /** + * @test + */ + public function it_scopes_to_end_date(): void + { + $this->attempts->add(new Attempt(1, 1, new Carbon('2020-05-13'))); + $this->attempts->add(new Attempt(1, 2, new Carbon('2020-05-15'))); + + $this->handleTest(null, null, '2020-05-14'); + + $this->response->assertJsonCount(1, 'data'); + $this->assertEquals(1, $this->response->json('data')[0]['door_id']); + } + + /** + * @test + */ + public function it_scopes_to_door_id(): void + { + $this->attempts->add(new Attempt(1, 1, new Carbon('2020-05-13'))); + $this->attempts->add(new Attempt(1, 2, new Carbon('2020-05-15'))); + + $this->handleTest(1); + + $this->response->assertJsonCount(1, 'data'); + $this->assertEquals(1, $this->response->json('data')[0]['door_id']); + } } -- GitLab From d54536b39920bfd1e2535febe8b62eaa645160fe Mon Sep 17 00:00:00 2001 From: dakriy Date: Tue, 16 Jun 2020 16:45:31 -0700 Subject: [PATCH 11/38] add override create test --- .../app/Http/Controllers/ApiController.php | 15 +-- .../OverrideCreate/OverrideCreate.php | 38 ++++---- .../Api/Overrides/OverridesCreateApiTest.php | 95 +++++++++++++++++++ 3 files changed, 117 insertions(+), 31 deletions(-) create mode 100644 src/backend/tests/Feature/Api/Overrides/OverridesCreateApiTest.php diff --git a/src/backend/app/Http/Controllers/ApiController.php b/src/backend/app/Http/Controllers/ApiController.php index c0454b11..9727e7e1 100644 --- a/src/backend/app/Http/Controllers/ApiController.php +++ b/src/backend/app/Http/Controllers/ApiController.php @@ -38,17 +38,6 @@ abstract class ApiController extends Controller $this->status = $code; } - /** - * @return \Illuminate\Http\JsonResponse - */ - public function respondSuccess(): JsonResponse - { - return new JsonResponse([ - 'status' => 'success', - 'code' => $this->status, - ], $this->status); - } - /** * @param array $data * @return JsonResponse @@ -56,7 +45,7 @@ abstract class ApiController extends Controller public function respondWithData(array $data): JsonResponse { return new JsonResponse(array_merge($data, [ - 'status' => 'success', + 'status' => $this->status === 200 ? 'success' : 'error', 'code' => $this->status, ]), $this->status); } @@ -65,7 +54,7 @@ abstract class ApiController extends Controller { return new JsonResponse([ 'message' => $message, - 'status' => 'success', + 'status' => $this->status === 200 ? 'success' : 'error', 'code' => $this->status, ], $this->status); } diff --git a/src/backend/src/UseCases/Overrides/OverrideCreate/OverrideCreate.php b/src/backend/src/UseCases/Overrides/OverrideCreate/OverrideCreate.php index 79232ef8..f3cfec51 100644 --- a/src/backend/src/UseCases/Overrides/OverrideCreate/OverrideCreate.php +++ b/src/backend/src/UseCases/Overrides/OverrideCreate/OverrideCreate.php @@ -53,26 +53,28 @@ class OverrideCreate implements OverrideCreateUseCase $response->addError('Door does not exist!'); } - try { - $override = $this->overrides->addOverride( - new Override( - 0, - $attributes['reason'], - $userId, - $doorId, - $attributes['type'], - new Carbon($attributes['start']), - new Carbon($attributes['end']) - ) - ); + if (!$response->hasError()) { + try { + $override = $this->overrides->addOverride( + new Override( + 0, + $attributes['reason'], + $userId, + $doorId, + $attributes['type'], + new Carbon($attributes['start']), + new Carbon($attributes['end']) + ) + ); - if (!$override) { - $response->addError('Something went wrong when adding the override'); - } else { - $response->setOverride($override); + if (!$override) { + $response->addError('Something went wrong when adding the override'); + } else { + $response->setOverride($override); + } + } catch (InvalidArgumentException $e) { + $response->addError($e->getMessage()); } - } catch (InvalidArgumentException $e) { - $response->addError($e->getMessage()); } if ($response->hasError()) { diff --git a/src/backend/tests/Feature/Api/Overrides/OverridesCreateApiTest.php b/src/backend/tests/Feature/Api/Overrides/OverridesCreateApiTest.php new file mode 100644 index 00000000..99baa03f --- /dev/null +++ b/src/backend/tests/Feature/Api/Overrides/OverridesCreateApiTest.php @@ -0,0 +1,95 @@ +overrides = new InMemoryOverridesRepository(); + $this->instance(OverridesRepository::class, $this->overrides); + + $this->authenticate(); + } + + /** + * @param array $data + */ + protected function handleTest(array $data): void + { + $this->response = $this->postJson( + 'api/overrides', + array_merge( + ['api_token' => $this->authToken], + $data + ) + ); + } + + /** + * @test + * @throws \Source\Exceptions\EntityExistsException + */ + public function it_creates_an_override(): void + { + $this->doorsRepository->create(new Door(1, '', '', new HashedSearchable(''))); + $overrides = $this->overrides->filterHistory(null, null, null, null); + $this->assertCount(0, $overrides); + $this->handleTest([ + 'reason' => 'idk', + 'door_id' => '1', + 'type' => 1, + 'start' => '2020-04-14', + 'end' => '2020-04-15', + ]); + + $overrides = $this->overrides->filterHistory(null, null, null, null); + $this->response->assertStatus(200); + $this->assertCount(1, $overrides); + $this->assertEquals($this->authUser->getId(), $overrides[0]->getUserId()); + } + + /** + * @test + */ + public function it_fails_creating_an_override_if_door_is_not_found(): void + { + $this->handleTest([ + 'reason' => 'idk', + 'door_id' => '1', + 'type' => 1, + 'start' => '2020-04-14', + 'end' => '2020-04-15', + ]); + + $overrides = $this->overrides->filterHistory(null, null, null, null); + $this->response->assertStatus(422); + $this->assertCount(0, $overrides); + } +} -- GitLab From a330566898c6fcda6228ad526518f996334e1755 Mon Sep 17 00:00:00 2001 From: dakriy Date: Tue, 16 Jun 2020 16:51:10 -0700 Subject: [PATCH 12/38] Add override get tests --- .../Api/Overrides/OverrideGetApiTest.php | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/backend/tests/Feature/Api/Overrides/OverrideGetApiTest.php diff --git a/src/backend/tests/Feature/Api/Overrides/OverrideGetApiTest.php b/src/backend/tests/Feature/Api/Overrides/OverrideGetApiTest.php new file mode 100644 index 00000000..14c0cb03 --- /dev/null +++ b/src/backend/tests/Feature/Api/Overrides/OverrideGetApiTest.php @@ -0,0 +1,68 @@ +overrides = new InMemoryOverridesRepository(); + $this->instance(OverridesRepository::class, $this->overrides); + + $this->authenticate(); + } + + protected function handleTest(string $id): void + { + $this->response = $this->getJson('api/overrides/' . $id . '?api_token=' . $this->authToken); + } + + /** + * @test + */ + public function it_gets_override(): void + { + $o = $this->overrides->addOverride(new Override(0, 'hi', 1, 1, Override::TYPE_OPEN, Carbon::now(), Carbon::now()->addDay())); + + $this->handleTest($o->getId()); + $this->response->assertStatus(200); + + $this->response->assertJson(['override' => ['reason' => 'hi']]); + } + + /** + * @test + */ + public function it_handles_non_existent_override(): void + { + $this->handleTest('non-existent'); + + $this->response->assertStatus(404); + } +} -- GitLab From 760037135f8cb416db4e24bd018e36c744007cc7 Mon Sep 17 00:00:00 2001 From: dakriy Date: Tue, 16 Jun 2020 17:08:01 -0700 Subject: [PATCH 13/38] Add tests for updating override --- .../Overrides/DatabaseOverridesRepository.php | 12 +-- .../Overrides/InMemoryOverridesRepository.php | 4 +- .../Overrides/OverridesRepository.php | 10 +- .../Door/Commands/OverrideCommand.php | 14 +-- .../OverrideCreate/OverrideCreate.php | 6 +- .../OverrideUpdate/OverrideUpdate.php | 16 +--- .../Api/Overrides/OverridesUpdateApiTest.php | 94 +++++++++++++++++++ 7 files changed, 119 insertions(+), 37 deletions(-) create mode 100644 src/backend/tests/Feature/Api/Overrides/OverridesUpdateApiTest.php diff --git a/src/backend/src/Gateways/Overrides/DatabaseOverridesRepository.php b/src/backend/src/Gateways/Overrides/DatabaseOverridesRepository.php index 8d7b9ffd..f24c1bee 100644 --- a/src/backend/src/Gateways/Overrides/DatabaseOverridesRepository.php +++ b/src/backend/src/Gateways/Overrides/DatabaseOverridesRepository.php @@ -119,7 +119,7 @@ QUERY; /** * @inheritDoc */ - public function addOverride(Override $override): ?Override + public function addOverride(Override $override): Override { $o = new \App\Override(); $o->setAttribute('user_id', $override->getUserId()); @@ -133,9 +133,7 @@ QUERY; $o->setCreatedAt($override->getCreatedAt()); } - if (!$o->save()) { - return null; - } + $o->save(); return self::toOverride($o); } @@ -143,7 +141,7 @@ QUERY; /** * @inheritDoc */ - public function updateOverride(string $overrideId, Override $override): ?Override + public function updateOverride(string $overrideId, Override $override): Override { /** @var \App\Override $o */ $o = \App\Override::query()->find($this->castToInt($overrideId)); @@ -159,9 +157,7 @@ QUERY; $o->setAttribute('end', $override->getEnd()); $o->setAttribute('reason', $override->getReason()); - if (!$o->save()) { - return null; - } + $o->save(); return self::toOverride($o); } diff --git a/src/backend/src/Gateways/Overrides/InMemoryOverridesRepository.php b/src/backend/src/Gateways/Overrides/InMemoryOverridesRepository.php index b211f76a..2557a165 100644 --- a/src/backend/src/Gateways/Overrides/InMemoryOverridesRepository.php +++ b/src/backend/src/Gateways/Overrides/InMemoryOverridesRepository.php @@ -60,7 +60,7 @@ class InMemoryOverridesRepository implements OverridesRepository /** * @inheritDoc */ - public function addOverride(Override $override): ?Override + public function addOverride(Override $override): Override { $override = new Override( $override->getId(), @@ -82,7 +82,7 @@ class InMemoryOverridesRepository implements OverridesRepository /** * @inheritDoc */ - public function updateOverride(string $overrideId, Override $override): ?Override + public function updateOverride(string $overrideId, Override $override): Override { $this->overrides = array_filter($this->overrides, static function (Override $o) use ($overrideId) { return !$o->hasIdOf($overrideId); diff --git a/src/backend/src/Gateways/Overrides/OverridesRepository.php b/src/backend/src/Gateways/Overrides/OverridesRepository.php index 5c49e831..e35cd2b5 100644 --- a/src/backend/src/Gateways/Overrides/OverridesRepository.php +++ b/src/backend/src/Gateways/Overrides/OverridesRepository.php @@ -30,20 +30,22 @@ interface OverridesRepository public function activeOverrideForDoorBetween(string $doorId, Carbon $begin, Carbon $end): ?Override; /** + * Persists an override to the application. Only the latest override is ever looked at for scheduling + * * @param \Source\Entities\Override $override - * @return \Source\Entities\Override|null + * @return \Source\Entities\Override */ - public function addOverride(Override $override): ?Override; + public function addOverride(Override $override): Override; /** * Update an override * * @param string $overrideId * @param \Source\Entities\Override $override - * @return \Source\Entities\Override|null + * @return \Source\Entities\Override * @throws \Source\Exceptions\EntityNotFoundException */ - public function updateOverride(string $overrideId, Override $override): ?Override; + public function updateOverride(string $overrideId, Override $override): Override; /** * Retrieves an override diff --git a/src/backend/src/UseCases/Door/Commands/OverrideCommand.php b/src/backend/src/UseCases/Door/Commands/OverrideCommand.php index 38cc75d2..dffd9f31 100644 --- a/src/backend/src/UseCases/Door/Commands/OverrideCommand.php +++ b/src/backend/src/UseCases/Door/Commands/OverrideCommand.php @@ -53,7 +53,7 @@ class OverrideCommand extends Command $length = (int)substr($args, 1); if ($length > 0) { - return $this->overrides->addOverride(new Override( + $this->overrides->addOverride(new Override( 0, "Open mode override created at keypad by {$user->getDisplayName()}.", $user->getId(), @@ -61,7 +61,8 @@ class OverrideCommand extends Command Override::TYPE_OPEN, Carbon::now(), Carbon::now()->addRealMinutes($length) - )) !== null; + )); + return true; } return false; @@ -69,7 +70,7 @@ class OverrideCommand extends Command $length = (int)substr($args, 1); if ($length > 0) { - return $this->overrides->addOverride(new Override( + $this->overrides->addOverride(new Override( 0, "Closed mode override created at keypad by {$user->getDisplayName()}.", $user->getId(), @@ -77,7 +78,8 @@ class OverrideCommand extends Command Override::TYPE_LOCKED, Carbon::now(), Carbon::now()->addRealMinutes($length) - )) !== null; + )); + return true; } return false; @@ -86,7 +88,7 @@ class OverrideCommand extends Command if ($override) { try { - return $this->overrides->updateOverride($override->getId(), new Override( + $this->overrides->updateOverride($override->getId(), new Override( $override->getId(), $override->getReason() . "\nCancelled at keypad by {$user->getDisplayName()}.", $override->getUserId(), @@ -94,7 +96,7 @@ class OverrideCommand extends Command $override->getType(), $override->getStart(), Carbon::now()->subSecond() - )) !== null; + )); } catch (EntityNotFoundException $e) { return false; } diff --git a/src/backend/src/UseCases/Overrides/OverrideCreate/OverrideCreate.php b/src/backend/src/UseCases/Overrides/OverrideCreate/OverrideCreate.php index f3cfec51..9d3a5e1e 100644 --- a/src/backend/src/UseCases/Overrides/OverrideCreate/OverrideCreate.php +++ b/src/backend/src/UseCases/Overrides/OverrideCreate/OverrideCreate.php @@ -67,11 +67,7 @@ class OverrideCreate implements OverrideCreateUseCase ) ); - if (!$override) { - $response->addError('Something went wrong when adding the override'); - } else { - $response->setOverride($override); - } + $response->setOverride($override); } catch (InvalidArgumentException $e) { $response->addError($e->getMessage()); } diff --git a/src/backend/src/UseCases/Overrides/OverrideUpdate/OverrideUpdate.php b/src/backend/src/UseCases/Overrides/OverrideUpdate/OverrideUpdate.php index d84d431b..09b6221b 100644 --- a/src/backend/src/UseCases/Overrides/OverrideUpdate/OverrideUpdate.php +++ b/src/backend/src/UseCases/Overrides/OverrideUpdate/OverrideUpdate.php @@ -48,11 +48,13 @@ class OverrideUpdate implements OverrideUpdateUseCase $reason = $attributes['reason'] ?? $override->getReason(); $start = $attributes['start'] ?? null; $end = $attributes['end'] ?? null; + if ($start) { $start = new Carbon($start); } else { $start = $override->getStart(); } + if ($end) { $end = new Carbon($end); } else { @@ -70,17 +72,7 @@ class OverrideUpdate implements OverrideUpdateUseCase )); $response = new ResponseModel(); - - if (!$override) { - $response->addError('Something went wrong when adding the override'); - } else { - $response->setOverride($override); - } - - if ($response->hasError()) { - $presenter->presentError($response); - } else { - $presenter->present($response); - } + $response->setOverride($override); + $presenter->present($response); } } diff --git a/src/backend/tests/Feature/Api/Overrides/OverridesUpdateApiTest.php b/src/backend/tests/Feature/Api/Overrides/OverridesUpdateApiTest.php new file mode 100644 index 00000000..d0fdf16a --- /dev/null +++ b/src/backend/tests/Feature/Api/Overrides/OverridesUpdateApiTest.php @@ -0,0 +1,94 @@ +overrides = new InMemoryOverridesRepository(); + $this->instance(OverridesRepository::class, $this->overrides); + + $this->authenticate(); + } + + protected function handleTest(string $id, array $data): void + { + $this->response = $this->patchJson( + 'api/overrides/' . $id, + array_merge(['api_token' => $this->authToken], $data) + ); + } + + /** + * @test + */ + public function it_updates_an_override(): void + { + $o = $this->overrides->addOverride(new Override(0, 'hi', 1, 1, Override::TYPE_OPEN, Carbon::now(), Carbon::now()->addDay())); + + $this->handleTest($o->getId(), ['reason' => 'new reason boio']); + + $this->response->assertStatus(200); + + $overrides = $this->overrides->filterHistory(null, null, null, null); + $this->assertCount(1, $overrides); + + $this->assertEquals('new reason boio', $overrides[0]->getReason()); + $this->response->assertJson(['override' => ['reason' => 'new reason boio', 'user_id' => 1]]); + } + + /** + * @test + */ + public function it_updates_many_attributes(): void + { + $o = $this->overrides->addOverride(new Override(0, 'hi', 1, 1, Override::TYPE_OPEN, Carbon::now(), Carbon::now()->addDay())); + + $this->handleTest($o->getId(), ['reason' => 'new reason boio', 'start' => '2020-01-02', 'end' => '2020-02-03']); + + $this->response->assertStatus(200); + + $overrides = $this->overrides->filterHistory(null, null, null, null); + $this->assertCount(1, $overrides); + + $this->assertEquals('new reason boio', $overrides[0]->getReason()); + $this->response->assertJson(['override' => ['reason' => 'new reason boio', 'user_id' => 1, 'start' => '2020-01-02T00:00:00-08:00', 'end' => '2020-02-03T00:00:00-08:00']]); + } + + /** + * @test + */ + public function it_cannot_update_non_existent_overrides(): void + { + $this->handleTest('lol', []); + + $this->response->assertStatus(404); + } +} -- GitLab From cb58d7d1f686c590aea7f4295b81b1e4f2c298f3 Mon Sep 17 00:00:00 2001 From: dakriy Date: Tue, 16 Jun 2020 17:21:29 -0700 Subject: [PATCH 14/38] Overrides get tests --- .../Http/Controllers/OverridesController.php | 8 +- .../Api/Overrides/OverridesGetApiTest.php | 140 ++++++++++++++++++ 2 files changed, 144 insertions(+), 4 deletions(-) create mode 100644 src/backend/tests/Feature/Api/Overrides/OverridesGetApiTest.php diff --git a/src/backend/app/Http/Controllers/OverridesController.php b/src/backend/app/Http/Controllers/OverridesController.php index aa66668a..5fbcae5a 100644 --- a/src/backend/app/Http/Controllers/OverridesController.php +++ b/src/backend/app/Http/Controllers/OverridesController.php @@ -153,10 +153,10 @@ class OverridesController extends ApiController $this->authorizer->protect(Permissions::LOGS_READ); $this->validate($this->request, [ - 'start' => 'date', - 'end' => 'date', - 'door_id' => 'integer', - 'user_id' => 'integer', + 'start' => 'nullable|date', + 'end' => 'nullable|date', + 'door_id' => 'nullable|integer', + 'user_id' => 'nullable|integer', ]); $presenter = new ApiPresenter(); diff --git a/src/backend/tests/Feature/Api/Overrides/OverridesGetApiTest.php b/src/backend/tests/Feature/Api/Overrides/OverridesGetApiTest.php new file mode 100644 index 00000000..3b75186b --- /dev/null +++ b/src/backend/tests/Feature/Api/Overrides/OverridesGetApiTest.php @@ -0,0 +1,140 @@ +overrides = new InMemoryOverridesRepository(); + $this->instance(OverridesRepository::class, $this->overrides); + + $this->authenticate(); + } + + /** + * @param string|null $start + * @param string|null $end + * @param string|null $doorId + * @param string|null $userId + */ + protected function handleTest(?string $start, ?string $end, ?string $doorId, ?string $userId): void + { + $this->response = $this->getJson( + 'api/overrides?api_token=' . $this->authToken + . '&start=' . $start + . '&end=' . $end + . '&door_id=' . $doorId + . '&user_id=' . $userId + ); + } + + protected function createBasicOverrides(): void + { + $this->overrides->addOverride(new Override( + 1, + 'reason 1', + 2, + 3, + Override::TYPE_OPEN, + new Carbon('2020-03-22'), + new Carbon('2020-03-23') + )); + $this->overrides->addOverride(new Override( + 2, + 'reason 2', + 3, + 2, + Override::TYPE_OPEN, + new Carbon('2020-03-25'), + new Carbon('2020-03-26') + )); + + } + + /** + * @test + */ + public function overrides_filter_by_start(): void + { + $this->createBasicOverrides(); + + $this->handleTest('2020-03-24', null, null, null); + + $this->response->assertStatus(200); + + $this->response->assertJsonCount(1, 'data'); + $this->assertEquals(2, $this->response->json('data')[0]['id']); + } + + /** + * @test + */ + public function overrides_filter_by_end(): void + { + $this->createBasicOverrides(); + + $this->handleTest(null, '2020-03-24', null, null); + + $this->response->assertStatus(200); + + $this->response->assertJsonCount(1, 'data'); + $this->assertEquals(1, $this->response->json('data')[0]['id']); + } + + /** + * @test + */ + public function overrides_filter_by_user(): void + { + $this->createBasicOverrides(); + + $this->handleTest(null, null, null, 3); + + $this->response->assertStatus(200); + + $this->response->assertJsonCount(1, 'data'); + $this->assertEquals(2, $this->response->json('data')[0]['id']); + } + + /** + * @test + */ + public function overrides_filter_by_door(): void + { + $this->createBasicOverrides(); + + $this->handleTest(null, null, 3, null); + + $this->response->assertStatus(200); + + $this->response->assertJsonCount(1, 'data'); + $this->assertEquals(1, $this->response->json('data')[0]['id']); + } +} -- GitLab From 1674fe361266aa9efed141e1489273137414eb43 Mon Sep 17 00:00:00 2001 From: dakriy Date: Tue, 16 Jun 2020 17:34:18 -0700 Subject: [PATCH 15/38] Add proper error checking on override creation and updating --- .../Overrides/DatabaseOverridesRepository.php | 32 +++++++++-- .../Overrides/OverridesRepository.php | 1 + .../tests/Database/OverrideDatabaseTest.php | 55 +++++++++++++++++++ 3 files changed, 84 insertions(+), 4 deletions(-) diff --git a/src/backend/src/Gateways/Overrides/DatabaseOverridesRepository.php b/src/backend/src/Gateways/Overrides/DatabaseOverridesRepository.php index f24c1bee..98ff54e8 100644 --- a/src/backend/src/Gateways/Overrides/DatabaseOverridesRepository.php +++ b/src/backend/src/Gateways/Overrides/DatabaseOverridesRepository.php @@ -6,11 +6,15 @@ namespace Source\Gateways\Overrides; use Carbon\Carbon; use Source\Sanitize\CastsTo; use Source\Entities\Override; +use Illuminate\Support\Facades\Log; +use Illuminate\Database\QueryException; use Illuminate\Database\ConnectionInterface; use Source\Exceptions\EntityNotFoundException; class DatabaseOverridesRepository implements OverridesRepository { + protected const FOREIGN_KEY_VIOLATION = '23503'; + use CastsTo; /** @@ -78,9 +82,9 @@ class DatabaseOverridesRepository implements OverridesRepository if ($begin && $end) { $query->whereRaw('((:BEGIN, :END) OVERLAPS ("start", "end"))', [':BEGIN' => $begin, ':END' => $end]); - } elseif ($begin) { + } else if ($begin) { $query->where('end', '>', $begin); - } elseif ($end) { + } else if ($end) { $query->where('start', '<', $end); } @@ -133,7 +137,17 @@ QUERY; $o->setCreatedAt($override->getCreatedAt()); } - $o->save(); + try { + $o->save(); + } catch (QueryException $e) { + if ($e->getCode() === self::FOREIGN_KEY_VIOLATION) { + throw new EntityNotFoundException('Cannot create override because the specified user or door does not exist.'); + } + + Log::error('Failed creating override: ' . $e); + + throw $e; + } return self::toOverride($o); } @@ -157,7 +171,17 @@ QUERY; $o->setAttribute('end', $override->getEnd()); $o->setAttribute('reason', $override->getReason()); - $o->save(); + try { + $o->save(); + } catch (QueryException $e) { + if ($e->getCode() === self::FOREIGN_KEY_VIOLATION) { + throw new EntityNotFoundException('Cannot update override because the referenced user or door does not exist.'); + } + + Log::error('Failed updating override: ' . $e); + + throw $e; + } return self::toOverride($o); } diff --git a/src/backend/src/Gateways/Overrides/OverridesRepository.php b/src/backend/src/Gateways/Overrides/OverridesRepository.php index e35cd2b5..3425fa86 100644 --- a/src/backend/src/Gateways/Overrides/OverridesRepository.php +++ b/src/backend/src/Gateways/Overrides/OverridesRepository.php @@ -34,6 +34,7 @@ interface OverridesRepository * * @param \Source\Entities\Override $override * @return \Source\Entities\Override + * @throws \Source\Exceptions\EntityNotFoundException */ public function addOverride(Override $override): Override; diff --git a/src/backend/tests/Database/OverrideDatabaseTest.php b/src/backend/tests/Database/OverrideDatabaseTest.php index 1df03cc9..adb7546a 100644 --- a/src/backend/tests/Database/OverrideDatabaseTest.php +++ b/src/backend/tests/Database/OverrideDatabaseTest.php @@ -10,6 +10,7 @@ use Tests\DatabaseTestCase; use Source\Entities\Override; use Illuminate\Support\Facades\DB; use Source\Entities\HashedSearchable; +use Source\Exceptions\EntityNotFoundException; use Source\Gateways\Doors\DatabaseDoorsRepository; use Source\Gateways\Users\DatabaseUsersRepository; use Source\Gateways\Overrides\DatabaseOverridesRepository; @@ -69,6 +70,7 @@ class OverrideDatabaseTest extends DatabaseTestCase /** * @test * @throws \Source\Exceptions\EntityExistsException + * @throws \Source\Exceptions\EntityNotFoundException */ public function it_can_create_and_find_overrides(): void { @@ -102,6 +104,7 @@ class OverrideDatabaseTest extends DatabaseTestCase /** * @test * @throws \Source\Exceptions\EntityExistsException + * @throws \Source\Exceptions\EntityNotFoundException */ public function it_gets_active_override_for_door(): void { @@ -131,4 +134,56 @@ class OverrideDatabaseTest extends DatabaseTestCase // It picks the latest override $this->assertEquals(Override::TYPE_OPEN, $this->repository->activeOverrideForDoorBetween($d1->getId(), Carbon::now(), Carbon::now()->addHours(3))->getType()); } + + /** + * @test + * @throws \Source\Exceptions\EntityExistsException + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_throws_an_exception_on_insert_of_row_referencing_invalid_user(): void + { + $d = $this->createDoor('d1'); + $this->expectException(EntityNotFoundException::class); + $this->repository->addOverride(new Override(0, 'the reason', 269141, $d->getId(), Override::TYPE_OPEN, Carbon::now(), Carbon::now())); + } + + /** + * @test + * @throws \Source\Exceptions\EntityExistsException + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_throws_an_exception_on_insert_of_row_referencing_invalid_door(): void + { + $u = $this->createUser(); + $this->expectException(EntityNotFoundException::class); + $this->repository->addOverride(new Override(0, 'the reason', $u->getId(), 270370, Override::TYPE_OPEN, Carbon::now(), Carbon::now())); + } + + /** + * @test + * @throws \Source\Exceptions\EntityExistsException + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_throws_exception_on_update_with_invalid_door(): void + { + $d = $this->createDoor('d1'); + $u = $this->createUser('u1'); + $id = $this->repository->addOverride(new Override(0, 'the reason', $u->getId(), $d->getId(), Override::TYPE_OPEN, Carbon::now(), Carbon::now()))->getId(); + $this->expectException(EntityNotFoundException::class); + $this->repository->updateOverride($id, new Override(0, 'the reason', $u->getId(), 268467, Override::TYPE_OPEN, Carbon::now(), Carbon::now())); + } + + /** + * @test + * @throws \Source\Exceptions\EntityExistsException + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_throws_exception_on_update_with_invalid_user(): void + { + $d = $this->createDoor('d1'); + $u = $this->createUser('u1'); + $id = $this->repository->addOverride(new Override(0, 'the reason', $u->getId(), $d->getId(), Override::TYPE_OPEN, Carbon::now(), Carbon::now()))->getId(); + $this->expectException(EntityNotFoundException::class); + $this->repository->updateOverride($id, new Override(0, 'the reason', 267270, $d->getId(), Override::TYPE_OPEN, Carbon::now(), Carbon::now())); + } } -- GitLab From 2b82e7ec5f26b2e5e9ab03ec0e84ea800ba01ab0 Mon Sep 17 00:00:00 2001 From: dakriy Date: Tue, 16 Jun 2020 17:34:54 -0700 Subject: [PATCH 16/38] fix code styles --- .../src/Gateways/Overrides/DatabaseOverridesRepository.php | 4 ++-- .../tests/Feature/Api/Overrides/OverrideGetApiTest.php | 1 - .../tests/Feature/Api/Overrides/OverridesCreateApiTest.php | 1 - .../tests/Feature/Api/Overrides/OverridesGetApiTest.php | 2 -- .../tests/Feature/Api/Overrides/OverridesUpdateApiTest.php | 1 - 5 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/backend/src/Gateways/Overrides/DatabaseOverridesRepository.php b/src/backend/src/Gateways/Overrides/DatabaseOverridesRepository.php index 98ff54e8..e8de2c5e 100644 --- a/src/backend/src/Gateways/Overrides/DatabaseOverridesRepository.php +++ b/src/backend/src/Gateways/Overrides/DatabaseOverridesRepository.php @@ -82,9 +82,9 @@ class DatabaseOverridesRepository implements OverridesRepository if ($begin && $end) { $query->whereRaw('((:BEGIN, :END) OVERLAPS ("start", "end"))', [':BEGIN' => $begin, ':END' => $end]); - } else if ($begin) { + } elseif ($begin) { $query->where('end', '>', $begin); - } else if ($end) { + } elseif ($end) { $query->where('start', '<', $end); } diff --git a/src/backend/tests/Feature/Api/Overrides/OverrideGetApiTest.php b/src/backend/tests/Feature/Api/Overrides/OverrideGetApiTest.php index 14c0cb03..6fa41b71 100644 --- a/src/backend/tests/Feature/Api/Overrides/OverrideGetApiTest.php +++ b/src/backend/tests/Feature/Api/Overrides/OverrideGetApiTest.php @@ -3,7 +3,6 @@ namespace Tests\Feature\Api\Overrides; - use Carbon\Carbon; use Source\Entities\Override; use Illuminate\Testing\TestResponse; diff --git a/src/backend/tests/Feature/Api/Overrides/OverridesCreateApiTest.php b/src/backend/tests/Feature/Api/Overrides/OverridesCreateApiTest.php index 99baa03f..b1a5cd8a 100644 --- a/src/backend/tests/Feature/Api/Overrides/OverridesCreateApiTest.php +++ b/src/backend/tests/Feature/Api/Overrides/OverridesCreateApiTest.php @@ -3,7 +3,6 @@ namespace Tests\Feature\Api\Overrides; - use Source\Entities\Door; use Illuminate\Testing\TestResponse; use Source\Entities\HashedSearchable; diff --git a/src/backend/tests/Feature/Api/Overrides/OverridesGetApiTest.php b/src/backend/tests/Feature/Api/Overrides/OverridesGetApiTest.php index 3b75186b..32161240 100644 --- a/src/backend/tests/Feature/Api/Overrides/OverridesGetApiTest.php +++ b/src/backend/tests/Feature/Api/Overrides/OverridesGetApiTest.php @@ -3,7 +3,6 @@ namespace Tests\Feature\Api\Overrides; - use Carbon\Carbon; use Source\Entities\Override; use Illuminate\Testing\TestResponse; @@ -75,7 +74,6 @@ class OverridesGetApiTest extends AuthenticatesWithApplicationTestCase new Carbon('2020-03-25'), new Carbon('2020-03-26') )); - } /** diff --git a/src/backend/tests/Feature/Api/Overrides/OverridesUpdateApiTest.php b/src/backend/tests/Feature/Api/Overrides/OverridesUpdateApiTest.php index d0fdf16a..e14ed496 100644 --- a/src/backend/tests/Feature/Api/Overrides/OverridesUpdateApiTest.php +++ b/src/backend/tests/Feature/Api/Overrides/OverridesUpdateApiTest.php @@ -3,7 +3,6 @@ namespace Tests\Feature\Api\Overrides; - use Carbon\Carbon; use Source\Entities\Override; use Illuminate\Testing\TestResponse; -- GitLab From e194921ef9c9055a48e73212b44abd9acd4f3d2c Mon Sep 17 00:00:00 2001 From: dakriy Date: Tue, 16 Jun 2020 18:46:57 -0700 Subject: [PATCH 17/38] Add token get tests --- .../app/Http/Controllers/TokensController.php | 4 +- .../Tokens/DatabaseTokensRepository.php | 49 +++++--- .../Tokens/InMemoryTokensRepository.php | 15 ++- .../Feature/Api/Tokens/TokenGetApiTest.php | 57 +++++++++ .../Feature/Api/Tokens/TokensGetApiTest.php | 115 ++++++++++++++++++ .../AuthenticatesWithApplicationTestCase.php | 2 +- .../Users/Authenticate/AttemptUseCaseTest.php | 4 +- .../Users/Authenticate/SamlUseCaseTest.php | 6 +- 8 files changed, 224 insertions(+), 28 deletions(-) create mode 100644 src/backend/tests/Feature/Api/Tokens/TokenGetApiTest.php create mode 100644 src/backend/tests/Feature/Api/Tokens/TokensGetApiTest.php diff --git a/src/backend/app/Http/Controllers/TokensController.php b/src/backend/app/Http/Controllers/TokensController.php index b2b7af9b..ab530100 100644 --- a/src/backend/app/Http/Controllers/TokensController.php +++ b/src/backend/app/Http/Controllers/TokensController.php @@ -46,8 +46,8 @@ class TokensController extends ApiController $this->authorizer->protect(Permissions::MANAGE_USERS); $this->validate($this->request, [ - 'user_id' => 'integer', - 'valid_at' => 'date', + 'user_id' => 'nullable|integer', + 'valid_at' => 'nullable|date', ]); $presenter = new AllTokensAPIPresenter(); diff --git a/src/backend/src/Gateways/Tokens/DatabaseTokensRepository.php b/src/backend/src/Gateways/Tokens/DatabaseTokensRepository.php index 8889cf9f..d49c5378 100644 --- a/src/backend/src/Gateways/Tokens/DatabaseTokensRepository.php +++ b/src/backend/src/Gateways/Tokens/DatabaseTokensRepository.php @@ -3,38 +3,56 @@ namespace Source\Gateways\Tokens; -use App\User; use Carbon\Carbon; use Source\Entities\Token; use Illuminate\Support\Str; use Source\Sanitize\CastsTo; use Source\Entities\RawToken; +use Illuminate\Support\Facades\Log; use Source\Entities\HashedSearchable; +use Illuminate\Database\QueryException; use Illuminate\Database\Eloquent\Builder; use Source\Exceptions\EntityNotFoundException; class DatabaseTokensRepository implements TokensRepository { + protected const FOREIGN_KEY_VIOLATION = '23503'; + use CastsTo; /** - * @inheritDoc + * @param \App\Token $dbToken + * @param \Source\Entities\Token $token + * @throws \Source\Exceptions\EntityNotFoundException */ - public function create(Token $token): Token + protected function saveToken(\App\Token $dbToken, Token $token): void { - /** @var \App\User|null $user */ - $user = User::query()->find($token->getUserId()); - - if (!$user) { - throw new EntityNotFoundException('Cannot create token for non existent user'); - } - - $dbToken = new \App\Token(); $dbToken->setAttribute('name', $token->getName()); $dbToken->setAttribute('user_id', $token->getUserId()); $dbToken->setAttribute('api_token', $token->getToken()->getHash()); $dbToken->setAttribute('expires_at', $token->getExpiresAt()); - $dbToken->save(); + + try { + $dbToken->save(); + } catch (QueryException $e) { + if ($e->getCode() === self::FOREIGN_KEY_VIOLATION) { + throw new EntityNotFoundException('Cannot save token for non existent user'); + } + + Log::error('Cannot save token: ' . $e); + + throw $e; + } + } + + /** + * @inheritDoc + */ + public function create(Token $token): Token + { + $dbToken = new \App\Token(); + + $this->saveToken($dbToken, $token); return self::dbTokenToToken($dbToken); } @@ -63,13 +81,10 @@ class DatabaseTokensRepository implements TokensRepository $dbToken = \App\Token::query()->find($this->castToInt($tokenId)); if (!$dbToken) { - throw new EntityNotFoundException(); + throw new EntityNotFoundException('Token with id "' . $tokenId . '" not found.'); } - $dbToken->setAttribute('name', $token->getName()); - $dbToken->setAttribute('expired_at', $token->getExpiresAt()); - $dbToken->setAttribute('api_token', $token->getToken()->getHash()); - $dbToken->save(); + $this->saveToken($dbToken, $token); return self::dbTokenToToken($dbToken); } diff --git a/src/backend/src/Gateways/Tokens/InMemoryTokensRepository.php b/src/backend/src/Gateways/Tokens/InMemoryTokensRepository.php index e088785f..525ce53b 100644 --- a/src/backend/src/Gateways/Tokens/InMemoryTokensRepository.php +++ b/src/backend/src/Gateways/Tokens/InMemoryTokensRepository.php @@ -36,6 +36,7 @@ class InMemoryTokensRepository implements TokensRepository public function createLoginToken(string $userId, string $salt): RawToken { $raw = self::generateTokenString(); + return new RawToken($raw, $this->create(new Token( 0, $userId, @@ -50,7 +51,7 @@ class InMemoryTokensRepository implements TokensRepository */ public function update(string $tokenId, Token $token): Token { - foreach ($this->tokens as $key=>$tok) { + foreach ($this->tokens as $key => $tok) { if ($tok->hasIdOf($tokenId)) { $this->tokens[$key] = $token; @@ -69,10 +70,10 @@ class InMemoryTokensRepository implements TokensRepository public function filter(?string $userId = null, ?Carbon $validAt = null): array { return array_values(array_filter($this->tokens, static function (Token $token) use ($userId, $validAt) { - $include = true; + $include = $token->getName() !== null; if ($validAt) { - $include = $token->isValidAtTime($validAt); + $include = $include && $token->isValidAtTime($validAt); } if ($userId !== null) { @@ -142,4 +143,12 @@ class InMemoryTokensRepository implements TokensRepository return null; } + + /** + * @return \Source\Entities\Token[] + */ + public function getAll(): array + { + return $this->tokens; + } } diff --git a/src/backend/tests/Feature/Api/Tokens/TokenGetApiTest.php b/src/backend/tests/Feature/Api/Tokens/TokenGetApiTest.php new file mode 100644 index 00000000..00ad355e --- /dev/null +++ b/src/backend/tests/Feature/Api/Tokens/TokenGetApiTest.php @@ -0,0 +1,57 @@ +authenticate(); + } + + protected function handleTest(string $id): void + { + $this->response = $this->getJson('api/tokens/' . $id . '?api_token=' . $this->authToken); + } + + /** + * @test + */ + public function it_errors_on_invalid_token(): void + { + $this->handleTest('hello there'); + + $this->response->assertStatus(404); + } + + /** + * @test + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_gets_a_valid_token(): void + { + $token = $this->tokens->create(new Token(0, 1, new HashedSearchable(''))); + $this->handleTest($token->getId()); + $this->assertEquals($token->getName(), $this->response->json('token')['name']); + $this->assertEquals($token->getId(), $this->response->json('token')['id']); + } +} diff --git a/src/backend/tests/Feature/Api/Tokens/TokensGetApiTest.php b/src/backend/tests/Feature/Api/Tokens/TokensGetApiTest.php new file mode 100644 index 00000000..4ba9fe5b --- /dev/null +++ b/src/backend/tests/Feature/Api/Tokens/TokensGetApiTest.php @@ -0,0 +1,115 @@ +authenticate(); + } + + protected function handleTest(?string $userId, ?string $validAt): void + { + $this->response = $this->getJson( + 'api/tokens?api_token=' . $this->authToken + . '&user_id=' . $userId + . '&valid_at=' . $validAt + ); + } + + /** + * @test + */ + public function it_gets_no_tokens(): void + { + $this->handleTest(null, null); + $this->response->assertJsonCount(0, 'data'); + } + + /** + * @test + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_scopes_to_user_id(): void + { + $this->tokens->create(new Token(0, 1, new HashedSearchable(''), 'name', null)); + $this->tokens->create(new Token(10, 2, new HashedSearchable(''), 'name 2', null)); + + $this->handleTest(2, null); + + $this->response->assertStatus(200); + + $this->response->assertJsonCount(1, 'data'); + $this->assertEquals(10, $this->response->json('data')[0]['id']); + } + + /** + * @test + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_scopes_to_valid_date(): void + { + $this->tokens->create(new Token(0, 1, new HashedSearchable(''), 'name', new Carbon('2019-11-12'))); + $this->tokens->create(new Token(10, 2, new HashedSearchable(''), 'name 2', new Carbon('2020-10-10'))); + + $this->handleTest(null, '2020-05-29'); + + $this->response->assertStatus(200); + + $this->response->assertJsonCount(1, 'data'); + $this->assertEquals(10, $this->response->json('data')[0]['id']); + } + + /** + * @test + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_scopes_to_date_and_user_id(): void + { + $id = $this->tokens->create(new Token(0, 1, new HashedSearchable(''), 'name', new Carbon('2019-11-12')))->getId(); + $this->tokens->create(new Token(10, 2, new HashedSearchable(''), 'name 2', new Carbon('2020-10-10'))); + + $this->handleTest(1, '2019-05-29'); + + $this->response->assertStatus(200); + + $this->response->assertJsonCount(1, 'data'); + $this->assertEquals($id, $this->response->json('data')[0]['id']); + } + + /** + * @test + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_does_not_have_to_scop(): void + { + $this->tokens->create(new Token(0, 1, new HashedSearchable(''), 'name', new Carbon('2019-11-12'))); + $this->tokens->create(new Token(10, 2, new HashedSearchable(''), 'name 2', new Carbon('2020-10-10'))); + + $this->handleTest(null, null); + + $this->response->assertStatus(200); + + $this->response->assertJsonCount(2, 'data'); + } +} diff --git a/src/backend/tests/Feature/AuthenticatesWithApplicationTestCase.php b/src/backend/tests/Feature/AuthenticatesWithApplicationTestCase.php index efc5dded..b2917655 100644 --- a/src/backend/tests/Feature/AuthenticatesWithApplicationTestCase.php +++ b/src/backend/tests/Feature/AuthenticatesWithApplicationTestCase.php @@ -69,7 +69,7 @@ class AuthenticatesWithApplicationTestCase extends TestCase $this->usersRepository->create($this->authUser); $this->authorizer->setCurrentUserId($this->authUser->getId()); - $this->tokens->create(new Token(1, 1, HashedSearchable::hash(config('app.key'), self::VALID_TOKEN), 'name')); + $this->tokens->create(new Token(1, 1, HashedSearchable::hash(config('app.key'), self::VALID_TOKEN))); $this->authToken = self::VALID_TOKEN; } diff --git a/src/backend/tests/Unit/Source/UseCases/Users/Authenticate/AttemptUseCaseTest.php b/src/backend/tests/Unit/Source/UseCases/Users/Authenticate/AttemptUseCaseTest.php index e8012d81..cbd8495a 100644 --- a/src/backend/tests/Unit/Source/UseCases/Users/Authenticate/AttemptUseCaseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Users/Authenticate/AttemptUseCaseTest.php @@ -107,8 +107,8 @@ class AttemptUseCaseTest extends UseCaseBaseTest $this->handleTest(); - $this->assertCount(1, $this->tokens->filter()); - $token = $this->tokens->filter()[0]; + $this->assertCount(1, $this->tokens->getAll()); + $token = $this->tokens->getAll()[0]; $this->assertLessThan(Carbon::now()->addHours(25), $token->getExpiresAt()); $this->assertGreaterThan(Carbon::now()->subHours(23), $token->getExpiresAt()); $this->assertEquals($user->getId(), $token->getUserId()); diff --git a/src/backend/tests/Unit/Source/UseCases/Users/Authenticate/SamlUseCaseTest.php b/src/backend/tests/Unit/Source/UseCases/Users/Authenticate/SamlUseCaseTest.php index f220f657..1629126b 100644 --- a/src/backend/tests/Unit/Source/UseCases/Users/Authenticate/SamlUseCaseTest.php +++ b/src/backend/tests/Unit/Source/UseCases/Users/Authenticate/SamlUseCaseTest.php @@ -111,7 +111,7 @@ class SamlUseCaseTest extends UseCaseBaseTest $token = HashedSearchable::hash(self::SALT, self::VALID_TOKEN); $this->tokens->create(new Token(0, $user->getId(), $token)); $this->useCase->samlLogout(self::VALID_TOKEN); - $tok = $this->tokens->filter()[0]; + $tok = $this->tokens->getAll()[0]; $this->assertTrue($tok->isInvalid()); } @@ -185,8 +185,8 @@ class SamlUseCaseTest extends UseCaseBaseTest $this->handleLoginTest($samlUser); - $this->assertCount(1, $this->tokens->filter()); - $token = $this->tokens->filter()[0]; + $this->assertCount(1, $this->tokens->getAll()); + $token = $this->tokens->getAll()[0]; $this->assertLessThan(Carbon::now()->addHours(25), $token->getExpiresAt()); $this->assertGreaterThan(Carbon::now()->subHours(23), $token->getExpiresAt()); $this->assertEquals($user->getId(), $token->getUserId()); -- GitLab From d8c51ae41a7486a49fb678dc116511fd0a5ee435 Mon Sep 17 00:00:00 2001 From: dakriy Date: Tue, 16 Jun 2020 18:54:27 -0700 Subject: [PATCH 18/38] Create token tests --- .../Tokens/CreateToken/CreateToken.php | 2 +- .../Api/Tokens/TokensCreateApiTest.php | 57 +++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 src/backend/tests/Feature/Api/Tokens/TokensCreateApiTest.php diff --git a/src/backend/src/UseCases/Tokens/CreateToken/CreateToken.php b/src/backend/src/UseCases/Tokens/CreateToken/CreateToken.php index d5cda97c..f14279f1 100644 --- a/src/backend/src/UseCases/Tokens/CreateToken/CreateToken.php +++ b/src/backend/src/UseCases/Tokens/CreateToken/CreateToken.php @@ -36,7 +36,7 @@ class CreateToken implements CreateTokenUseCase { $name = $attributes['name'] ?? null; if (!$name) { - throw new InvalidArgumentException('Name cannot be null'); + throw new InvalidArgumentException('Name cannot be empty'); } $tokenString = $this->tokens::generateTokenString(); diff --git a/src/backend/tests/Feature/Api/Tokens/TokensCreateApiTest.php b/src/backend/tests/Feature/Api/Tokens/TokensCreateApiTest.php new file mode 100644 index 00000000..3ce20b4a --- /dev/null +++ b/src/backend/tests/Feature/Api/Tokens/TokensCreateApiTest.php @@ -0,0 +1,57 @@ +authenticate(); + } + + /** + * @param array $data + */ + protected function handleTest(array $data): void + { + $this->response = $this->postJson('api/tokens', array_merge( + ['api_token' => $this->authToken], + $data + )); + } + + /** + * @test + */ + public function it_creates_a_token(): void + { + $this->handleTest(['name' => 'general kenobi', 'user_id' => 1]); + $this->response->assertStatus(200); + $this->response->assertJson(['token' => ['name' => 'general kenobi', 'user_id' => 1]]); + $tokens = $this->tokens->filter(); + $this->assertCount(1, $tokens); + $token = $tokens[0]; + $this->assertEquals( + HashedSearchable::hash(config('app.key'), $this->response->json('token_string')), + $token->getToken() + ); + } +} -- GitLab From c03ce1c69ecb36426d47dd23a9b0025c0408dcc5 Mon Sep 17 00:00:00 2001 From: dakriy Date: Tue, 16 Jun 2020 19:07:48 -0700 Subject: [PATCH 19/38] make tests for update token --- .../Tokens/UpdateToken/UpdateToken.php | 2 +- .../Api/Tokens/TokensUpdateApiTest.php | 83 +++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 src/backend/tests/Feature/Api/Tokens/TokensUpdateApiTest.php diff --git a/src/backend/src/UseCases/Tokens/UpdateToken/UpdateToken.php b/src/backend/src/UseCases/Tokens/UpdateToken/UpdateToken.php index 650d81a8..22f2249b 100644 --- a/src/backend/src/UseCases/Tokens/UpdateToken/UpdateToken.php +++ b/src/backend/src/UseCases/Tokens/UpdateToken/UpdateToken.php @@ -33,7 +33,7 @@ class UpdateToken implements UpdateTokenUseCase } $expiresAt = null; - if (isset($attributes['expires_at'])) { + if (array_key_exists('expires_at', $attributes)) { $expiresAt = $this->liberalCastToCarbon($expiresAt); } else { $expiresAt = $token->getExpiresAt(); diff --git a/src/backend/tests/Feature/Api/Tokens/TokensUpdateApiTest.php b/src/backend/tests/Feature/Api/Tokens/TokensUpdateApiTest.php new file mode 100644 index 00000000..aeff71d7 --- /dev/null +++ b/src/backend/tests/Feature/Api/Tokens/TokensUpdateApiTest.php @@ -0,0 +1,83 @@ +authenticate(); + } + + protected function handleTest(string $id, array $data): void + { + $this->response = $this->patchJson( + 'api/tokens/' . $id, + array_merge(['api_token' => $this->authToken], $data) + ); + } + + /** + * @test + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_updates_a_token(): void + { + $token = $this->tokens->create(new Token(0, 1, new HashedSearchable(''), 'name')); + + $this->handleTest($token->getId(), ['name' => 'new name']); + + $this->response->assertStatus(200); + + $new = $this->tokens->get($token->getId()); + $this->assertEquals('new name', $new->getName()); + $this->response->assertJson(['token' => ['name' => 'new name']]); + } + + /** + * @test + */ + public function it_cannot_update_non_existent_token(): void + { + $this->handleTest('hi', []); + + $this->response->assertStatus(404); + } + + /** + * @test + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_can_clear_expires(): void + { + $token = $this->tokens->create(new Token(0, 1, new HashedSearchable(''), 'name', Carbon::now())); + + $this->handleTest($token->getId(), ['expires_at' => null]); + + $this->response->assertStatus(200); + $this->response->assertJson(['token' => ['expires_at' => null]]); + $this->assertCount(1, $this->tokens->filter()); + $token = $this->tokens->filter()[0]; + $this->assertNull($token->getExpiresAt()); + } +} -- GitLab From 4f10987cea80b44c435d20bd830037a43e7c20b1 Mon Sep 17 00:00:00 2001 From: dakriy Date: Tue, 16 Jun 2020 19:12:44 -0700 Subject: [PATCH 20/38] Make tokens expire tests --- .../Tokens/DatabaseTokensRepository.php | 2 +- .../Tokens/InMemoryTokensRepository.php | 3 + .../Api/Tokens/TokensExpireApiTest.php | 63 +++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/backend/tests/Feature/Api/Tokens/TokensExpireApiTest.php diff --git a/src/backend/src/Gateways/Tokens/DatabaseTokensRepository.php b/src/backend/src/Gateways/Tokens/DatabaseTokensRepository.php index d49c5378..ff8d62a9 100644 --- a/src/backend/src/Gateways/Tokens/DatabaseTokensRepository.php +++ b/src/backend/src/Gateways/Tokens/DatabaseTokensRepository.php @@ -184,7 +184,7 @@ class DatabaseTokensRepository implements TokensRepository $dbToken = \App\Token::query()->find($this->castToInt($tokenId)); if (!$dbToken) { - throw new EntityNotFoundException(); + throw new EntityNotFoundException('Token not found.'); } $token = self::dbTokenToToken($dbToken); diff --git a/src/backend/src/Gateways/Tokens/InMemoryTokensRepository.php b/src/backend/src/Gateways/Tokens/InMemoryTokensRepository.php index 525ce53b..ecef1e61 100644 --- a/src/backend/src/Gateways/Tokens/InMemoryTokensRepository.php +++ b/src/backend/src/Gateways/Tokens/InMemoryTokensRepository.php @@ -126,8 +126,11 @@ class InMemoryTokensRepository implements TokensRepository foreach ($this->tokens as $token) { if ($token->hasIdOf($tokenId) && $token->isValid()) { $token->setExpiresAt(Carbon::now()); + return; } } + + throw new EntityNotFoundException(); } /** diff --git a/src/backend/tests/Feature/Api/Tokens/TokensExpireApiTest.php b/src/backend/tests/Feature/Api/Tokens/TokensExpireApiTest.php new file mode 100644 index 00000000..9f3a18db --- /dev/null +++ b/src/backend/tests/Feature/Api/Tokens/TokensExpireApiTest.php @@ -0,0 +1,63 @@ +authenticate(); + } + + /** + * @param string $id + */ + protected function handleTest(string $id): void + { + $this->response = $this->postJson('api/tokens/' . $id . '/expire', ['api_token' => $this->authToken]); + } + + /** + * @test + */ + public function it_cannot_expire_non_existent_tokens(): void + { + $this->handleTest('bad id'); + + $this->response->assertStatus(404); + } + + /** + * @test + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_expires_tokens(): void + { + $token = $this->tokens->create(new Token(0, 1, new HashedSearchable(''), 'name')); + + $this->assertNull($token->getExpiresAt()); + + $this->handleTest($token->getId()); + + $this->assertNotNull($this->tokens->filter()[0]->getExpiresAt()); + } +} -- GitLab From 2d2704e1ba0986c7c75540c464460479f8262cf1 Mon Sep 17 00:00:00 2001 From: dakriy Date: Tue, 16 Jun 2020 23:58:23 -0700 Subject: [PATCH 21/38] Increase php memory limit, and create entries get tests --- php/dev.ini | 1 + php/prod.ini | 1 + .../Feature/Api/Entries/EntriesGetApiTest.php | 109 ++++++++++++++++++ .../Feature/Api/Tokens/TokenGetApiTest.php | 1 - .../Api/Tokens/TokensCreateApiTest.php | 1 - .../Api/Tokens/TokensExpireApiTest.php | 1 - .../Api/Tokens/TokensUpdateApiTest.php | 1 - 7 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 src/backend/tests/Feature/Api/Entries/EntriesGetApiTest.php diff --git a/php/dev.ini b/php/dev.ini index 66192d15..a1a02ec9 100644 --- a/php/dev.ini +++ b/php/dev.ini @@ -12,3 +12,4 @@ xdebug.remote.mode=req xdebug.remote.handler=dbgp date.timezone = "America/Los_Angeles" +memory_limit = 256M diff --git a/php/prod.ini b/php/prod.ini index 52e86d2a..02e4b50e 100644 --- a/php/prod.ini +++ b/php/prod.ini @@ -1 +1,2 @@ date.timezone = "America/Los_Angeles" +memory_limit = 256M diff --git a/src/backend/tests/Feature/Api/Entries/EntriesGetApiTest.php b/src/backend/tests/Feature/Api/Entries/EntriesGetApiTest.php new file mode 100644 index 00000000..3585eb0e --- /dev/null +++ b/src/backend/tests/Feature/Api/Entries/EntriesGetApiTest.php @@ -0,0 +1,109 @@ +entries = new InMemoryEntriesRepository(); + $this->instance(EntriesRepository::class, $this->entries); + + $this->authenticate(); + } + + protected function handleTest(?string $start, ?string $end, ?string $doorId, ?string $userId): void + { + $this->response = $this->getJson( + 'api/entries?api_token=' . $this->authToken + . '&start=' . $start + . '&end=' . $end + . '&door_id=' . $doorId + . '&user_id=' . $userId + ); + } + + /** + * @test + */ + public function it_can_get_none(): void + { + $this->handleTest(null, null, null, null); + + $this->response->assertJsonCount(0, 'data'); + } + + /** + * @test + */ + public function it_filters_by_start(): void + { + $this->entries->add(new Entry(1, 1, 2, true, new Carbon('2020-01-02'))); + $this->entries->add(new Entry(2, 1, 2, true, new Carbon('2020-04-02'))); + + $this->handleTest('2020-02-05', null, null, null); + $this->response->assertJsonCount(1, 'data'); + $this->response->assertJson(['data' => [['id' => 2]]]); + } + + /** + * @test + */ + public function it_filters_by_end(): void + { + $this->entries->add(new Entry(1, 1, 2, true, new Carbon('2020-01-02'))); + $this->entries->add(new Entry(2, 1, 2, true, new Carbon('2020-04-02'))); + $this->handleTest(null, '2020-02-05', null, null); + $this->response->assertJsonCount(1, 'data'); + $this->response->assertJson(['data' => [['id' => 1]]]); + } + + /** + * @test + */ + public function it_filters_by_user_id(): void + { + $this->entries->add(new Entry(1, 1, 2, true)); + $this->entries->add(new Entry(2, 2, 1, true)); + $this->handleTest(null, null, null, 1); + $this->response->assertJsonCount(1, 'data'); + $this->response->assertJson(['data' => [['id' => 1]]]); + } + + /** + * @test + */ + public function it_filters_by_door_id(): void + { + $this->entries->add(new Entry(1, 1, 2, true)); + $this->entries->add(new Entry(2, 2, 1, true)); + $this->handleTest(null, null, 1, null); + $this->response->assertJsonCount(1, 'data'); + $this->response->assertJson(['data' => [['id' => 2]]]); + } +} diff --git a/src/backend/tests/Feature/Api/Tokens/TokenGetApiTest.php b/src/backend/tests/Feature/Api/Tokens/TokenGetApiTest.php index 00ad355e..00761537 100644 --- a/src/backend/tests/Feature/Api/Tokens/TokenGetApiTest.php +++ b/src/backend/tests/Feature/Api/Tokens/TokenGetApiTest.php @@ -3,7 +3,6 @@ namespace Tests\Feature\Api\Tokens; - use Source\Entities\Token; use Illuminate\Testing\TestResponse; use Source\Entities\HashedSearchable; diff --git a/src/backend/tests/Feature/Api/Tokens/TokensCreateApiTest.php b/src/backend/tests/Feature/Api/Tokens/TokensCreateApiTest.php index 3ce20b4a..5ce433d4 100644 --- a/src/backend/tests/Feature/Api/Tokens/TokensCreateApiTest.php +++ b/src/backend/tests/Feature/Api/Tokens/TokensCreateApiTest.php @@ -3,7 +3,6 @@ namespace Tests\Feature\Api\Tokens; - use Illuminate\Testing\TestResponse; use Source\Entities\HashedSearchable; use Tests\Feature\AuthenticatesWithApplicationTestCase; diff --git a/src/backend/tests/Feature/Api/Tokens/TokensExpireApiTest.php b/src/backend/tests/Feature/Api/Tokens/TokensExpireApiTest.php index 9f3a18db..0540837f 100644 --- a/src/backend/tests/Feature/Api/Tokens/TokensExpireApiTest.php +++ b/src/backend/tests/Feature/Api/Tokens/TokensExpireApiTest.php @@ -3,7 +3,6 @@ namespace Tests\Feature\Api\Tokens; - use Source\Entities\Token; use Illuminate\Testing\TestResponse; use Source\Entities\HashedSearchable; diff --git a/src/backend/tests/Feature/Api/Tokens/TokensUpdateApiTest.php b/src/backend/tests/Feature/Api/Tokens/TokensUpdateApiTest.php index aeff71d7..78894814 100644 --- a/src/backend/tests/Feature/Api/Tokens/TokensUpdateApiTest.php +++ b/src/backend/tests/Feature/Api/Tokens/TokensUpdateApiTest.php @@ -3,7 +3,6 @@ namespace Tests\Feature\Api\Tokens; - use Carbon\Carbon; use Source\Entities\Token; use Illuminate\Testing\TestResponse; -- GitLab From ee2f86874e693daf4ac26c4a0d23d78f37a7fe1f Mon Sep 17 00:00:00 2001 From: dakriy Date: Wed, 17 Jun 2020 00:20:54 -0700 Subject: [PATCH 22/38] Add door group tests --- .../Api/DoorGroup/AddDoorToGroupApiTest.php | 73 +++++++++++++++ .../Api/DoorGroup/GetGroupsForDoorApiTest.php | 88 +++++++++++++++++++ .../DoorGroup/RemoveDoorFromGroupApiTest.php | 74 ++++++++++++++++ 3 files changed, 235 insertions(+) create mode 100644 src/backend/tests/Feature/Api/DoorGroup/AddDoorToGroupApiTest.php create mode 100644 src/backend/tests/Feature/Api/DoorGroup/GetGroupsForDoorApiTest.php create mode 100644 src/backend/tests/Feature/Api/DoorGroup/RemoveDoorFromGroupApiTest.php diff --git a/src/backend/tests/Feature/Api/DoorGroup/AddDoorToGroupApiTest.php b/src/backend/tests/Feature/Api/DoorGroup/AddDoorToGroupApiTest.php new file mode 100644 index 00000000..28122d79 --- /dev/null +++ b/src/backend/tests/Feature/Api/DoorGroup/AddDoorToGroupApiTest.php @@ -0,0 +1,73 @@ +groups = new InMemoryGroupsRepository(); + $this->doorGroup = new InMemoryDoorGroupRepository($this->doorsRepository, $this->groups); + + $this->instance(GroupsRepository::class, $this->groups); + $this->instance(DoorGroupRepository::class, $this->doorGroup); + + $this->authenticate(); + } + + protected function handleTest(string $doorId, string $groupId): void + { + $this->response = $this->postJson('api/doors/' . $doorId . '/group/' . $groupId, [ + 'api_token' => $this->authToken, + ]); + } + + /** + * @test + * @throws \Source\Exceptions\EntityExistsException + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_adds_a_door_to_a_group(): void + { + $this->groups->create(new Group(1, '', '')); + $this->doorsRepository->create(new Door(1, '', '', new HashedSearchable(''))); + + $this->handleTest(1, 1); + + $this->response->assertStatus(200); + $this->assertCount(1, $this->doorGroup->getDoorsForGroup(1)); + } +} diff --git a/src/backend/tests/Feature/Api/DoorGroup/GetGroupsForDoorApiTest.php b/src/backend/tests/Feature/Api/DoorGroup/GetGroupsForDoorApiTest.php new file mode 100644 index 00000000..9de54a01 --- /dev/null +++ b/src/backend/tests/Feature/Api/DoorGroup/GetGroupsForDoorApiTest.php @@ -0,0 +1,88 @@ +groups = new InMemoryGroupsRepository(); + $this->doorGroup = new InMemoryDoorGroupRepository($this->doorsRepository, $this->groups); + + $this->instance(GroupsRepository::class, $this->groups); + $this->instance(DoorGroupRepository::class, $this->doorGroup); + + $this->authenticate(); + } + + protected function handleTest(string $doorId): void + { + $this->response = $this->getJson('api/doors/' . $doorId . '/groups?api_token=' . $this->authToken); + } + + /** + * @test + * @throws \Source\Exceptions\EntityExistsException + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_gets_groups_for_a_door(): void + { + $this->groups->create(new Group(1, '', '')); + $this->doorsRepository->create(new Door(1, '', '', new HashedSearchable(''))); + $this->doorGroup->addDoorToGroup(1, 1); + + $this->handleTest(1); + + $this->response->assertStatus(200); + $this->response->assertJsonCount(1, 'data'); + } + + /** + * @test + * @throws \Source\Exceptions\EntityExistsException + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_cannot_get_groups_for_non_existent_door(): void + { + $this->groups->create(new Group(1, '', '')); + $this->doorsRepository->create(new Door(1, '', '', new HashedSearchable(''))); + $this->doorGroup->addDoorToGroup(1, 1); + + $this->handleTest(2); + + $this->response->assertStatus(404); + } +} diff --git a/src/backend/tests/Feature/Api/DoorGroup/RemoveDoorFromGroupApiTest.php b/src/backend/tests/Feature/Api/DoorGroup/RemoveDoorFromGroupApiTest.php new file mode 100644 index 00000000..8d25a05c --- /dev/null +++ b/src/backend/tests/Feature/Api/DoorGroup/RemoveDoorFromGroupApiTest.php @@ -0,0 +1,74 @@ +groups = new InMemoryGroupsRepository(); + $this->doorGroup = new InMemoryDoorGroupRepository($this->doorsRepository, $this->groups); + + $this->instance(GroupsRepository::class, $this->groups); + $this->instance(DoorGroupRepository::class, $this->doorGroup); + + $this->authenticate(); + } + + protected function handleTest(string $doorId, string $groupId): void + { + $this->response = $this->deleteJson('api/doors/' . $doorId . '/group/' . $groupId, [ + 'api_token' => $this->authToken, + ]); + } + + /** + * @test + * @throws \Source\Exceptions\EntityExistsException + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_removes_a_door_from_a_group(): void + { + $this->groups->create(new Group(1, '', '')); + $this->doorsRepository->create(new Door(1, '', '', new HashedSearchable(''))); + $this->doorGroup->addDoorToGroup(1, 1); + + $this->handleTest(1, 1); + + $this->response->assertStatus(200); + $this->assertCount(0, $this->doorGroup->getDoorsForGroup(1)); + } +} -- GitLab From 9f8817f44d506a4079c4ed95bab48d32ac847e42 Mon Sep 17 00:00:00 2001 From: dakriy Date: Wed, 17 Jun 2020 00:41:46 -0700 Subject: [PATCH 23/38] Add tests for getting current users access --- .../Me/GetCurrentUserDoorAccessApiTest.php | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 src/backend/tests/Feature/Api/Me/GetCurrentUserDoorAccessApiTest.php diff --git a/src/backend/tests/Feature/Api/Me/GetCurrentUserDoorAccessApiTest.php b/src/backend/tests/Feature/Api/Me/GetCurrentUserDoorAccessApiTest.php new file mode 100644 index 00000000..f442fb85 --- /dev/null +++ b/src/backend/tests/Feature/Api/Me/GetCurrentUserDoorAccessApiTest.php @@ -0,0 +1,112 @@ +groups = new InMemoryGroupsRepository(); + $this->schedules = new InMemorySchedulesRepository(); + $this->doorGroup = new InMemoryDoorGroupRepository($this->doorsRepository, $this->groups); + $this->groupUser = new InMemoryGroupUserRepository($this->usersRepository, $this->groups); + $this->instance(GroupUserRepository::class, $this->groupUser); + $this->instance(DoorGroupRepository::class, $this->doorGroup); + $this->instance(GroupsRepository::class, $this->groups); + $this->instance(SchedulesRepository::class, $this->schedules); + + $this->authenticate(); + } + + protected function handleTest(): void + { + $this->response = $this->getJson('api/me/access?api_token=' . $this->authToken); + } + + /** + * @test + * @throws \Source\Exceptions\EntityExistsException + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_gets_doors_a_user_has_access_to(): void + { + $this->doorsRepository->create(new Door(1, '', '', new HashedSearchable(''))); + $this->doorsRepository->create(new Door(2, '', '', new HashedSearchable(''))); + $this->groups->create(new Group(1, '', '')); + $this->doorGroup->addDoorToGroup(1, 1); + $this->doorGroup->addDoorToGroup(2, 1); + $this->groupUser->addUserToGroup(1, 1); + $this->schedules->create(new Schedule(1, 1, Schedule::TYPE_USER_ACCESS, '', 1234, '', new Carbon('2020-06-09'))); + $this->schedules->create(new Schedule(2, 1, Schedule::TYPE_USER_ACCESS, '', 1235, '', new Carbon('2020-06-09'))); + + $this->handleTest(); + + $this->response->assertStatus(200); + $this->response->assertJson([ + 'groups' => [ + ['id' => 1, 'title' => '', 'description' => ''], + ], + 'doors' => [ + 1 => [ + ['id' => 1, 'name' => '', 'location' => ''], + ['id' => 2, 'name' => '', 'location' => ''], + ], + ], + 'schedules' => [ + 1 => [ + ['id' => 1, 'description' => '', 'rset' => '', 'duration' => 1234, 'end_date' => null], + ['id' => 2, 'description' => '', 'rset' => '', 'duration' => 1235, 'end_date' => null], + ], + ], + ]); + } +} -- GitLab From bddbe8c1cc28f72d2970b9faf3d678b7e072bd17 Mon Sep 17 00:00:00 2001 From: dakriy Date: Wed, 17 Jun 2020 00:47:11 -0700 Subject: [PATCH 24/38] Add tests for getting current user permissions --- src/backend/tests/Doubles/AuthorizerStub.php | 12 ++++- .../Me/GetCurrentUserPermissionsApiTest.php | 45 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/backend/tests/Feature/Api/Me/GetCurrentUserPermissionsApiTest.php diff --git a/src/backend/tests/Doubles/AuthorizerStub.php b/src/backend/tests/Doubles/AuthorizerStub.php index 51926b42..bd7789f3 100644 --- a/src/backend/tests/Doubles/AuthorizerStub.php +++ b/src/backend/tests/Doubles/AuthorizerStub.php @@ -14,6 +14,11 @@ class AuthorizerStub implements Authorizer protected ?string $id = null; + /** + * @var string[] + */ + protected array $perms = []; + /** * @param string|null $id */ @@ -100,12 +105,17 @@ class AuthorizerStub implements Authorizer } } + public function setPermissions(array $permssions): void + { + $this->perms = $permssions; + } + /** * @inheritDoc */ public function getPermissions(): array { - return []; + return $this->perms; } /** diff --git a/src/backend/tests/Feature/Api/Me/GetCurrentUserPermissionsApiTest.php b/src/backend/tests/Feature/Api/Me/GetCurrentUserPermissionsApiTest.php new file mode 100644 index 00000000..b5350fce --- /dev/null +++ b/src/backend/tests/Feature/Api/Me/GetCurrentUserPermissionsApiTest.php @@ -0,0 +1,45 @@ +authorizer->setPermissions(['perm1', 'perm2']); + + $this->authenticate(); + } + + protected function handleTest(): void + { + $this->response = $this->getJson('api/me/permissions?api_token='. $this->authToken); + } + + /** + * @test + */ + public function it_gets_current_user_permissions(): void + { + $this->handleTest(); + + $this->response->assertStatus(200); + $this->response->assertJson(['permissions' => ['perm1', 'perm2']]); + } +} -- GitLab From 090ed6e27d8a09810dcd7f720653d91120873b49 Mon Sep 17 00:00:00 2001 From: dakriy Date: Wed, 17 Jun 2020 00:50:21 -0700 Subject: [PATCH 25/38] Add test for getting current user token --- .../Api/Me/GetCurrentUserTokensApiTest.php | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/backend/tests/Feature/Api/Me/GetCurrentUserTokensApiTest.php diff --git a/src/backend/tests/Feature/Api/Me/GetCurrentUserTokensApiTest.php b/src/backend/tests/Feature/Api/Me/GetCurrentUserTokensApiTest.php new file mode 100644 index 00000000..e531efbd --- /dev/null +++ b/src/backend/tests/Feature/Api/Me/GetCurrentUserTokensApiTest.php @@ -0,0 +1,50 @@ +authenticate(); + } + + protected function handleTest(): void + { + $this->response = $this->getJson('api/me/tokens?api_token=' . $this->authToken); + } + + /** + * @test + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_gets_current_user_tokens(): void + { + $this->tokens->create(new Token(10, 1, new HashedSearchable(''), 'token 1')); + + $this->handleTest(); + + $this->response->assertStatus(200); + + $this->response->assertJson(['data' => [['id' => 10, 'name' => 'token 1']]]); + } +} -- GitLab From bb36ab816557e097059dcb853d58016b7dce037f Mon Sep 17 00:00:00 2001 From: dakriy Date: Wed, 17 Jun 2020 00:51:07 -0700 Subject: [PATCH 26/38] setUp not supposed to be a test --- src/backend/tests/Feature/Api/Me/GetCurrentUserTokensApiTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/backend/tests/Feature/Api/Me/GetCurrentUserTokensApiTest.php b/src/backend/tests/Feature/Api/Me/GetCurrentUserTokensApiTest.php index e531efbd..ef5a77dc 100644 --- a/src/backend/tests/Feature/Api/Me/GetCurrentUserTokensApiTest.php +++ b/src/backend/tests/Feature/Api/Me/GetCurrentUserTokensApiTest.php @@ -16,7 +16,6 @@ class GetCurrentUserTokensApiTest extends AuthenticatesWithApplicationTestCase protected TestResponse $response; /** - * @test * @throws \Illuminate\Contracts\Container\BindingResolutionException * @throws \Source\Exceptions\EntityExistsException * @throws \Source\Exceptions\EntityNotFoundException -- GitLab From 9a795a1d0f82f72d25f36e856b2b441b2a4bfe96 Mon Sep 17 00:00:00 2001 From: dakriy Date: Wed, 17 Jun 2020 00:55:52 -0700 Subject: [PATCH 27/38] Add test for getting door user access for any user --- .../Api/DoorUser/DoorUserAccessApiTest.php | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 src/backend/tests/Feature/Api/DoorUser/DoorUserAccessApiTest.php diff --git a/src/backend/tests/Feature/Api/DoorUser/DoorUserAccessApiTest.php b/src/backend/tests/Feature/Api/DoorUser/DoorUserAccessApiTest.php new file mode 100644 index 00000000..347c98df --- /dev/null +++ b/src/backend/tests/Feature/Api/DoorUser/DoorUserAccessApiTest.php @@ -0,0 +1,112 @@ +groups = new InMemoryGroupsRepository(); + $this->schedules = new InMemorySchedulesRepository(); + $this->doorGroup = new InMemoryDoorGroupRepository($this->doorsRepository, $this->groups); + $this->groupUser = new InMemoryGroupUserRepository($this->usersRepository, $this->groups); + $this->instance(GroupUserRepository::class, $this->groupUser); + $this->instance(DoorGroupRepository::class, $this->doorGroup); + $this->instance(GroupsRepository::class, $this->groups); + $this->instance(SchedulesRepository::class, $this->schedules); + + $this->authenticate(); + } + + protected function handleTest(string $userId): void + { + $this->response = $this->getJson('api/users/' . $userId . '/doors?api_token=' . $this->authToken); + } + + /** + * @test + * @throws \Source\Exceptions\EntityExistsException + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_gets_doors_a_user_has_access_to(): void + { + $this->doorsRepository->create(new Door(1, '', '', new HashedSearchable(''))); + $this->doorsRepository->create(new Door(2, '', '', new HashedSearchable(''))); + $this->groups->create(new Group(1, '', '')); + $this->doorGroup->addDoorToGroup(1, 1); + $this->doorGroup->addDoorToGroup(2, 1); + $this->groupUser->addUserToGroup(1, 1); + $this->schedules->create(new Schedule(1, 1, Schedule::TYPE_USER_ACCESS, '', 1234, '', new Carbon('2020-06-09'))); + $this->schedules->create(new Schedule(2, 1, Schedule::TYPE_USER_ACCESS, '', 1235, '', new Carbon('2020-06-09'))); + + $this->handleTest(1); + + $this->response->assertStatus(200); + $this->response->assertJson([ + 'groups' => [ + ['id' => 1, 'title' => '', 'description' => ''], + ], + 'doors' => [ + 1 => [ + ['id' => 1, 'name' => '', 'location' => ''], + ['id' => 2, 'name' => '', 'location' => ''], + ], + ], + 'schedules' => [ + 1 => [ + ['id' => 1, 'description' => '', 'rset' => '', 'duration' => 1234, 'end_date' => null], + ['id' => 2, 'description' => '', 'rset' => '', 'duration' => 1235, 'end_date' => null], + ], + ], + ]); + } +} -- GitLab From 233947fa698677ca5bd5372c56c3814a93124d0c Mon Sep 17 00:00:00 2001 From: dakriy Date: Wed, 17 Jun 2020 01:07:32 -0700 Subject: [PATCH 28/38] fix typos and centralize duration length to schedule --- .../Http/Controllers/SchedulesController.php | 20 ++++++------- src/backend/src/Entities/Schedule.php | 28 +++++++++++++++++++ .../RecurrenceSet/PhpRruleRecurrenceSet.php | 4 +-- .../RecurrenceSet/RecurrenceSetRepository.php | 4 +-- .../Door/StatusResponse/StatusResponse.php | 4 +-- .../ScheduleCreate/ScheduleCreate.php | 2 +- .../ScheduleCreate/ScheduleCreateUseCase.php | 2 +- .../ScheduleUpdate/ScheduleUpdate.php | 2 +- .../tests/Doubles/RecurrenceSetStub.php | 2 +- 9 files changed, 48 insertions(+), 20 deletions(-) diff --git a/src/backend/app/Http/Controllers/SchedulesController.php b/src/backend/app/Http/Controllers/SchedulesController.php index 962836f0..be8266f4 100644 --- a/src/backend/app/Http/Controllers/SchedulesController.php +++ b/src/backend/app/Http/Controllers/SchedulesController.php @@ -32,7 +32,7 @@ class SchedulesController extends ApiController * * * @authenticated - * @bodyParam duration integer required The duration in minutes that the event lasts for. Example: 120 + * @bodyParam duration integer required The duration in seconds that the event lasts for. Example: 120 * @bodyParam group_id integer required The group to apply the schedule for. Example: 8 * @bodyParam type integer required The type of schedule. Example: 0 * @bodyParam rset string required The RFC 5545 compliant string representing the set. Example: RRULE:FREQ=MINUTELY @@ -49,10 +49,10 @@ class SchedulesController extends ApiController $this->authorizer->protect(Permissions::MANAGE_DOORS); $this->validate($this->request, [ - 'duration' => 'required|integer', /* miliseconds */ + 'duration' => 'required|integer', 'group_id' => 'required|integer', - 'type' => 'required|integer', /* 0 = Open, 1 = UserAccess */ - 'rset' => 'required|string', /* RFC RSet (NOT FULLY COMPLIANT!) */ + 'type' => 'required|integer', + 'rset' => 'required|string', 'description' => 'required|string|max:1024', ]); @@ -147,7 +147,7 @@ class SchedulesController extends ApiController * * @authenticated * @urlParam scheduleId required The schedule to update. Example: 1 - * @bodyParam duration integer The duration in minutes that the event lasts for. Example: 120 + * @bodyParam duration integer The duration in seconds that the event lasts for. Example: 120 * @bodyParam group_id integer The group to apply the schedule for. Example: 8 * @bodyParam type integer The type of schedule. Example: 0 * @bodyParam rset string The RFC 5545 compliant string representing the set. Example: RRULE:FREQ=MINUTELY @@ -165,11 +165,11 @@ class SchedulesController extends ApiController $this->authorizer->protect(Permissions::MANAGE_DOORS); $this->validate($this->request, [ - 'duration' => 'integer', - 'group_id' => 'integer', - 'type' => 'integer', - 'rset' => 'string', - 'description' => 'string|max:1024', + 'duration' => 'nullable|integer', + 'group_id' => 'nullable|integer', + 'type' => 'nullable|integer', + 'rset' => 'nullable|string', + 'description' => 'nullable|string|max:1024', ]); $presenter = new ScheduleApiPresenter(); diff --git a/src/backend/src/Entities/Schedule.php b/src/backend/src/Entities/Schedule.php index 3a846b6e..3bf8ca9c 100644 --- a/src/backend/src/Entities/Schedule.php +++ b/src/backend/src/Entities/Schedule.php @@ -194,4 +194,32 @@ class Schedule { return $this->description; } + + /** + * @param \Carbon\Carbon $carbon + * @return \Carbon\Carbon + */ + public function addDuration(Carbon $carbon): Carbon + { + return $carbon->addRealSeconds($this->duration); + } + + /** + * @param \Carbon\Carbon $carbon + * @return \Carbon\Carbon + */ + public function subDuration(Carbon $carbon): Carbon + { + return $carbon->subRealSeconds($this->duration); + } + + /** + * @param \Carbon\Carbon $carbon + * @param int $duration + * @return \Carbon\Carbon + */ + public static function calculateEventEnd(Carbon $carbon, int $duration): Carbon + { + return $carbon->addRealSeconds($duration); + } } diff --git a/src/backend/src/Gateways/RecurrenceSet/PhpRruleRecurrenceSet.php b/src/backend/src/Gateways/RecurrenceSet/PhpRruleRecurrenceSet.php index 8f155479..ab967259 100644 --- a/src/backend/src/Gateways/RecurrenceSet/PhpRruleRecurrenceSet.php +++ b/src/backend/src/Gateways/RecurrenceSet/PhpRruleRecurrenceSet.php @@ -67,8 +67,8 @@ class PhpRruleRecurrenceSet implements RecurrenceSetRepository /** * @inheritDoc */ - public function occurrenceHappeningAtDate(Carbon $date, int $duration): bool + public function occurrenceHappeningAtDate(Carbon $date, int $durationSeconds): bool { - return count($this->occurrencesBetween($date->clone()->subRealSeconds($duration), $date)) > 0; + return count($this->occurrencesBetween($date->clone()->subRealSeconds($durationSeconds), $date)) > 0; } } diff --git a/src/backend/src/Gateways/RecurrenceSet/RecurrenceSetRepository.php b/src/backend/src/Gateways/RecurrenceSet/RecurrenceSetRepository.php index 5ec3986a..5c423a49 100644 --- a/src/backend/src/Gateways/RecurrenceSet/RecurrenceSetRepository.php +++ b/src/backend/src/Gateways/RecurrenceSet/RecurrenceSetRepository.php @@ -40,8 +40,8 @@ interface RecurrenceSetRepository * Determines if an instance is happening at the given date given the duration in seconds * * @param \Carbon\Carbon $date - * @param int $duration + * @param int $durationSeconds * @return bool */ - public function occurrenceHappeningAtDate(Carbon $date, int $duration): bool; + public function occurrenceHappeningAtDate(Carbon $date, int $durationSeconds): bool; } diff --git a/src/backend/src/UseCases/Door/StatusResponse/StatusResponse.php b/src/backend/src/UseCases/Door/StatusResponse/StatusResponse.php index fa2103f7..8426e50b 100644 --- a/src/backend/src/UseCases/Door/StatusResponse/StatusResponse.php +++ b/src/backend/src/UseCases/Door/StatusResponse/StatusResponse.php @@ -93,10 +93,10 @@ class StatusResponse implements StatusResponseUseCase } // Subtract off duration to make sure we get any currently running schedules - $b = $begin->subSeconds($schedule->getDuration()); + $b = $schedule->subDuration($begin); foreach ($this->rset->occurrencesBetween($b, $end) as $eventStart) { - $eventEnd = $eventStart->clone()->addRealSeconds($schedule->getDuration()); + $eventEnd = $schedule->addDuration($eventStart->clone()); $override = $this->overrides->activeOverrideForDoorBetween($doorId, $eventStart, $eventEnd); if ($override && $override->hasTypeOf(Override::TYPE_LOCKED)) { // If the beginning of the schedule overlaps with the override diff --git a/src/backend/src/UseCases/Schedules/ScheduleCreate/ScheduleCreate.php b/src/backend/src/UseCases/Schedules/ScheduleCreate/ScheduleCreate.php index 07d95d6b..ddeb2949 100644 --- a/src/backend/src/UseCases/Schedules/ScheduleCreate/ScheduleCreate.php +++ b/src/backend/src/UseCases/Schedules/ScheduleCreate/ScheduleCreate.php @@ -58,7 +58,7 @@ class ScheduleCreate implements ScheduleCreateUseCase $this->rset->parse($attributes['rset']); $end = $this->rset->endDate(); if ($end) { - $end->addRealSeconds($attributes['duration']); + $end = Schedule::calculateEventEnd($end, $attributes['duration']); } $schedule = new Schedule( 0, diff --git a/src/backend/src/UseCases/Schedules/ScheduleCreate/ScheduleCreateUseCase.php b/src/backend/src/UseCases/Schedules/ScheduleCreate/ScheduleCreateUseCase.php index b82270c1..91b54318 100644 --- a/src/backend/src/UseCases/Schedules/ScheduleCreate/ScheduleCreateUseCase.php +++ b/src/backend/src/UseCases/Schedules/ScheduleCreate/ScheduleCreateUseCase.php @@ -11,7 +11,7 @@ interface ScheduleCreateUseCase * Required Attributes * - type: int or string (0 = open mode schedule, 1 = access time schedule) * - rset: string (valid as defined by rfc 5321) - * - duration: int or string (number of ms for the event to last) + * - duration: int or string (number of seconds for the event to last) * - group_id: int or string (group id to attach the schedule to) * - description: string (user entered description of the schedule) * diff --git a/src/backend/src/UseCases/Schedules/ScheduleUpdate/ScheduleUpdate.php b/src/backend/src/UseCases/Schedules/ScheduleUpdate/ScheduleUpdate.php index 9a0b797d..4e9c6956 100644 --- a/src/backend/src/UseCases/Schedules/ScheduleUpdate/ScheduleUpdate.php +++ b/src/backend/src/UseCases/Schedules/ScheduleUpdate/ScheduleUpdate.php @@ -66,7 +66,7 @@ class ScheduleUpdate implements ScheduleUpdateUseCase $this->rset->parse($rset); $end = $this->rset->endDate(); if ($end) { - $end->addRealSeconds($duration); + $end = Schedule::calculateEventEnd($end, $attributes['duration']); } $schedule = new Schedule( 0, diff --git a/src/backend/tests/Doubles/RecurrenceSetStub.php b/src/backend/tests/Doubles/RecurrenceSetStub.php index 2a50d42e..0826aaf7 100644 --- a/src/backend/tests/Doubles/RecurrenceSetStub.php +++ b/src/backend/tests/Doubles/RecurrenceSetStub.php @@ -58,7 +58,7 @@ class RecurrenceSetStub implements RecurrenceSetRepository /** * @inheritDoc */ - public function occurrenceHappeningAtDate(Carbon $date, int $duration): bool + public function occurrenceHappeningAtDate(Carbon $date, int $durationSeconds): bool { return $this->occurrenceHappeningAtDate; } -- GitLab From 8b0567909008b9d0ad9f97827a763ebe7a805ee8 Mon Sep 17 00:00:00 2001 From: dakriy Date: Wed, 17 Jun 2020 01:30:30 -0700 Subject: [PATCH 29/38] Schedule save refactoring --- .../Overrides/DatabaseOverridesRepository.php | 48 +++++----- .../Schedules/DatabaseSchedulesRepository.php | 46 +++++++--- .../Schedules/InMemorySchedulesRepository.php | 7 +- .../Schedules/SchedulesRepository.php | 10 ++- .../ScheduleCreate/ScheduleCreate.php | 6 +- .../ScheduleCreate/ScheduleCreateUseCase.php | 1 + .../ScheduleUpdate/ScheduleUpdate.php | 6 +- .../Api/Schedules/SchedulesCreateApiTest.php | 90 +++++++++++++++++++ 8 files changed, 158 insertions(+), 56 deletions(-) create mode 100644 src/backend/tests/Feature/Api/Schedules/SchedulesCreateApiTest.php diff --git a/src/backend/src/Gateways/Overrides/DatabaseOverridesRepository.php b/src/backend/src/Gateways/Overrides/DatabaseOverridesRepository.php index e8de2c5e..4727c9ad 100644 --- a/src/backend/src/Gateways/Overrides/DatabaseOverridesRepository.php +++ b/src/backend/src/Gateways/Overrides/DatabaseOverridesRepository.php @@ -121,11 +121,12 @@ QUERY; } /** - * @inheritDoc + * @param \App\Override $o + * @param \Source\Entities\Override $override + * @throws \Source\Exceptions\EntityNotFoundException */ - public function addOverride(Override $override): Override + protected function saveOverride(\App\Override $o, Override $override): void { - $o = new \App\Override(); $o->setAttribute('user_id', $override->getUserId()); $o->setAttribute('door_id', $override->getDoorId()); $o->setAttribute('type', $override->getType()); @@ -133,21 +134,31 @@ QUERY; $o->setAttribute('end', $override->getEnd()); $o->setAttribute('reason', $override->getReason()); - if ($override->getCreatedAt()) { - $o->setCreatedAt($override->getCreatedAt()); - } - try { $o->save(); } catch (QueryException $e) { if ($e->getCode() === self::FOREIGN_KEY_VIOLATION) { - throw new EntityNotFoundException('Cannot create override because the specified user or door does not exist.'); + throw new EntityNotFoundException('Cannot save override because the specified user or door does not exist.'); } - Log::error('Failed creating override: ' . $e); + Log::error('Failed saving override: ' . $e); throw $e; } + } + + /** + * @inheritDoc + */ + public function addOverride(Override $override): Override + { + $o = new \App\Override(); + + if ($override->getCreatedAt()) { + $o->setCreatedAt($override->getCreatedAt()); + } + + $this->saveOverride($o, $override); return self::toOverride($o); } @@ -164,24 +175,7 @@ QUERY; throw new EntityNotFoundException('Override with id "' . $overrideId . '" does not exist.'); } - $o->setAttribute('user_id', $override->getUserId()); - $o->setAttribute('door_id', $override->getDoorId()); - $o->setAttribute('type', $override->getType()); - $o->setAttribute('start', $override->getStart()); - $o->setAttribute('end', $override->getEnd()); - $o->setAttribute('reason', $override->getReason()); - - try { - $o->save(); - } catch (QueryException $e) { - if ($e->getCode() === self::FOREIGN_KEY_VIOLATION) { - throw new EntityNotFoundException('Cannot update override because the referenced user or door does not exist.'); - } - - Log::error('Failed updating override: ' . $e); - - throw $e; - } + $this->saveOverride($o, $override); return self::toOverride($o); } diff --git a/src/backend/src/Gateways/Schedules/DatabaseSchedulesRepository.php b/src/backend/src/Gateways/Schedules/DatabaseSchedulesRepository.php index e8f378bc..574b0443 100644 --- a/src/backend/src/Gateways/Schedules/DatabaseSchedulesRepository.php +++ b/src/backend/src/Gateways/Schedules/DatabaseSchedulesRepository.php @@ -6,10 +6,15 @@ namespace Source\Gateways\Schedules; use Carbon\Carbon; use Source\Sanitize\CastsTo; use Source\Entities\Schedule; +use Illuminate\Support\Facades\Log; +use Illuminate\Database\QueryException; use Illuminate\Database\Eloquent\Builder; +use Source\Exceptions\EntityNotFoundException; class DatabaseSchedulesRepository implements SchedulesRepository { + protected const FOREIGN_KEY_VIOLATION = '23503'; + use CastsTo; /** @@ -46,16 +51,37 @@ class DatabaseSchedulesRepository implements SchedulesRepository } /** - * @inheritDoc + * @param \App\Schedule $dbSchedule + * @param \Source\Entities\Schedule $schedule + * @throws \Source\Exceptions\EntityNotFoundException */ - public function create(Schedule $schedule): ?Schedule + public function saveSchedule(\App\Schedule $dbSchedule, Schedule $schedule): void { - $dbSchedule = new \App\Schedule(); $this->setAttributesOnDbSchedule($dbSchedule, $schedule); - if (!$dbSchedule->save()) { - return null; + try { + $dbSchedule->save(); + } catch (QueryException $e) { + if ($e->getCode() === self::FOREIGN_KEY_VIOLATION) { + throw new EntityNotFoundException('Cannot save schedule because the group does not exist'); + } + + Log::error('Failed saving schedule: ' . $e); + + throw $e; } + } + + /** + * @inheritDoc + */ + public function create(Schedule $schedule): Schedule + { + $dbSchedule = new \App\Schedule(); + + $this->saveSchedule($dbSchedule, $schedule); + + $dbSchedule->save(); return self::toSchedule($dbSchedule); } @@ -140,20 +166,16 @@ class DatabaseSchedulesRepository implements SchedulesRepository /** * @inheritDoc */ - public function update(string $scheduleId, Schedule $schedule): ?Schedule + public function update(string $scheduleId, Schedule $schedule): Schedule { /** @var \App\Schedule|null $dbSchedule */ $dbSchedule = \App\Schedule::query()->find($this->castToInt($scheduleId)); if (!$scheduleId) { - return null; + throw new EntityNotFoundException('Schedule does not exist.'); } - $this->setAttributesOnDbSchedule($dbSchedule, $schedule); - - if (!$dbSchedule->save()) { - return null; - } + $this->saveSchedule($dbSchedule, $schedule); return self::toSchedule($dbSchedule); } diff --git a/src/backend/src/Gateways/Schedules/InMemorySchedulesRepository.php b/src/backend/src/Gateways/Schedules/InMemorySchedulesRepository.php index 2949e7fb..cd2f11ad 100644 --- a/src/backend/src/Gateways/Schedules/InMemorySchedulesRepository.php +++ b/src/backend/src/Gateways/Schedules/InMemorySchedulesRepository.php @@ -5,6 +5,7 @@ namespace Source\Gateways\Schedules; use Carbon\Carbon; use Source\Entities\Schedule; +use Source\Exceptions\EntityNotFoundException; class InMemorySchedulesRepository implements SchedulesRepository { @@ -16,7 +17,7 @@ class InMemorySchedulesRepository implements SchedulesRepository /** * @inheritDoc */ - public function create(Schedule $schedule): ?Schedule + public function create(Schedule $schedule): Schedule { $this->schedules[] = $schedule; return $schedule; @@ -79,7 +80,7 @@ class InMemorySchedulesRepository implements SchedulesRepository /** * @inheritDoc */ - public function update(string $scheduleId, Schedule $schedule): ?Schedule + public function update(string $scheduleId, Schedule $schedule): Schedule { foreach ($this->schedules as $k=>$s) { if ($s->hasIdOf($scheduleId)) { @@ -88,6 +89,6 @@ class InMemorySchedulesRepository implements SchedulesRepository } } - return null; + throw new EntityNotFoundException('Schedule not found.'); } } diff --git a/src/backend/src/Gateways/Schedules/SchedulesRepository.php b/src/backend/src/Gateways/Schedules/SchedulesRepository.php index 2fb51191..4fc0cb51 100644 --- a/src/backend/src/Gateways/Schedules/SchedulesRepository.php +++ b/src/backend/src/Gateways/Schedules/SchedulesRepository.php @@ -12,9 +12,10 @@ interface SchedulesRepository * Creates a schedule entry * * @param \Source\Entities\Schedule $schedule - * @return \Source\Entities\Schedule|null + * @return \Source\Entities\Schedule + * @throws \Source\Exceptions\EntityNotFoundException */ - public function create(Schedule $schedule): ?Schedule; + public function create(Schedule $schedule): Schedule; /** * Get a schedule @@ -48,7 +49,8 @@ interface SchedulesRepository * * @param string $scheduleId * @param \Source\Entities\Schedule $schedule - * @return \Source\Entities\Schedule|null + * @return \Source\Entities\Schedule + * @throws \Source\Exceptions\EntityNotFoundException */ - public function update(string $scheduleId, Schedule $schedule): ?Schedule; + public function update(string $scheduleId, Schedule $schedule): Schedule; } diff --git a/src/backend/src/UseCases/Schedules/ScheduleCreate/ScheduleCreate.php b/src/backend/src/UseCases/Schedules/ScheduleCreate/ScheduleCreate.php index ddeb2949..4f38ca01 100644 --- a/src/backend/src/UseCases/Schedules/ScheduleCreate/ScheduleCreate.php +++ b/src/backend/src/UseCases/Schedules/ScheduleCreate/ScheduleCreate.php @@ -74,11 +74,7 @@ class ScheduleCreate implements ScheduleCreateUseCase if (!$response->hasError()) { $schedule = $this->schedules->create($schedule); - if (!$schedule) { - $response->addError('Unable to create the schedule.'); - } else { - $response->setSchedule($schedule); - } + $response->setSchedule($schedule); } } catch (InvalidArgumentException $e) { // error: invalid rfc string or invalid type given diff --git a/src/backend/src/UseCases/Schedules/ScheduleCreate/ScheduleCreateUseCase.php b/src/backend/src/UseCases/Schedules/ScheduleCreate/ScheduleCreateUseCase.php index 91b54318..8c0d72cd 100644 --- a/src/backend/src/UseCases/Schedules/ScheduleCreate/ScheduleCreateUseCase.php +++ b/src/backend/src/UseCases/Schedules/ScheduleCreate/ScheduleCreateUseCase.php @@ -17,6 +17,7 @@ interface ScheduleCreateUseCase * * @param array $attributes * @param \Source\UseCases\Schedules\Presenter $presenter + * @throws \Source\Exceptions\EntityNotFoundException */ public function create(array $attributes, Presenter $presenter): void; } diff --git a/src/backend/src/UseCases/Schedules/ScheduleUpdate/ScheduleUpdate.php b/src/backend/src/UseCases/Schedules/ScheduleUpdate/ScheduleUpdate.php index 4e9c6956..6a50968e 100644 --- a/src/backend/src/UseCases/Schedules/ScheduleUpdate/ScheduleUpdate.php +++ b/src/backend/src/UseCases/Schedules/ScheduleUpdate/ScheduleUpdate.php @@ -82,11 +82,7 @@ class ScheduleUpdate implements ScheduleUpdateUseCase if (!$response->hasError()) { $schedule = $this->schedules->update($oldSchedule->getId(), $schedule); - if (!$schedule) { - $response->addError('Unable to update the schedule.'); - } else { - $response->setSchedule($schedule); - } + $response->setSchedule($schedule); } } catch (InvalidArgumentException $e) { // error: invalid rfc string or invalid type given diff --git a/src/backend/tests/Feature/Api/Schedules/SchedulesCreateApiTest.php b/src/backend/tests/Feature/Api/Schedules/SchedulesCreateApiTest.php new file mode 100644 index 00000000..9bc996b8 --- /dev/null +++ b/src/backend/tests/Feature/Api/Schedules/SchedulesCreateApiTest.php @@ -0,0 +1,90 @@ +rset = new RecurrenceSetStub(); + $this->rset->beginDate = Carbon::now(); + $this->rset->endDate = Carbon::now()->addDay(); + $this->schedules = new InMemorySchedulesRepository(); + $this->groups = new InMemoryGroupsRepository(); + $this->instance(GroupsRepository::class, $this->groups); + $this->instance(RecurrenceSetRepository::class, $this->rset); + $this->instance(SchedulesRepository::class, $this->schedules); + + $this->authenticate(); + } + + protected function handleTest(array $data): void + { + $this->response = $this->postJson('api/schedules', array_merge( + ['api_token' => $this->authToken], + $data + )); + } + + /** + * @test + * @throws \Source\Exceptions\EntityExistsException + */ + public function it_creates_a_schedule(): void + { + $this->groups->create(new Group(1, '', '')); + + $this->handleTest([ + 'duration' => 1234, + 'group_id' => 1, + 'type' => Schedule::TYPE_OPEN_MODE, + 'rset' => 'rset', + 'description' => 'desc' + ]); + $this->response->assertStatus(200); + + $this->assertCount(1, $this->schedules->filter()); + $this->assertEquals('desc', $this->schedules->filter()[0]->getDescription()); + $this->response->assertJson(['schedule' => ['group_id' => 1, 'type' => Schedule::TYPE_OPEN_MODE]]); + } +} -- GitLab From e8ee9f5b00d5cc04238129fb62d4cf66e463172d Mon Sep 17 00:00:00 2001 From: dakriy Date: Wed, 17 Jun 2020 01:35:09 -0700 Subject: [PATCH 30/38] Test schedule creation validation errors --- .../Api/Schedules/SchedulesCreateApiTest.php | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/backend/tests/Feature/Api/Schedules/SchedulesCreateApiTest.php b/src/backend/tests/Feature/Api/Schedules/SchedulesCreateApiTest.php index 9bc996b8..2f3d3290 100644 --- a/src/backend/tests/Feature/Api/Schedules/SchedulesCreateApiTest.php +++ b/src/backend/tests/Feature/Api/Schedules/SchedulesCreateApiTest.php @@ -87,4 +87,28 @@ class SchedulesCreateApiTest extends AuthenticatesWithApplicationTestCase $this->assertEquals('desc', $this->schedules->filter()[0]->getDescription()); $this->response->assertJson(['schedule' => ['group_id' => 1, 'type' => Schedule::TYPE_OPEN_MODE]]); } + + /** + * @test + */ + public function it_can_fail_to_create_a_schedule(): void + { + $this->rset->failParse = true; + $this->handleTest([ + 'duration' => -1, + 'group_id' => 1, + 'type' => 1234, + 'rset' => 'rset', + 'description' => 'desc' + ]); + + $this->response->assertStatus(422); + + $this->assertCount(0, $this->schedules->filter()); + $this->response->assertJson(['errors' => [ + 'Invalid group specified.', + 'Duration cannot be negative.', + 'Invalid rset string.', + ]]); + } } -- GitLab From 8cad4ae5d7362293ff1a25ae495f89111f08a1d1 Mon Sep 17 00:00:00 2001 From: dakriy Date: Wed, 17 Jun 2020 01:40:16 -0700 Subject: [PATCH 31/38] Add tests for getting a schedule --- .../Api/Schedules/ScheduleGetApiTest.php | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/backend/tests/Feature/Api/Schedules/ScheduleGetApiTest.php diff --git a/src/backend/tests/Feature/Api/Schedules/ScheduleGetApiTest.php b/src/backend/tests/Feature/Api/Schedules/ScheduleGetApiTest.php new file mode 100644 index 00000000..6ba495e8 --- /dev/null +++ b/src/backend/tests/Feature/Api/Schedules/ScheduleGetApiTest.php @@ -0,0 +1,69 @@ +schedules = new InMemorySchedulesRepository(); + $this->instance(SchedulesRepository::class, $this->schedules); + + $this->authenticate(); + } + + protected function handleTest(string $id): void + { + $this->response = $this->getJson('api/schedules/' . $id . '?api_token=' . $this->authToken); + } + + /** + * @test + */ + public function it_cannot_get_a_schedule_that_is_not_there(): void + { + $this->handleTest('bad id'); + + $this->response->assertStatus(404); + } + + /** + * @test + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_can_get_a_schedule(): void + { + $this->schedules->create(new Schedule(1, 1, Schedule::TYPE_OPEN_MODE, 'r set', 1234, 'desc', Carbon::now())); + + $this->handleTest(1); + + $this->response->assertStatus(200); + + $this->response->assertJson(['schedule' => ['id' => 1, 'description' => 'desc']]); + } +} -- GitLab From f421b531d119937134d350fb18096e429acfb53d Mon Sep 17 00:00:00 2001 From: dakriy Date: Wed, 17 Jun 2020 02:07:19 -0700 Subject: [PATCH 32/38] Add tests for different kinds of filtering on schedules --- .../Http/Controllers/SchedulesController.php | 8 +- .../Schedules/InMemorySchedulesRepository.php | 25 +++- .../Api/Schedules/SchedulesGetApiTest.php | 113 ++++++++++++++++++ 3 files changed, 139 insertions(+), 7 deletions(-) create mode 100644 src/backend/tests/Feature/Api/Schedules/SchedulesGetApiTest.php diff --git a/src/backend/app/Http/Controllers/SchedulesController.php b/src/backend/app/Http/Controllers/SchedulesController.php index be8266f4..d7442c3a 100644 --- a/src/backend/app/Http/Controllers/SchedulesController.php +++ b/src/backend/app/Http/Controllers/SchedulesController.php @@ -115,10 +115,10 @@ class SchedulesController extends ApiController $this->authorizer->protect(Permissions::MANAGE_DOORS); $this->validate($this->request, [ - 'start' => 'date', - 'end' => 'date', - 'type' => 'integer', - 'group_id' => 'integer', + 'start' => 'nullable|date', + 'end' => 'nullable|date', + 'type' => 'nullable|integer', + 'group_id' => 'nullable|integer', ]); $presenter = new SchedulesGetApiPresenter(); diff --git a/src/backend/src/Gateways/Schedules/InMemorySchedulesRepository.php b/src/backend/src/Gateways/Schedules/InMemorySchedulesRepository.php index cd2f11ad..af72d7b8 100644 --- a/src/backend/src/Gateways/Schedules/InMemorySchedulesRepository.php +++ b/src/backend/src/Gateways/Schedules/InMemorySchedulesRepository.php @@ -20,6 +20,7 @@ class InMemorySchedulesRepository implements SchedulesRepository public function create(Schedule $schedule): Schedule { $this->schedules[] = $schedule; + return $schedule; } @@ -69,8 +70,25 @@ class InMemorySchedulesRepository implements SchedulesRepository $include = $include && $schedule->hasGroupIdOf($groupId); } - if ($begin || $end) { - $include = $schedule->isActiveForDate($begin) || $schedule->isActiveForDate($end); + if ($schedule->getEnd()) { + if ($begin && $end) { + $include = $include && + ($begin->lessThanOrEqualTo($schedule->getEnd()) && + $end->greaterThanOrEqualTo($schedule->getStart())); + } elseif ($begin) { + $include = $include && $begin->lessThanOrEqualTo($schedule->getEnd()); + } elseif ($end) { + $include = $include && $end->greaterThanOrEqualTo($schedule->getStart()); + } + } elseif ($begin && $end) { + $include = $include && + (($begin->lessThanOrEqualTo($schedule->getStart()) && + $end->greaterThanOrEqualTo($schedule->getStart())) || + $begin->greaterThanOrEqualTo($schedule->getStart())); + } elseif ($begin) { + $include = $include && $begin->greaterThanOrEqualTo($schedule->getStart()); + } elseif ($end) { + $include = $include && $end->greaterThanOrEqualTo($schedule->getStart()); } return $include; @@ -82,9 +100,10 @@ class InMemorySchedulesRepository implements SchedulesRepository */ public function update(string $scheduleId, Schedule $schedule): Schedule { - foreach ($this->schedules as $k=>$s) { + foreach ($this->schedules as $k => $s) { if ($s->hasIdOf($scheduleId)) { $this->schedules[$k] = $schedule; + return $schedule; } } diff --git a/src/backend/tests/Feature/Api/Schedules/SchedulesGetApiTest.php b/src/backend/tests/Feature/Api/Schedules/SchedulesGetApiTest.php new file mode 100644 index 00000000..cd236ea1 --- /dev/null +++ b/src/backend/tests/Feature/Api/Schedules/SchedulesGetApiTest.php @@ -0,0 +1,113 @@ +schedules = new InMemorySchedulesRepository(); + $this->instance(SchedulesRepository::class, $this->schedules); + + $this->authenticate(); + } + + protected function handleTest(?string $start, ?string $end, ?string $type, ?string $groupId): void + { + $this->response = $this->getJson( + 'api/schedules?api_token=' . $this->authToken + . '&start=' . $start + . '&end=' . $end + . '&type=' . $type + . '&group_id=' . $groupId + ); + } + + /** + * @test + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_filters_schedules_by_begin(): void + { + $this->schedules->create(new Schedule(1, 1, Schedule::TYPE_OPEN_MODE, 'r set', 1234, 'desc', new Carbon('2020-03-30'))); + $this->schedules->create(new Schedule(2, 1, Schedule::TYPE_OPEN_MODE, 'r set', 1234, 'desc', new Carbon('2020-04-30'))); + + $this->handleTest('2020-04-01', null, null, null); + + $this->response->assertStatus(200); + $this->response->assertJsonCount(1, 'data'); + $this->response->assertJson(['data' => [['id' => 1]]]); + } + + /** + * @test + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_filters_schedules_by_end(): void + { + $this->schedules->create(new Schedule(1, 1, Schedule::TYPE_OPEN_MODE, 'r set', 1234, 'desc', new Carbon('2020-03-30'))); + $this->schedules->create(new Schedule(2, 1, Schedule::TYPE_OPEN_MODE, 'r set', 1234, 'desc', new Carbon('2020-04-30'))); + + $this->handleTest(null, '2020-05-01', null, null); + + $this->response->assertStatus(200); + $this->response->assertJsonCount(2, 'data'); + } + + /** + * @test + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_filters_schedules_by_type(): void + { + $this->schedules->create(new Schedule(1, 1, Schedule::TYPE_USER_ACCESS, 'r set', 1234, 'desc', new Carbon('2020-03-30'))); + $this->schedules->create(new Schedule(2, 1, Schedule::TYPE_OPEN_MODE, 'r set', 1234, 'desc', new Carbon('2020-04-30'))); + + $this->handleTest(null, null, Schedule::TYPE_USER_ACCESS, null); + + $this->response->assertStatus(200); + $this->response->assertJsonCount(1, 'data'); + $this->response->assertJson(['data' => [['id' => 1]]]); + } + + /** + * @test + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_filters_schedules_by_groupe(): void + { + $this->schedules->create(new Schedule(1, 2, Schedule::TYPE_USER_ACCESS, 'r set', 1234, 'desc', new Carbon('2020-03-30'))); + $this->schedules->create(new Schedule(2, 1, Schedule::TYPE_OPEN_MODE, 'r set', 1234, 'desc', new Carbon('2020-04-30'))); + + $this->handleTest(null, null, null, 1); + + $this->response->assertStatus(200); + $this->response->assertJsonCount(1, 'data'); + $this->response->assertJson(['data' => [['id' => 2]]]); + } +} -- GitLab From 1d1e5ccd782bd992d15d9c758699ea2e45fa41a2 Mon Sep 17 00:00:00 2001 From: dakriy Date: Wed, 17 Jun 2020 02:13:42 -0700 Subject: [PATCH 33/38] Add tests for schedule update --- .../ScheduleUpdate/ScheduleUpdate.php | 2 +- .../Api/Schedules/SchedulesUpdateApiTest.php | 118 ++++++++++++++++++ 2 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 src/backend/tests/Feature/Api/Schedules/SchedulesUpdateApiTest.php diff --git a/src/backend/src/UseCases/Schedules/ScheduleUpdate/ScheduleUpdate.php b/src/backend/src/UseCases/Schedules/ScheduleUpdate/ScheduleUpdate.php index 6a50968e..a875d3fe 100644 --- a/src/backend/src/UseCases/Schedules/ScheduleUpdate/ScheduleUpdate.php +++ b/src/backend/src/UseCases/Schedules/ScheduleUpdate/ScheduleUpdate.php @@ -66,7 +66,7 @@ class ScheduleUpdate implements ScheduleUpdateUseCase $this->rset->parse($rset); $end = $this->rset->endDate(); if ($end) { - $end = Schedule::calculateEventEnd($end, $attributes['duration']); + $end = Schedule::calculateEventEnd($end, $duration); } $schedule = new Schedule( 0, diff --git a/src/backend/tests/Feature/Api/Schedules/SchedulesUpdateApiTest.php b/src/backend/tests/Feature/Api/Schedules/SchedulesUpdateApiTest.php new file mode 100644 index 00000000..3e26aab0 --- /dev/null +++ b/src/backend/tests/Feature/Api/Schedules/SchedulesUpdateApiTest.php @@ -0,0 +1,118 @@ +rset = new RecurrenceSetStub(); + $this->rset->beginDate = Carbon::now(); + $this->rset->endDate = Carbon::now()->addDay(); + $this->schedules = new InMemorySchedulesRepository(); + $this->groups = new InMemoryGroupsRepository(); + $this->instance(GroupsRepository::class, $this->groups); + $this->instance(RecurrenceSetRepository::class, $this->rset); + $this->instance(SchedulesRepository::class, $this->schedules); + + $this->authenticate(); + } + + protected function handleTest(string $id, array $data): void + { + $this->response = $this->patchJson('api/schedules/' . $id, array_merge( + ['api_token' => $this->authToken], + $data + )); + } + + /** + * @test + * @throws \Source\Exceptions\EntityExistsException + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_updates_a_schedule(): void + { + $this->groups->create(new Group(1, '', '')); + $this->schedules->create(new Schedule(1, 1, Schedule::TYPE_USER_ACCESS, '', 1234, 'old', Carbon::now())); + + $this->handleTest(1, [ + 'type' => Schedule::TYPE_OPEN_MODE, + 'rset' => 'rset', + 'description' => 'new' + ]); + $this->response->assertStatus(200); + + $this->assertCount(1, $this->schedules->filter()); + $this->assertEquals('new', $this->schedules->filter()[0]->getDescription()); + $this->assertEquals(Schedule::TYPE_OPEN_MODE, $this->schedules->filter()[0]->getType()); + $this->assertEquals('rset', $this->schedules->filter()[0]->getRset()); + $this->response->assertJson(['schedule' => ['group_id' => 1, 'type' => Schedule::TYPE_OPEN_MODE]]); + } + + /** + * @test + * @throws \Source\Exceptions\EntityNotFoundException + */ + public function it_can_fail_to_create_a_schedule(): void + { + $this->rset->failParse = true; + $this->schedules->create(new Schedule(1, 1, Schedule::TYPE_USER_ACCESS, '', 1234, 'old', Carbon::now())); + $this->handleTest(1, [ + 'type' => Schedule::TYPE_OPEN_MODE, + 'rset' => 'rset', + 'description' => 'new', + 'duration' => -1, + 'group_id' => 1, + ]); + + $this->response->assertStatus(422); + + $this->assertEquals('old', $this->schedules->filter()[0]->getDescription()); + $this->response->assertJson(['errors' => [ + 'Invalid group specified.', + 'Duration cannot be negative.', + 'Invalid rset string.', + ]]); + } +} -- GitLab From f514ca95e5fe6bb8891af9ccd851ee7699f55e27 Mon Sep 17 00:00:00 2001 From: dakriy Date: Wed, 17 Jun 2020 02:14:43 -0700 Subject: [PATCH 34/38] Remove unused exception --- .../src/Exceptions/NotImplementedException.php | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 src/backend/src/Exceptions/NotImplementedException.php diff --git a/src/backend/src/Exceptions/NotImplementedException.php b/src/backend/src/Exceptions/NotImplementedException.php deleted file mode 100644 index a4e23cc3..00000000 --- a/src/backend/src/Exceptions/NotImplementedException.php +++ /dev/null @@ -1,15 +0,0 @@ - Date: Wed, 17 Jun 2020 02:32:05 -0700 Subject: [PATCH 35/38] Attempt to add code coverage to gitlab --- .gitlab-ci.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fdafbbed..9d75b493 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,6 +10,7 @@ variables: stages: - build - test + - coverage - deploy build_web_backend: @@ -60,7 +61,7 @@ test_web_backend_database: - vendor/bin/phpunit --testsuite Database generate_api_docs: - stage: test + stage: coverage script: - cd src/backend - "if (php artisan apidoc:generate | grep \"Exception\") then echo \"Failed to generate API docs.\" && false; else true; fi" @@ -69,6 +70,16 @@ generate_api_docs: - src/backend/public/docs expire_in: 1 day +generate_code_coverage: + stage: coverage + script: + - cd src/backend + - phpdbg -qrr vendor/bin/phpunit --coverage-xml cov + artifacts: + reports: + cobertura: src/backend/cov + + deploy_backend_production: stage: deploy before_script: -- GitLab From a66872f336bdd3945997c7fedc359ebda5511c58 Mon Sep 17 00:00:00 2001 From: dakriy Date: Wed, 17 Jun 2020 02:49:49 -0700 Subject: [PATCH 36/38] Remove unused function and add code coverage generation --- .gitlab-ci.yml | 7 ++++--- src/backend/src/Entities/User.php | 14 -------------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9d75b493..a4c9ce6f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -74,10 +74,11 @@ generate_code_coverage: stage: coverage script: - cd src/backend - - phpdbg -qrr vendor/bin/phpunit --coverage-xml cov + - phpdbg -qrr vendor/bin/phpunit --coverage-html cov artifacts: - reports: - cobertura: src/backend/cov + paths: + - src/backend/cov + expire_in: 30 days deploy_backend_production: diff --git a/src/backend/src/Entities/User.php b/src/backend/src/Entities/User.php index eb8cf189..f691dcc5 100644 --- a/src/backend/src/Entities/User.php +++ b/src/backend/src/Entities/User.php @@ -186,20 +186,6 @@ class User $this->id = $id; } - /** - * @param string|null $email - * @param string|null $password - * @return bool - */ - public function matchCredentials(?string $email, ?string $password): bool - { - if (!$this->password) { - return false; - } - - return $this->hasEmailOf($email) && $this->password->matches($password); - } - /** * @return string */ -- GitLab From b82f84e001193471c7008146e1d680b51173af70 Mon Sep 17 00:00:00 2001 From: dakriy Date: Wed, 17 Jun 2020 03:04:27 -0700 Subject: [PATCH 37/38] increase memory limit for phpdbg --- .gitlab-ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a4c9ce6f..1afa771b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -74,13 +74,12 @@ generate_code_coverage: stage: coverage script: - cd src/backend - - phpdbg -qrr vendor/bin/phpunit --coverage-html cov + - phpdbg -qrr -d memory_limit=256M vendor/bin/phpunit --coverage-html cov artifacts: paths: - src/backend/cov expire_in: 30 days - deploy_backend_production: stage: deploy before_script: -- GitLab From 86f588ca4d0430f810e5d94aaf8b96fa7a9de714 Mon Sep 17 00:00:00 2001 From: dakriy Date: Wed, 17 Jun 2020 03:06:32 -0700 Subject: [PATCH 38/38] Remove unused function --- src/backend/src/Entities/User.php | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/backend/src/Entities/User.php b/src/backend/src/Entities/User.php index f691dcc5..1728164d 100644 --- a/src/backend/src/Entities/User.php +++ b/src/backend/src/Entities/User.php @@ -262,19 +262,6 @@ class User return $this->getFirstName() === $name; } - /** - * @param \Source\Entities\User|null $user - * @return bool - */ - public function is(?User $user): bool - { - if (!$user) { - return false; - } - - return $this->hasEmailOf($user); - } - /** * @param \Carbon\Carbon|null $date * @return bool -- GitLab