diff --git a/.env.example b/.env.example index 1d5caf3..da5698c 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,5 @@ APP_NAME=Laravel +APP_NAME=Laravel APP_ENV=local APP_KEY= APP_DEBUG=true diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 15258a5..0b78f32 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -8,6 +8,7 @@ use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Database\Query\Builder; use Illuminate\Support\ServiceProvider; +use Illuminate\Support\Facades\Schema; class AppServiceProvider extends ServiceProvider { @@ -34,5 +35,7 @@ public function boot() 'office' => Office::class, 'user' => User::class ]); + + Schema::defaultStringLength(191); } } diff --git a/composer.lock b/composer.lock index c38d975..2f85e0f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6aee78c7a3c32b78c1a7c794189d8d69", + "content-hash": "6cadd819a6415b190ae2704ced6e6c8b", "packages": [ { "name": "asm89/stack-cors", @@ -744,16 +744,16 @@ }, { "name": "guzzlehttp/promises", - "version": "1.4.1", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d" + "reference": "136a635e2b4a49b9d79e9c8fee267ffb257fdba0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/8e7d04f1f6450fef59366c399cfad4b9383aa30d", - "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d", + "url": "https://api.github.com/repos/guzzle/promises/zipball/136a635e2b4a49b9d79e9c8fee267ffb257fdba0", + "reference": "136a635e2b4a49b9d79e9c8fee267ffb257fdba0", "shasum": "" }, "require": { @@ -765,7 +765,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.5-dev" } }, "autoload": { @@ -781,10 +781,25 @@ "MIT" ], "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" } ], "description": "Guzzle promises library", @@ -793,9 +808,23 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/1.4.1" + "source": "https://github.com/guzzle/promises/tree/1.5.0" }, - "time": "2021-03-07T09:25:29+00:00" + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2021-10-07T13:05:22+00:00" }, { "name": "guzzlehttp/psr7", @@ -914,16 +943,16 @@ }, { "name": "laravel/framework", - "version": "v8.63.0", + "version": "v8.64.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "8f3d280f36a427730c8c8fa34316c79eed38781e" + "reference": "3337c029e1bb31d9712d27437cc27010ba302c9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/8f3d280f36a427730c8c8fa34316c79eed38781e", - "reference": "8f3d280f36a427730c8c8fa34316c79eed38781e", + "url": "https://api.github.com/repos/laravel/framework/zipball/3337c029e1bb31d9712d27437cc27010ba302c9e", + "reference": "3337c029e1bb31d9712d27437cc27010ba302c9e", "shasum": "" }, "require": { @@ -1081,20 +1110,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2021-10-05T14:04:25+00:00" + "time": "2021-10-12T13:43:13+00:00" }, { "name": "laravel/sanctum", - "version": "v2.11.2", + "version": "v2.11.4", "source": { "type": "git", "url": "https://github.com/laravel/sanctum.git", - "reference": "b21e65cbe13896946986cb0868180cd69e1bd5d3" + "reference": "2cc0c0f79eb92578f606f6130fafd31b18229db1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sanctum/zipball/b21e65cbe13896946986cb0868180cd69e1bd5d3", - "reference": "b21e65cbe13896946986cb0868180cd69e1bd5d3", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/2cc0c0f79eb92578f606f6130fafd31b18229db1", + "reference": "2cc0c0f79eb92578f606f6130fafd31b18229db1", "shasum": "" }, "require": { @@ -1145,20 +1174,20 @@ "issues": "https://github.com/laravel/sanctum/issues", "source": "https://github.com/laravel/sanctum" }, - "time": "2021-06-15T15:56:21+00:00" + "time": "2021-10-13T13:38:15+00:00" }, { "name": "laravel/serializable-closure", - "version": "v1.0.2", + "version": "v1.0.3", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "679e24d36ff8b9be0e36f5222244ec8602e18867" + "reference": "6cfc678735f22ccedad761b8cae2bab14c3d8e5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/679e24d36ff8b9be0e36f5222244ec8602e18867", - "reference": "679e24d36ff8b9be0e36f5222244ec8602e18867", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/6cfc678735f22ccedad761b8cae2bab14c3d8e5b", + "reference": "6cfc678735f22ccedad761b8cae2bab14c3d8e5b", "shasum": "" }, "require": { @@ -1204,7 +1233,7 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2021-09-29T13:25:52+00:00" + "time": "2021-10-07T14:00:57+00:00" }, { "name": "laravel/tinker", @@ -1812,21 +1841,21 @@ }, { "name": "nette/schema", - "version": "v1.2.1", + "version": "v1.2.2", "source": { "type": "git", "url": "https://github.com/nette/schema.git", - "reference": "f5ed39fc96358f922cedfd1e516f0dadf5d2be0d" + "reference": "9a39cef03a5b34c7de64f551538cbba05c2be5df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/schema/zipball/f5ed39fc96358f922cedfd1e516f0dadf5d2be0d", - "reference": "f5ed39fc96358f922cedfd1e516f0dadf5d2be0d", + "url": "https://api.github.com/repos/nette/schema/zipball/9a39cef03a5b34c7de64f551538cbba05c2be5df", + "reference": "9a39cef03a5b34c7de64f551538cbba05c2be5df", "shasum": "" }, "require": { - "nette/utils": "^3.1.4 || ^4.0", - "php": ">=7.1 <8.1" + "nette/utils": "^2.5.7 || ^3.1.5 || ^4.0", + "php": ">=7.1 <8.2" }, "require-dev": { "nette/tester": "^2.3 || ^2.4", @@ -1868,9 +1897,9 @@ ], "support": { "issues": "https://github.com/nette/schema/issues", - "source": "https://github.com/nette/schema/tree/v1.2.1" + "source": "https://github.com/nette/schema/tree/v1.2.2" }, - "time": "2021-03-04T17:51:11+00:00" + "time": "2021-10-15T11:40:02+00:00" }, { "name": "nette/utils", @@ -2407,30 +2436,30 @@ }, { "name": "psr/log", - "version": "2.0.0", + "version": "1.1.4", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376" + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/ef29f6d262798707a9edd554e2b82517ef3a9376", - "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", "shasum": "" }, "require": { - "php": ">=8.0.0" + "php": ">=5.3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "1.1.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Log\\": "src" + "Psr\\Log\\": "Psr/Log/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2451,9 +2480,9 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/2.0.0" + "source": "https://github.com/php-fig/log/tree/1.1.4" }, - "time": "2021-07-14T16:41:46+00:00" + "time": "2021-05-03T11:20:27+00:00" }, { "name": "psr/simple-cache", @@ -2508,16 +2537,16 @@ }, { "name": "psy/psysh", - "version": "v0.10.8", + "version": "v0.10.9", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "e4573f47750dd6c92dca5aee543fa77513cbd8d3" + "reference": "01281336c4ae557fe4a994544f30d3a1bc204375" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/e4573f47750dd6c92dca5aee543fa77513cbd8d3", - "reference": "e4573f47750dd6c92dca5aee543fa77513cbd8d3", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/01281336c4ae557fe4a994544f30d3a1bc204375", + "reference": "01281336c4ae557fe4a994544f30d3a1bc204375", "shasum": "" }, "require": { @@ -2577,9 +2606,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.10.8" + "source": "https://github.com/bobthecow/psysh/tree/v0.10.9" }, - "time": "2021-04-10T16:23:39+00:00" + "time": "2021-10-10T13:37:39+00:00" }, { "name": "ralouphie/getallheaders", @@ -2627,16 +2656,16 @@ }, { "name": "ramsey/collection", - "version": "1.2.1", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/ramsey/collection.git", - "reference": "eaca1dc1054ddd10cbd83c1461907bee6fb528fa" + "reference": "cccc74ee5e328031b15640b51056ee8d3bb66c0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/collection/zipball/eaca1dc1054ddd10cbd83c1461907bee6fb528fa", - "reference": "eaca1dc1054ddd10cbd83c1461907bee6fb528fa", + "url": "https://api.github.com/repos/ramsey/collection/zipball/cccc74ee5e328031b15640b51056ee8d3bb66c0a", + "reference": "cccc74ee5e328031b15640b51056ee8d3bb66c0a", "shasum": "" }, "require": { @@ -2690,7 +2719,7 @@ ], "support": { "issues": "https://github.com/ramsey/collection/issues", - "source": "https://github.com/ramsey/collection/tree/1.2.1" + "source": "https://github.com/ramsey/collection/tree/1.2.2" }, "funding": [ { @@ -2702,7 +2731,7 @@ "type": "tidelift" } ], - "time": "2021-08-06T03:41:06+00:00" + "time": "2021-10-10T03:01:02+00:00" }, { "name": "ramsey/uuid", @@ -5533,19 +5562,20 @@ }, { "name": "facade/ignition", - "version": "2.14.0", + "version": "2.15.0", "source": { "type": "git", "url": "https://github.com/facade/ignition.git", - "reference": "c6126e291bd44ad3fe482537a145fc70e3320598" + "reference": "3ee6e94815462bcf09bca0efc1c9069685df8da3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/facade/ignition/zipball/c6126e291bd44ad3fe482537a145fc70e3320598", - "reference": "c6126e291bd44ad3fe482537a145fc70e3320598", + "url": "https://api.github.com/repos/facade/ignition/zipball/3ee6e94815462bcf09bca0efc1c9069685df8da3", + "reference": "3ee6e94815462bcf09bca0efc1c9069685df8da3", "shasum": "" }, "require": { + "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", "facade/flare-client-php": "^1.9.1", @@ -5605,7 +5635,7 @@ "issues": "https://github.com/facade/ignition/issues", "source": "https://github.com/facade/ignition" }, - "time": "2021-10-01T12:58:45+00:00" + "time": "2021-10-11T15:24:06+00:00" }, { "name": "facade/ignition-contracts", @@ -5849,16 +5879,16 @@ }, { "name": "laravel/sail", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/laravel/sail.git", - "reference": "5c91d33949e43500dc1d49abc5d7c2ffb6c96f44" + "reference": "80f6cd93844e87ebc2e7310f9a9b9917473f5eb0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sail/zipball/5c91d33949e43500dc1d49abc5d7c2ffb6c96f44", - "reference": "5c91d33949e43500dc1d49abc5d7c2ffb6c96f44", + "url": "https://api.github.com/repos/laravel/sail/zipball/80f6cd93844e87ebc2e7310f9a9b9917473f5eb0", + "reference": "80f6cd93844e87ebc2e7310f9a9b9917473f5eb0", "shasum": "" }, "require": { @@ -5905,7 +5935,7 @@ "issues": "https://github.com/laravel/sail/issues", "source": "https://github.com/laravel/sail" }, - "time": "2021-10-01T13:32:17+00:00" + "time": "2021-10-12T15:38:11+00:00" }, { "name": "mockery/mockery", @@ -7903,7 +7933,7 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^8.0" + "php": "^7.3|^8.0" }, "platform-dev": [], "plugin-api-version": "2.1.0" diff --git a/tests/Feature/UserReservationControllerTest.php b/tests/Feature/UserReservationControllerTest.php index ae6bbb0..544cf0a 100644 --- a/tests/Feature/UserReservationControllerTest.php +++ b/tests/Feature/UserReservationControllerTest.php @@ -8,9 +8,6 @@ use App\Notifications\NewHostReservation; use App\Notifications\NewUserReservation; use Illuminate\Foundation\Testing\LazilyRefreshDatabase; -use Illuminate\Foundation\Testing\RefreshDatabase; -use Illuminate\Foundation\Testing\WithFaker; -use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Notification; use Tests\TestCase; @@ -28,7 +25,7 @@ public function itListsReservationsThatBelongToTheUser() [$reservation] = Reservation::factory()->for($user)->count(2)->create(); $image = $reservation->office->images()->create([ - 'path' => 'office_image.jpg' + 'path' => 'office_image.jpg', ]); $reservation->office()->update(['featured_image_id' => $image->id]); @@ -117,7 +114,7 @@ public function itFiltersResultsByStatus() $user = User::factory()->create(); $reservation = Reservation::factory()->for($user)->create([ - 'status' => Reservation::STATUS_ACTIVE + 'status' => Reservation::STATUS_ACTIVE, ]); $reservation2 = Reservation::factory()->for($user)->cancelled()->create(); @@ -233,11 +230,11 @@ public function itCannotMakeReservationOnOfficeThatIsPendingOrHidden() $user = User::factory()->create(); $office = Office::factory()->create([ - 'approval_status' => Office::APPROVAL_PENDING + 'approval_status' => Office::APPROVAL_PENDING, ]); $office2 = Office::factory()->create([ - 'hidden' => true + 'hidden' => true, ]); $this->actingAs($user); @@ -376,4 +373,119 @@ public function itSendsNotificationsOnNewReservations() $response->assertCreated(); } + + /** @test */ + public function itDoesNotAllowCancellationOfReservationsThatIsCancelled() + { + $user = User::factory()->create(); + + $office = Office::factory()->create(); + + $reservation = Reservation::factory()->for($office)->for($user)->create([ + 'status' => Reservation::STATUS_CANCELLED, + ]); + + $this->actingAs($user); + + $response = $this->deleteJson('/api/reservations/'.$reservation->id); + + $response->assertUnprocessable() + ->assertJsonValidationErrors(['reservation' => 'You cannot cancel this reservation']); + $this->assertModelExists($reservation); + $this->assertDatabaseHas('reservations', [ + 'id' => $reservation->id, + ]); + } + + /** @test */ + public function itDoesNotAllowCancellationOfReservationsThatHasStarted() + { + $user = User::factory()->create(); + + $office = Office::factory()->create(); + + $reservation = Reservation::factory()->for($office)->for($user)->create([ + 'start_date' => now()->addDays(-1)->toDateString(), + ]); + + $this->actingAs($user); + + $response = $this->deleteJson('/api/reservations/'.$reservation->id); + + $response->assertUnprocessable() + ->assertJsonValidationErrors(['reservation' => 'You cannot cancel this reservation']); + $this->assertModelExists($reservation); + $this->assertDatabaseHas('reservations', [ + 'id' => $reservation->id, + ]); + } + + /** @test */ + public function itDoesNotAllowCancellationOfReservationsThatDoesNotBelongsToYou() + { + $user = User::factory()->create(); + $new_user = User::factory()->create(); + + $office = Office::factory()->create(); + + $reservation = Reservation::factory()->for($office)->for($user)->create([ + 'status' => Reservation::STATUS_CANCELLED, + ]); + + $this->actingAs($new_user); + + $response = $this->deleteJson('/api/reservations/'.$reservation->id); + + $response->assertUnprocessable() + ->assertJsonValidationErrors(['reservation' => 'You cannot cancel this reservation']); + $this->assertModelExists($reservation); + $this->assertDatabaseHas('reservations', [ + 'id' => $reservation->id, + ]); + } + + /** @test */ + public function itCanclledReservationThatStartDateIsInFuture() + { + $user = User::factory()->create(); + + $office = Office::factory()->create(); + + $reservation = Reservation::factory()->for($office)->for($user)->create([ + 'start_date' => now()->addDay()->toDateString(), + ]); + + $this->actingAs($user); + + $response = $this->deleteJson('/api/reservations/'.$reservation->id); + + $response->assertOk() + ->assertStatus(200) + ->assertJsonPath('data.user_id', $user->id) + ->assertJsonPath('data.office_id', $office->id) + ->assertJsonPath('data.status', Reservation::STATUS_CANCELLED); + } + + /** @test */ + public function itCanclledReservationThatStartDateIsInFutureAndActive() + { + $user = User::factory()->create(); + + $office = Office::factory()->create(); + + $reservation = Reservation::factory()->for($office)->for($user)->create([ + 'status' => Reservation::STATUS_ACTIVE, + 'start_date' => now()->addDay()->toDateString(), + ]); + + $this->actingAs($user); + + $response = $this->deleteJson('/api/reservations/'.$reservation->id); + + $response->assertOk() + ->assertStatus(200) + ->assertJsonPath('data.user_id', $user->id) + ->assertJsonPath('data.office_id', $office->id) + ->assertJsonPath('data.status', Reservation::STATUS_CANCELLED); + } }