diff --git a/.env.ci b/.env.ci new file mode 100644 index 00000000..9bd273d7 --- /dev/null +++ b/.env.ci @@ -0,0 +1,18 @@ +APP_NAME=Laravel +APP_ENV=testing +APP_KEY=base64:fDr4dLzbpxwzo9eDpy8of5b6/Dt2Pnvnd3lng8cf348= +APP_DEBUG=true +APP_URL=http://localhost +APP_TIMEZONE='Europe/Warsaw' + +LOG_CHANNEL=stack +LOG_LEVEL=debug + +BROADCAST_DRIVER=log +CACHE_DRIVER=file +FILESYSTEM_DRIVER=local +QUEUE_CONNECTION=redis +SESSION_DRIVER=file +SESSION_LIFETIME=120 + +MEMCACHED_HOST=memcached diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 899a93c0..6b0a21fc 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -36,5 +36,8 @@ jobs: - name: Run PHP linter run: composer cs + - name: Cache views + run: php artisan view:cache + - name: Execute tests run: php artisan test --env=ci diff --git a/bootstrap/app.php b/bootstrap/app.php new file mode 100644 index 00000000..b434403e --- /dev/null +++ b/bootstrap/app.php @@ -0,0 +1,24 @@ +singleton( + Illuminate\Contracts\Http\Kernel::class, + Blumilk\Meetup\Core\Http\Kernel::class +); + +$app->singleton( + Illuminate\Contracts\Console\Kernel::class, + Blumilk\Meetup\Core\Console\Kernel::class +); + +$app->singleton( + Illuminate\Contracts\Debug\ExceptionHandler::class, + Blumilk\Meetup\Core\Exceptions\Handler::class +); + +return $app; diff --git a/bootstrap/cache/.gitignore b/bootstrap/cache/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/bootstrap/cache/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/phpunit.xml b/phpunit.xml index 96c6ff7a..85cf3cf6 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -16,8 +16,8 @@ - - + + diff --git a/src/Http/Controllers/OrganizationProfileController.php b/src/Http/Controllers/OrganizationProfileController.php index 81127787..4eaab494 100644 --- a/src/Http/Controllers/OrganizationProfileController.php +++ b/src/Http/Controllers/OrganizationProfileController.php @@ -30,26 +30,26 @@ public function store(StoreOrganizationProfileRequest $request, Organization $or return redirect()->route("organizations.edit", $organization); } - public function edit(Organization $organization, OrganizationProfile $profile): View + public function edit(Organization $organization, OrganizationProfile $organizationProfile): View { return view("organizations.profiles.edit") ->with([ "organization" => $organization, - "profile" => $profile, + "profile" => $organizationProfile, "availableProfiles" => AvailableProfiles::casesToSelect(), ]); } - public function update(UpdateOrganizationProfileRequest $request, Organization $organization, OrganizationProfile $profile): RedirectResponse + public function update(UpdateOrganizationProfileRequest $request, Organization $organization, OrganizationProfile $organizationProfile): RedirectResponse { - $profile->update($request->validated()); + $organizationProfile->update($request->validated()); return redirect()->route("organizations.edit", $organization); } - public function destroy(Organization $organization, OrganizationProfile $profile): RedirectResponse + public function destroy(Organization $organization, OrganizationProfile $organizationProfile): RedirectResponse { - $profile->delete(); + $organizationProfile->delete(); return back(); } diff --git a/src/Http/Routing/WebRouting.php b/src/Http/Routing/WebRouting.php index 2228f3a2..dfdf88fd 100755 --- a/src/Http/Routing/WebRouting.php +++ b/src/Http/Routing/WebRouting.php @@ -93,9 +93,9 @@ public function wire(): void $this->router->controller(OrganizationProfileController::class)->group(function (): void { $this->router->get("/organizations/{organization}/profiles/create", "create")->name("organizations.profiles.create"); $this->router->post("/organizations/{organization}/profiles", "store")->name("organizations.profiles.store"); - $this->router->get("/organizations/{organization}/profiles/{profile}/edit", "edit")->name("organizations.profiles.edit"); - $this->router->put("/organizations/{organization}/profiles/{profile}", "update")->name("organizations.profiles.update"); - $this->router->delete("/organizations/{organization}/profiles/{profile}", "destroy")->name("organizations.profiles.destroy"); + $this->router->get("/organizations/{organization}/profiles/{organizationProfile}/edit", "edit")->name("organizations.profiles.edit")->scopeBindings(); + $this->router->put("/organizations/{organization}/profiles/{organizationProfile}", "update")->name("organizations.profiles.update")->scopeBindings(); + $this->router->delete("/organizations/{organization}/profiles/{organizationProfile}", "destroy")->name("organizations.profiles.destroy")->scopeBindings(); }); $this->router->controller(SpeakersController::class)->group(function (): void { diff --git a/src/Services/InvitationsService.php b/src/Services/InvitationsService.php index 625ef0cd..abc1b7dd 100755 --- a/src/Services/InvitationsService.php +++ b/src/Services/InvitationsService.php @@ -6,11 +6,12 @@ use Blumilk\Meetup\Core\Models\User; use Blumilk\Meetup\Core\Notifications\InvitationEmailNotification; +use Illuminate\Support\Facades\Notification; class InvitationsService { public function sendInvitation(User $senderUser, string $email): void { - $senderUser->notify(new InvitationEmailNotification($senderUser, $email)); + Notification::route("mail", $email)->notify(new InvitationEmailNotification($senderUser, $email)); } } diff --git a/tests/CreatesApplication.php b/tests/CreatesApplication.php new file mode 100644 index 00000000..efeacce9 --- /dev/null +++ b/tests/CreatesApplication.php @@ -0,0 +1,20 @@ +make(Kernel::class)->bootstrap(); + + return $app; + } +} diff --git a/tests/Feature/ContactTest.php b/tests/Feature/ContactTest.php new file mode 100644 index 00000000..d24e5e3f --- /dev/null +++ b/tests/Feature/ContactTest.php @@ -0,0 +1,57 @@ +get("/contact") + ->assertOk(); + } + + public function testUserCanSendContactForm(): void + { + Notification::fake(); + + $this->post("/contact", [ + "name" => "John", + "email" => "john.doe@example.com", + "subject" => "Test subject", + "message" => "Test message", + ]) + ->assertSessionHasNoErrors(); + + $this->assertDatabaseHas("contacts", [ + "name" => "John", + "email" => "john.doe@example.com", + "subject" => "Test subject", + "message" => "Test message", + ]); + + $contact = Contact::query()->first(); + + Notification::assertSentTo([$contact], ContactEmailNotification::class); + } + + public function testContactFormDataIsRequired(): void + { + $this->post("/contact") + ->assertInvalid([ + "name", + "email", + "subject", + "message", + ]); + } +} diff --git a/tests/Feature/InviteAdminTest.php b/tests/Feature/InviteAdminTest.php new file mode 100644 index 00000000..8b55fafb --- /dev/null +++ b/tests/Feature/InviteAdminTest.php @@ -0,0 +1,59 @@ + "admin"]); + $this->admin = User::factory()->create()->assignRole("admin"); + } + + public function testAdminCanSeeSendInvitationPage(): void + { + $this->actingAs($this->admin) + ->get("/invitation") + ->assertOk(); + } + + public function testAdminCanSendInvitation(): void + { + Notification::fake(); + + $this->actingAs($this->admin) + ->post("/invitation", [ + "email" => "invited@example.com", + ]) + ->assertSessionHasNoErrors(); + + Notification::assertSentOnDemand( + InvitationEmailNotification::class, + fn ($notification, $channels, $notifiable) => $notifiable->routes["mail"] === "invited@example.com", + ); + } + + public function testUserCannotSendInvitation(): void + { + $user = User::factory()->create(); + + $this->actingAs($user) + ->get("/invitation") + ->assertLocation("/"); + } +} diff --git a/tests/Feature/Meetups/BrowseMeetupsTest.php b/tests/Feature/Meetups/BrowseMeetupsTest.php new file mode 100644 index 00000000..7e355061 --- /dev/null +++ b/tests/Feature/Meetups/BrowseMeetupsTest.php @@ -0,0 +1,71 @@ + "admin"]); + $this->admin = User::factory()->create()->assignRole("admin"); + } + + public function testUserCanSeeMeetupsList(): void + { + $meetups = Meetup::factory() + ->count(15) + ->for($this->admin) + ->create(); + + $this->assertDatabaseCount("meetups", 15); + + $response = $this->get(route("meetups")) + ->assertOk(); + + foreach ($meetups as $meetup) { + $response->assertSee($meetup->logo_path) + ->assertSee($meetup->title) + ->assertSee($meetup->date->toDateString()) + ->assertSee($meetup->place); + } + } + + public function testMeetupsListIsPaginated(): void + { + Meetup::factory() + ->count(30) + ->for($this->admin) + ->create(); + + $meetups = Meetup::query() + ->latest() + ->skip(20) + ->take(10); + + $this->assertDatabaseCount("meetups", 30); + + $response = $this->get(route("meetups") . "?page=2") + ->assertOk(); + + foreach ($meetups as $meetup) { + $response->assertSee($meetup->logo_path) + ->assertSee($meetup->title) + ->assertSee($meetup->date->format("Y-m-d h:i")) + ->assertSee($meetup->place); + } + } +} diff --git a/tests/Feature/Meetups/CreateMeetupsTest.php b/tests/Feature/Meetups/CreateMeetupsTest.php new file mode 100644 index 00000000..73d55ef7 --- /dev/null +++ b/tests/Feature/Meetups/CreateMeetupsTest.php @@ -0,0 +1,68 @@ + "admin"]); + $this->admin = User::factory()->create()->assignRole("admin"); + } + + public function testAdminCanCreateMeetup(): void + { + $this->actingAs($this->admin) + ->get(route("meetups.create")) + ->assertOk(); + + $this->actingAs($this->admin) + ->post(route("meetups.store"), [ + "title" => "Test Meetup", + "description" => "Description", + "date" => Carbon::parse("2022-12-12 12:00:00"), + "place" => "Place", + "language" => "en", + "organizations" => "", + "speakers" => "", + ]) + ->assertSessionHasNoErrors() + ->assertRedirect(); + + $this->assertDatabaseHas("meetups", [ + "user_id" => $this->admin->id, + "title" => "Test Meetup", + "description" => "Description", + "date" => Carbon::parse("2022-12-12 12:00:00"), + "place" => "Place", + "language" => "en", + ]); + } + + public function testUserCannotCreateMeetup(): void + { + $user = User::factory()->create(); + + $this->actingAs($user) + ->get(route("meetups.create")) + ->assertForbidden(); + + $this->actingAs($user) + ->post(route("meetups.store")) + ->assertForbidden(); + } +} diff --git a/tests/Feature/Meetups/DeleteMeetupsTest.php b/tests/Feature/Meetups/DeleteMeetupsTest.php new file mode 100644 index 00000000..c9ba743f --- /dev/null +++ b/tests/Feature/Meetups/DeleteMeetupsTest.php @@ -0,0 +1,48 @@ + "admin"]); + $this->admin = User::factory()->create()->assignRole("admin"); + } + + public function testAdminCanDeleteMeetup(): void + { + $meetup = Meetup::factory()->for($this->admin)->create(); + + $this->actingAs($this->admin) + ->delete(route("meetups.destroy", $meetup)) + ->assertRedirect(); + + $this->assertModelMissing($meetup); + } + + public function testUserCannotDeleteMeetup(): void + { + $meetup = Meetup::factory()->for($this->admin)->create(); + + $user = User::factory()->create(); + + $this->actingAs($user) + ->delete(route("meetups.destroy", $meetup)) + ->assertForbidden(); + } +} diff --git a/tests/Feature/Meetups/EditMeetupsTest.php b/tests/Feature/Meetups/EditMeetupsTest.php new file mode 100644 index 00000000..ced2032a --- /dev/null +++ b/tests/Feature/Meetups/EditMeetupsTest.php @@ -0,0 +1,74 @@ + "admin"]); + $this->admin = User::factory()->create()->assignRole("admin"); + } + + public function testAdminCanEditMeetup(): void + { + $meetup = Meetup::factory()->for($this->admin)->create(); + + $this->actingAs($this->admin) + ->get(route("meetups.edit", $meetup)) + ->assertOk(); + + $this->actingAs($this->admin) + ->put(route("meetups.update", $meetup), [ + "title" => "Test Meetup", + "description" => "Description", + "date" => Carbon::parse("2022-12-12 12:00:00"), + "place" => "Place", + "language" => "en", + "organizations" => "", + "speakers" => "", + ]) + ->assertSessionHasNoErrors() + ->assertRedirect(); + + $this->assertDatabaseHas("meetups", [ + "user_id" => $this->admin->id, + "title" => "Test Meetup", + "description" => "Description", + "date" => Carbon::parse("2022-12-12 12:00:00"), + "place" => "Place", + "language" => "en", + ]); + } + + public function testUserCannotEditMeetup(): void + { + $user = User::factory()->create(); + $meetup = Meetup::factory()->for($user)->create(); + + $user = User::factory()->create(); + + $this->actingAs($user) + ->get(route("meetups.edit", $meetup)) + ->assertForbidden(); + + $this->actingAs($user) + ->put(route("meetups.update", $meetup)) + ->assertForbidden(); + } +} diff --git a/tests/Feature/NewsletterTest.php b/tests/Feature/NewsletterTest.php new file mode 100644 index 00000000..18e16541 --- /dev/null +++ b/tests/Feature/NewsletterTest.php @@ -0,0 +1,39 @@ +get("/newsletter") + ->assertOk(); + } + + public function testUserCanSubscribeNewsletter(): void + { + Notification::fake(); + + $this->post("/newsletter/subscribe", [ + "email" => "subscriber@example.com", + ]) + ->assertSessionHasNoErrors() + ->assertOk(); + + $subscriber = NewsletterSubscriber::query() + ->where("email", "subscriber@example.com") + ->first(); + + Notification::assertSentTo($subscriber, NewsletterNotification::class); + } +} diff --git a/tests/Feature/Organizations/BrowseOrganizationsTest.php b/tests/Feature/Organizations/BrowseOrganizationsTest.php new file mode 100644 index 00000000..ad7d2051 --- /dev/null +++ b/tests/Feature/Organizations/BrowseOrganizationsTest.php @@ -0,0 +1,52 @@ +count(10)->create(); + + $this->assertDatabaseCount("organizations", 10); + + $response = $this->get(route("organizations")) + ->assertOk(); + + foreach ($organizations as $organization) { + $response->assertSee($organization->name) + ->assertSee($organization->logo_path) + ->assertSee($organization->description); + } + } + + public function testOrganizationsListIsPaginated(): void + { + Organization::factory()->count(30)->create(); + + $this->assertDatabaseCount("organizations", 30); + + $organizations = Meetup::query() + ->latest() + ->skip(20) + ->take(10); + + $response = $this->get(route("organizations") . "?page=2") + ->assertOk(); + + foreach ($organizations as $organization) { + $response->assertSee($organization->name) + ->assertSee($organization->logo_path) + ->assertSee($organization->description); + } + } +} diff --git a/tests/Feature/Organizations/CreateOrganizationsTest.php b/tests/Feature/Organizations/CreateOrganizationsTest.php new file mode 100644 index 00000000..3d860fe9 --- /dev/null +++ b/tests/Feature/Organizations/CreateOrganizationsTest.php @@ -0,0 +1,69 @@ + "admin"]); + $this->admin = User::factory()->create()->assignRole("admin"); + } + + public function testAdminCanCreateOrganization(): void + { + $this->actingAs($this->admin) + ->get(route("organizations.create")) + ->assertOk(); + + $this->actingAs($this->admin) + ->post(route("organizations.store"), [ + "name" => "Test organization", + "description" => "Test organization description", + "location" => "Panama", + "organization_type" => "test", + "foundation_date" => Carbon::parse("2022-01-01 10:00:00"), + "number_of_employees" => 1000, + "website_url" => "https://testorganization.info", + ]) + ->assertSessionHasNoErrors() + ->assertRedirect(); + + $this->assertDatabaseHas("organizations", [ + "name" => "Test organization", + "description" => "Test organization description", + "location" => "Panama", + "organization_type" => "test", + "foundation_date" => Carbon::parse("2022-01-01 10:00:00"), + "number_of_employees" => 1000, + "website_url" => "https://testorganization.info", + ]); + } + + public function testUserCannotCreateOrganization(): void + { + $user = User::factory()->create(); + + $this->actingAs($user) + ->get(route("organizations.create")) + ->assertForbidden(); + + $this->actingAs($user) + ->post(route("organizations.store")) + ->assertForbidden(); + } +} diff --git a/tests/Feature/Organizations/DeleteOrganizationsTest.php b/tests/Feature/Organizations/DeleteOrganizationsTest.php new file mode 100644 index 00000000..d318beda --- /dev/null +++ b/tests/Feature/Organizations/DeleteOrganizationsTest.php @@ -0,0 +1,48 @@ + "admin"]); + $this->admin = User::factory()->create()->assignRole("admin"); + } + + public function testAdminCanDeleteOrganization(): void + { + $organization = Organization::factory()->create(); + + $this->actingAs($this->admin) + ->delete(route("organizations.destroy", $organization)) + ->assertRedirect(); + + $this->assertModelMissing($organization); + } + + public function testUserCannotDeleteOrganization(): void + { + $user = User::factory()->create(); + + $organization = Organization::factory()->create(); + + $this->actingAs($user) + ->delete(route("organizations.destroy", $organization)) + ->assertForbidden(); + } +} diff --git a/tests/Feature/Organizations/EditOrganizationsTest.php b/tests/Feature/Organizations/EditOrganizationsTest.php new file mode 100644 index 00000000..2cdff16a --- /dev/null +++ b/tests/Feature/Organizations/EditOrganizationsTest.php @@ -0,0 +1,69 @@ + "admin"]); + $this->admin = User::factory()->create()->assignRole("admin"); + } + + public function testAdminCanEditOrganization(): void + { + $organization = Organization::factory()->create(); + + $this->actingAs($this->admin) + ->get(route("organizations.edit", $organization)) + ->assertOk(); + + $this->actingAs($this->admin) + ->put(route("organizations.update", $organization), [ + "name" => "Test organization", + "description" => "Test description", + "location" => "Panama", + "organization_type" => "test", + "foundation_date" => Carbon::parse("2022-01-01 10:00:00"), + "number_of_employees" => 1000, + "website_url" => "https://testorganization.info", + ]) + ->assertSessionHasNoErrors() + ->assertRedirect(); + + $this->assertDatabaseHas("organizations", [ + "name" => "Test organization", + "description" => "Test description", + "location" => "Panama", + "organization_type" => "test", + "foundation_date" => Carbon::parse("2022-01-01 10:00:00"), + "number_of_employees" => 1000, + "website_url" => "https://testorganization.info", + ]); + } + + public function testUserCannotEditOrganization(): void + { + $organization = Organization::factory()->create(); + $user = User::factory()->create(); + + $this->actingAs($user) + ->get(route("organizations.edit", $organization)) + ->assertForbidden(); + } +} diff --git a/tests/Feature/Organizations/Profiles/CreateOrganizationProfilesTest.php b/tests/Feature/Organizations/Profiles/CreateOrganizationProfilesTest.php new file mode 100644 index 00000000..6584057c --- /dev/null +++ b/tests/Feature/Organizations/Profiles/CreateOrganizationProfilesTest.php @@ -0,0 +1,64 @@ + "admin"]); + $this->admin = User::factory()->create()->assignRole("admin"); + } + + public function testAdminCanCreateOrganizationProfile(): void + { + $organization = Organization::factory()->create(); + + $this->actingAs($this->admin) + ->get(route("organizations.profiles.create", $organization)) + ->assertOk(); + + $this->actingAs($this->admin) + ->post(route("organizations.profiles.store", $organization), [ + "label" => "Facebook", + "link" => "https://facebook.com", + ]) + ->assertSessionHasNoErrors() + ->assertRedirect(); + + $this->assertDatabaseHas("organization_profiles", [ + "organization_id" => $organization->id, + "label" => "Facebook", + "link" => "https://facebook.com", + ]); + } + + public function testUserCannotCreateOrganizationProfile(): void + { + $user = User::factory()->create(); + + $organization = Organization::factory()->create(); + + $this->actingAs($user) + ->get(route("organizations.profiles.create", $organization)) + ->assertForbidden(); + + $this->actingAs($user) + ->post(route("organizations.profiles.store", $organization)) + ->assertForbidden(); + } +} diff --git a/tests/Feature/Organizations/Profiles/DeleteOrganizationProfilesTest.php b/tests/Feature/Organizations/Profiles/DeleteOrganizationProfilesTest.php new file mode 100644 index 00000000..37f96867 --- /dev/null +++ b/tests/Feature/Organizations/Profiles/DeleteOrganizationProfilesTest.php @@ -0,0 +1,63 @@ + "admin"]); + $this->admin = User::factory()->create()->assignRole("admin"); + } + + public function testAdminCanDeleteOrganizationProfile(): void + { + $organization = Organization::factory()->create(); + + OrganizationProfile::factory() + ->for($organization) + ->create(); + + $this->assertDatabaseCount("organization_profiles", 1); + $organizationProfile = OrganizationProfile::query()->first(); + + $this->actingAs($this->admin) + ->delete(route("organizations.profiles.destroy", [$organization, $organizationProfile])) + ->assertRedirect(); + + $this->assertModelMissing($organizationProfile); + } + + public function testUserCannotDeleteOrganizationProfile(): void + { + $user = User::factory()->create(); + + $organization = Organization::factory()->create(); + + OrganizationProfile::factory() + ->for($organization) + ->create(); + + $this->assertDatabaseCount("organization_profiles", 1); + $organizationProfile = OrganizationProfile::query()->first(); + + $this->actingAs($user) + ->delete(route("organizations.profiles.destroy", [$organization, $organizationProfile])) + ->assertForbidden(); + } +} diff --git a/tests/Feature/Organizations/Profiles/EditOrganizationProfilesTest.php b/tests/Feature/Organizations/Profiles/EditOrganizationProfilesTest.php new file mode 100644 index 00000000..a75006f8 --- /dev/null +++ b/tests/Feature/Organizations/Profiles/EditOrganizationProfilesTest.php @@ -0,0 +1,79 @@ + "admin"]); + $this->admin = User::factory()->create()->assignRole("admin"); + } + + public function testAdminCanEditOrganizationProfile(): void + { + $organization = Organization::factory()->create(); + + OrganizationProfile::factory() + ->for($organization) + ->create(); + + $this->assertDatabaseCount("organization_profiles", 1); + $organizationProfile = OrganizationProfile::query()->first(); + + $this->actingAs($this->admin) + ->get(route("organizations.profiles.edit", [$organization, $organizationProfile])) + ->assertOk(); + + $this->actingAs($this->admin) + ->put(route("organizations.profiles.update", [$organization, $organizationProfile]), [ + "label" => "Twitter", + "link" => "https://twitter.com", + ]) + ->assertSessionHasNoErrors() + ->assertRedirect(); + + $this->assertDatabaseHas("organization_profiles", [ + "organization_id" => $organization->id, + "label" => "Twitter", + "link" => "https://twitter.com", + ]); + } + + public function testUserCannotEditOrganizationProfile(): void + { + $user = User::factory()->create(); + + $organization = Organization::factory()->create(); + + OrganizationProfile::factory() + ->for($organization) + ->create(); + + $this->assertDatabaseCount("organization_profiles", 1); + $organizationProfile = OrganizationProfile::query()->first(); + + $this->actingAs($user) + ->get(route("organizations.profiles.edit", [$organization, $organizationProfile])) + ->assertForbidden(); + + $this->actingAs($user) + ->put(route("organizations.profiles.update", [$organization, $organizationProfile])) + ->assertForbidden(); + } +} diff --git a/tests/Feature/Organizations/Profiles/OrganizationProfilesRequestTest.php b/tests/Feature/Organizations/Profiles/OrganizationProfilesRequestTest.php new file mode 100644 index 00000000..b8e58b88 --- /dev/null +++ b/tests/Feature/Organizations/Profiles/OrganizationProfilesRequestTest.php @@ -0,0 +1,52 @@ + "admin"]); + $this->admin = User::factory()->create()->assignRole("admin"); + } + + public function testOrganizationProfileRequestHasRelatedOrganization(): void + { + $organization = Organization::factory()->create(); + $foreignOrganization = Organization::factory()->create(); + + OrganizationProfile::factory() + ->for($organization) + ->create(); + + $this->assertDatabaseCount("organization_profiles", 1); + $organizationProfile = OrganizationProfile::query()->first(); + + $this->actingAs($this->admin) + ->get(route("organizations.profiles.edit", [$foreignOrganization, $organizationProfile])) + ->assertNotFound(); + + $this->actingAs($this->admin) + ->put(route("organizations.profiles.update", [$foreignOrganization, $organizationProfile])) + ->assertNotFound(); + + $this->actingAs($this->admin) + ->delete(route("organizations.profiles.destroy", [$foreignOrganization, $organizationProfile])) + ->assertNotFound(); + } +} diff --git a/tests/Feature/Speakers/BrowseSpeakersTest.php b/tests/Feature/Speakers/BrowseSpeakersTest.php new file mode 100644 index 00000000..01f149e3 --- /dev/null +++ b/tests/Feature/Speakers/BrowseSpeakersTest.php @@ -0,0 +1,51 @@ +create(); + $speakers = Speaker::factory()->count(10)->create(); + + $response = $this->actingAs($user) + ->get(route("speakers")) + ->assertOk(); + + foreach ($speakers as $speaker) { + $response->assertSee($speaker->name) + ->assertSee($speaker->avatar_path); + } + } + + public function testSpeakersListIsPaginated(): void + { + $user = User::factory()->create(); + + Speaker::factory()->count(30)->create(); + + $speakers = Speaker::query() + ->latest() + ->skip(20) + ->take(10); + + $response = $this->actingAs($user) + ->get(route("speakers") . "?page=2") + ->assertOk(); + + foreach ($speakers as $speaker) { + $response->assertSee($speaker->name) + ->assertSee($speaker->avatar_path); + } + } +} diff --git a/tests/Feature/Speakers/CreateSpeakersTest.php b/tests/Feature/Speakers/CreateSpeakersTest.php new file mode 100644 index 00000000..aa29999d --- /dev/null +++ b/tests/Feature/Speakers/CreateSpeakersTest.php @@ -0,0 +1,62 @@ + "admin"]); + $this->admin = User::factory()->create()->assignRole("admin"); + } + + public function testAdminCanCreateSpeaker(): void + { + $this->actingAs($this->admin) + ->get(route("speakers.create")) + ->assertOk(); + + $this->actingAs($this->admin) + ->post(route("speakers.store"), [ + "name" => "speaker", + "description" => "speaker description", + "linkedin_url" => "https://linkedin.com/example", + "github_url" => "https://github.com/example", + ]) + ->assertSessionHasNoErrors() + ->assertRedirect(); + + $this->assertDatabaseHas("speakers", [ + "name" => "speaker", + "description" => "speaker description", + "linkedin_url" => "https://linkedin.com/example", + "github_url" => "https://github.com/example", + ]); + } + + public function testUserCannotCreateSpeaker(): void + { + $user = User::factory()->create(); + + $this->actingAs($user) + ->get(route("speakers.create")) + ->assertForbidden(); + + $this->actingAs($user) + ->post(route("speakers.store")) + ->assertForbidden(); + } +} diff --git a/tests/Feature/Speakers/DeleteSpeakersTest.php b/tests/Feature/Speakers/DeleteSpeakersTest.php new file mode 100644 index 00000000..6f44513a --- /dev/null +++ b/tests/Feature/Speakers/DeleteSpeakersTest.php @@ -0,0 +1,48 @@ + "admin"]); + $this->admin = User::factory()->create()->assignRole("admin"); + } + + public function testAdminCanDeleteSpeaker(): void + { + $speaker = Speaker::factory()->create(); + + $this->actingAs($this->admin) + ->delete(route("speakers.destroy", $speaker)) + ->assertRedirect(); + + $this->assertModelMissing($speaker); + } + + public function testUserCannotDeleteSpeaker(): void + { + $user = User::factory()->create(); + + $speaker = Speaker::factory()->create(); + + $this->actingAs($user) + ->delete(route("speakers.destroy", $speaker)) + ->assertForbidden(); + } +} diff --git a/tests/Feature/Speakers/EditSpeakersTest.php b/tests/Feature/Speakers/EditSpeakersTest.php new file mode 100644 index 00000000..6320e7e9 --- /dev/null +++ b/tests/Feature/Speakers/EditSpeakersTest.php @@ -0,0 +1,67 @@ + "admin"]); + $this->admin = User::factory()->create()->assignRole("admin"); + } + + public function testAdminCanEditSpeaker(): void + { + $speaker = Speaker::factory()->create(); + + $this->actingAs($this->admin) + ->get(route("speakers.edit", $speaker)) + ->assertOk(); + + $this->actingAs($this->admin) + ->put(route("speakers.update", $speaker), [ + "name" => "speaker", + "description" => "speaker description", + "linkedin_url" => "https://linkedin.com/", + "github_url" => "https://github.com/", + ]) + ->assertSessionHasNoErrors() + ->assertRedirect(); + + $this->assertDatabaseHas("speakers", [ + "name" => "speaker", + "description" => "speaker description", + "linkedin_url" => "https://linkedin.com/", + "github_url" => "https://github.com/", + ]); + } + + public function testUserCannotEditSpeaker(): void + { + $user = User::factory()->create(); + + $speaker = Speaker::factory()->create(); + + $this->actingAs($user) + ->get(route("speakers.edit", $speaker)) + ->assertForbidden(); + + $this->actingAs($user) + ->put(route("speakers.update", $speaker)) + ->assertForbidden(); + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php new file mode 100644 index 00000000..53411164 --- /dev/null +++ b/tests/TestCase.php @@ -0,0 +1,12 @@ +