Skip to content

Commit 082d3ec

Browse files
Add test for console command and requests not covered before, rename test methods according to convention
1 parent dc67247 commit 082d3ec

28 files changed

+303
-147
lines changed

app/Exports/BookingsExportSpreadsheet.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ class BookingsExportSpreadsheet extends Spreadsheet
1717
* @param Collection<Booking> $bookings
1818
*/
1919
public function __construct(
20-
private Event $event,
21-
private BookingOption $bookingOption,
22-
private Collection $bookings
20+
private readonly Event $event,
21+
private readonly BookingOption $bookingOption,
22+
private readonly Collection $bookings
2323
) {
2424
parent::__construct();
2525

app/Exports/Traits/ExportsToExcel.php

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,6 @@
1111
*/
1212
trait ExportsToExcel
1313
{
14-
public function createSheetFromCollection(
15-
string $title,
16-
Collection $collection,
17-
array $headerColumns,
18-
\Closure $rowProvider
19-
): Worksheet {
20-
$sheet = $this->createSheet();
21-
self::fillSheetFromCollection($sheet, $title, $collection, $headerColumns, $rowProvider);
22-
return $sheet;
23-
}
24-
2514
public function setMetaData(string $title): void
2615
{
2716
$this->getProperties()
@@ -35,7 +24,7 @@ public static function fillSheetFromCollection(
3524
Collection $collection,
3625
array $headerColumns,
3726
\Closure $rowProvider
38-
): void {
27+
): Worksheet {
3928
$worksheet->setTitle(substr(str_replace(['*', ':', '/', '\\', '?', '[', ']'], '', $title), 0, 31));
4029
$worksheet->fromArray([
4130
[$title],
@@ -48,6 +37,8 @@ public static function fillSheetFromCollection(
4837
self::formatHeadline($worksheet, $columnCount);
4938
$worksheet->setAutoFilter([1, 3, $columnCount, 3]);
5039
self::setAutoSizeForColumns($worksheet, $columnCount);
40+
41+
return $worksheet;
5142
}
5243

5344
public static function formatHeadline(Worksheet $worksheet, int $columnCount): void

app/Http/Controllers/LocationController.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
use App\Http\Requests\LocationRequest;
77
use App\Models\Location;
88
use App\Models\Organization;
9-
use App\Models\User;
109
use Illuminate\Http\RedirectResponse;
1110
use Illuminate\Support\Facades\Session;
1211
use Illuminate\View\View;
@@ -41,7 +40,7 @@ public function create(): View
4140

4241
public function store(LocationRequest $request): RedirectResponse
4342
{
44-
$this->authorize('create', User::class);
43+
$this->authorize('create', Location::class);
4544

4645
$location = new Location();
4746
if ($location->fillAndSave($request->validated())) {

app/Models/Booking.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public function age(): Attribute
9494
return Attribute::get(fn () => Carbon::now()->floatDiffInYears($this->date_of_birth));
9595
}
9696

97-
public function bookedByUser()
97+
public function bookedByUser(): BelongsTo
9898
{
9999
return $this->belongsTo(User::class, 'booked_by_user_id');
100100
}
@@ -126,7 +126,7 @@ public function scopeGroup(Builder $query, Group|int $group): Builder
126126
);
127127
}
128128

129-
public function scopePaymentStatus(Builder $query, int|PaymentStatus $paymentStatus)
129+
public function scopePaymentStatus(Builder $query, int|PaymentStatus $paymentStatus): Builder
130130
{
131131
$payment = is_int($paymentStatus)
132132
? $paymentStatus

database/factories/BookingOptionFactory.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ public function definition(): array
2222
return [
2323
'name' => __('Booking option') . ' #' . $this->faker->unique()->randomNumber(),
2424
'description' => $this->faker->sentences(2, true),
25-
'available_from' => Carbon::yesterday()->startOfDay(),
26-
'available_until' => Carbon::tomorrow()->endOfDay(),
25+
'available_from' => $this->faker->dateTimeBetween('-30 years', '-1 day'),
26+
'available_until' => $this->faker->dateTimeBetween('+1 day', '+30 days'),
2727
'price' => $this->faker->randomFloat(2, 5, 100),
2828
];
2929
}

database/factories/EventFactory.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,12 @@ public function definition(): array
3535
];
3636
}
3737

38-
public function visibility(Visibility $visibility): static
38+
public function visibility(?Visibility $visibility): static
3939
{
40+
if ($visibility === null) {
41+
return $this;
42+
}
43+
4044
return $this->state(fn (array $attributes) => [
4145
'visibility' => $visibility,
4246
]);
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
namespace Tests\Feature\Console\Commands;
4+
5+
use App\Console\Commands\CheckDocumentsCommand;
6+
use App\Models\Document;
7+
use Illuminate\Foundation\Testing\RefreshDatabase;
8+
use Illuminate\Support\Facades\Storage;
9+
use PHPUnit\Framework\Attributes\CoversClass;
10+
use Symfony\Component\Console\Command\Command;
11+
use Tests\TestCase;
12+
use Tests\Traits\GeneratesTestData;
13+
14+
#[CoversClass(CheckDocumentsCommand::class)]
15+
#[CoversClass(Document::class)]
16+
class CheckDocumentsCommandTest extends TestCase
17+
{
18+
use GeneratesTestData;
19+
use RefreshDatabase;
20+
21+
public function testAllDocumentsOk(): void
22+
{
23+
self::createDocuments();
24+
25+
Storage::shouldReceive('exists')
26+
->andReturn(true);
27+
28+
$this->artisan('app:check-documents')
29+
->expectsOutput('All documents ok.')
30+
->assertSuccessful();
31+
}
32+
33+
public function testCommandDetectsMissingDocuments(): void
34+
{
35+
$existingDocuments = self::createDocuments();
36+
foreach ($existingDocuments as $document) {
37+
Storage::shouldReceive('exists')
38+
->with($document->path)
39+
->andReturn(true);
40+
}
41+
42+
$missingDocuments = self::createDocuments();
43+
foreach ($missingDocuments as $document) {
44+
Storage::shouldReceive('exists')
45+
->with($document->path)
46+
->andReturn(false);
47+
}
48+
49+
$command = $this->artisan('app:check-documents')
50+
->expectsOutput(sprintf('%d documents are missing.', count($missingDocuments)));
51+
foreach ($missingDocuments as $document) {
52+
$command->expectsOutputToContain($document->path . ' missing');
53+
}
54+
$command->assertExitCode(Command::FAILURE);
55+
}
56+
}

tests/Feature/Http/AccountControllerTest.php

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace Http;
3+
namespace Tests\Feature\Http;
44

55
use App\Http\Controllers\AccountController;
66
use App\Http\Requests\UserRequest;
@@ -18,24 +18,17 @@ class AccountControllerTest extends TestCase
1818
{
1919
use RefreshDatabase;
2020

21-
public function testAccountIsAccessibleWithCorrectAbility(): void
21+
public function testUserCanViewAccountOnlyWithCorrectAbility(): void
2222
{
2323
$this->assertUserCanGetOnlyWithAbility('/account', Ability::ViewAccount);
2424
}
2525

26-
public function testEditAccountIsAccessibleWithCorrectAbility(): void
26+
public function testUserCanOpenEditAccountFormOnlyWithCorrectAbility(): void
2727
{
2828
$this->assertUserCanGetOnlyWithAbility('/account/edit', Ability::EditAccount);
2929
}
3030

31-
public function testAccountCannotBeEditedWithoutAbility(): void
32-
{
33-
$this->actingAsUserWithAbility(Ability::ViewAccount);
34-
35-
$this->put('/account', $this->getRandomUserData())->assertForbidden();
36-
}
37-
38-
public function testAccountCanBeEditedWithAbility(): void
31+
public function testUserCanUpdateAccountWithCorrectAbility(): void
3932
{
4033
$this->actingAsUserWithAbility(Ability::EditAccount);
4134

@@ -44,7 +37,14 @@ public function testAccountCanBeEditedWithAbility(): void
4437
->assertRedirect('/account/edit');
4538
}
4639

47-
public function testAccountEditThrowsErrorsForInvalidData(): void
40+
public function testUserCannotUpdateAccountWithoutAbility(): void
41+
{
42+
$this->actingAsUserWithAbility(Ability::ViewAccount);
43+
44+
$this->put('/account', $this->getRandomUserData())->assertForbidden();
45+
}
46+
47+
public function testUserReceivesErrorMessagesForInvalidAccountData(): void
4848
{
4949
$this->actingAsUserWithAbility(Ability::EditAccount);
5050

@@ -63,7 +63,7 @@ private function getRandomUserData(): array
6363
);
6464
}
6565

66-
public function testListOfOwnAbilitiesIsAccessibleWithCorrectAbility(): void
66+
public function testUserCanViewAbilitiesOnlyWithCorrectAbility(): void
6767
{
6868
$this->assertUserCanGetOnlyWithAbility('/account/abilities', Ability::ViewAbilities);
6969
}

tests/Feature/Http/Auth/AuthenticationTest.php

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ class AuthenticationTest extends TestCase
2222
{
2323
use RefreshDatabase;
2424

25-
public function testLoginScreenCanBeRendered(): void
25+
public function testGuestCanViewLoginForm(): void
2626
{
2727
$this->assertGuestCanGet('/login');
2828
}
2929

30-
public function testUsersCanAuthenticateUsingTheLoginScreen(): void
30+
public function testActiveUserCanLogin(): void
3131
{
3232
$user = User::factory()->create();
3333

@@ -41,7 +41,7 @@ public function testUsersCanAuthenticateUsingTheLoginScreen(): void
4141
}
4242

4343
#[DataProvider('notActiveStatuses')]
44-
public function testUsersCannotAuthenticateIfNotActive(ActiveStatus $activeStatus): void
44+
public function testInactiveUserCannotLogin(ActiveStatus $activeStatus): void
4545
{
4646
$user = User::factory()
4747
->status($activeStatus)
@@ -63,7 +63,7 @@ public static function notActiveStatuses(): array
6363
];
6464
}
6565

66-
public function testUsersCannotAuthenticateWithInvalidPassword(): void
66+
public function testUserCannotLoginWithWrongPassword(): void
6767
{
6868
$user = User::factory()->create();
6969

@@ -74,4 +74,13 @@ public function testUsersCannotAuthenticateWithInvalidPassword(): void
7474

7575
$this->assertGuest();
7676
}
77+
78+
public function testUserCanLogout(): void
79+
{
80+
$this->actingAsAnyUser();
81+
82+
$this->post(route('logout'))
83+
->assertRedirect('/');
84+
$this->assertGuest();
85+
}
7786
}

tests/Feature/Http/Auth/EmailVerificationTest.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ class EmailVerificationTest extends TestCase
2727
{
2828
use RefreshDatabase;
2929

30-
public function testEmailVerificationPromptCanBeRendered(): void
30+
public function testUserCanOpenEmailVerificationPrompt(): void
3131
{
3232
$this->actingAs($this->createUnverifiedUser())
33-
->get('/')
33+
->get('/verify-email')
3434
->assertOk();
3535
}
3636

37-
public function testEmailVerificationLinkCanBeRequested(): void
37+
public function testUserCanRequestEmailVerificationLink(): void
3838
{
3939
Notification::fake();
4040

@@ -51,7 +51,7 @@ public function testEmailVerificationLinkCanBeRequested(): void
5151
});
5252
}
5353

54-
public function testEmailCanBeVerified(): void
54+
public function testUserCanVerifyEmail(): void
5555
{
5656
$user = $this->createUnverifiedUser();
5757

@@ -70,7 +70,7 @@ public function testEmailCanBeVerified(): void
7070
$this->assertTrue($user->fresh()->hasVerifiedEmail());
7171
}
7272

73-
public function testEmailIsNotVerifiedWithInvalidHash(): void
73+
public function testUserCannotVerifyEmailWithInvalidHash(): void
7474
{
7575
$user = $this->createUnverifiedUser();
7676

tests/Feature/Http/Auth/PasswordConfirmationTest.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class PasswordConfirmationTest extends TestCase
1313
{
1414
use RefreshDatabase;
1515

16-
public function testConfirmPasswordScreenCanBeRendered(): void
16+
public function testUserCanViewConfirmPasswordForm(): void
1717
{
1818
$user = User::factory()->create();
1919

@@ -22,10 +22,11 @@ public function testConfirmPasswordScreenCanBeRendered(): void
2222
$response->assertStatus(200);
2323
}
2424

25-
public function testPasswordCanBeConfirmed(): void
25+
public function testUserCanConfirmPassword(): void
2626
{
2727
$user = User::factory()->create();
2828

29+
/** @noinspection PhpUnhandledExceptionInspection */
2930
$this->actingAs($user)
3031
->post('/confirm-password', [
3132
'password' => 'password',
@@ -34,7 +35,7 @@ public function testPasswordCanBeConfirmed(): void
3435
->assertSessionHasNoErrors();
3536
}
3637

37-
public function testPasswordIsNotConfirmedWithInvalidPassword(): void
38+
public function testUserCannotConfirmWithInvalidPassword(): void
3839
{
3940
$user = User::factory()->create();
4041

0 commit comments

Comments
 (0)