seed(RolePermissionSeeder::class); } protected function actingWithRole(string $role): User { $user = User::factory()->create(); $user->syncRoles([$role]); $this->withHeaders($this->apiHeadersFor($user)); return $user; } #[Test] public function a_redirect_is_normalised_and_closes_the_report_it_answers(): void { $this->actingWithRole('editor'); MissingUrl::report('/proyectos/viejo', 'es'); $this->postJson('/api/v1/redirects', [ 'from' => 'proyectos/viejo/', 'to' => '/proyectos/nuevo?x=1', ]) ->assertCreated() ->assertJsonPath('data.from', '/proyectos/viejo') ->assertJsonPath('data.to', '/proyectos/nuevo') ->assertJsonPath('data.status', 301) ->assertJsonPath('data.automatic', false); $this->assertSame(MissingUrlStatus::Resolved, MissingUrl::query()->sole()->status); // The same address in the same language is one rule, not two. $this->postJson('/api/v1/redirects', ['from' => '/proyectos/viejo', 'to' => '/otra']) ->assertUnprocessable() ->assertJsonValidationErrors('from'); $this->postJson('/api/v1/redirects', ['from' => '/a', 'to' => '/a/']) ->assertUnprocessable() ->assertJsonValidationErrors('to'); } #[Test] public function a_missing_url_is_given_a_destination(): void { $this->actingWithRole('editor'); MissingUrl::report('/en/old', 'en'); $missing = MissingUrl::query()->sole(); $this->getJson('/api/v1/missing-urls')->assertJsonCount(1, 'data'); $this->postJson("/api/v1/missing-urls/{$missing->id}/redirect", ['to' => '/en/new']) ->assertCreated() ->assertJsonPath('data.from', '/en/old') ->assertJsonPath('data.locale', 'en'); $this->assertSame(MissingUrlStatus::Resolved, $missing->fresh()->status); $this->getJson('/api/v1/missing-urls')->assertJsonCount(0, 'data'); $this->postJson("/api/v1/missing-urls/{$missing->id}/redirect", ['to' => '/en/other']) ->assertUnprocessable() ->assertJsonValidationErrors('locale'); } #[Test] public function a_missing_url_can_be_ignored_but_not_declared_resolved(): void { $this->actingWithRole('editor'); $missing = MissingUrl::factory()->create(); $this->patchJson("/api/v1/missing-urls/{$missing->id}", ['status' => 'ignored']) ->assertOk() ->assertJsonPath('data.status', 'ignored'); $this->patchJson("/api/v1/missing-urls/{$missing->id}", ['status' => 'resolved']) ->assertUnprocessable(); } #[Test] public function a_repository_is_added_and_synced_on_the_queue(): void { Queue::fake(); $this->actingWithRole('admin'); $id = $this->postJson('/api/v1/repositories', [ 'provider' => 'github', 'full_name' => 'pireon/landing', 'show_publicly' => true, // Synced columns are not the caller's to set. 'stars' => 9999, ]) ->assertCreated() ->assertJsonPath('data.full_name', 'pireon/landing') ->assertJsonPath('data.stars', 0) ->json('data.id'); $this->postJson('/api/v1/repositories', ['provider' => 'github', 'full_name' => 'pireon/landing']) ->assertUnprocessable() ->assertJsonValidationErrors('full_name'); $this->postJson("/api/v1/repositories/{$id}/sync")->assertAccepted(); Queue::assertPushed(SyncRepository::class); } #[Test] public function an_editor_reads_repositories_but_cannot_sync_them(): void { Queue::fake(); $this->actingWithRole('editor'); $repository = Repository::factory()->create(); $this->getJson('/api/v1/repositories')->assertOk(); $this->postJson("/api/v1/repositories/{$repository->id}/sync")->assertForbidden(); Queue::assertNothingPushed(); } #[Test] public function a_setting_is_replaced_whole(): void { $this->actingWithRole('admin'); Setting::set('site.contact', ['email' => 'hola@example.org']); $this->getJson('/api/v1/settings')->assertOk()->assertJsonPath('data.0.key', 'site.contact'); $this->patchJson('/api/v1/settings/site.contact', ['value' => ['email' => 'nuevo@example.org']]) ->assertOk() ->assertJsonPath('data.value.email', 'nuevo@example.org'); $this->assertSame(['email' => 'nuevo@example.org'], Setting::get('site.contact')); } #[Test] public function the_content_version_is_not_edited_by_hand(): void { $this->actingWithRole('admin'); ContentVersion::bump(); $this->patchJson('/api/v1/settings/'.ContentVersion::KEY, ['value' => 1])->assertForbidden(); } #[Test] public function an_editor_sees_settings_but_changes_none(): void { $this->actingWithRole('editor'); Setting::set(Maintenance::KEY, ['enabled' => false]); $this->getJson('/api/v1/settings')->assertOk(); $this->getJson('/api/v1/maintenance')->assertOk()->assertJsonPath('data.enabled', false); $this->patchJson('/api/v1/settings/'.Maintenance::KEY, ['value' => ['enabled' => true]])->assertForbidden(); $this->putJson('/api/v1/maintenance', ['enabled' => true])->assertForbidden(); $this->assertFalse(Maintenance::isEnabled()); } #[Test] public function maintenance_is_switched_on_and_off_keeping_its_wording(): void { $this->actingWithRole('admin'); $this->putJson('/api/v1/maintenance', [ 'enabled' => true, 'message' => ['es' => 'Volvemos enseguida.', 'en' => ''], 'until' => now()->addHour()->toIso8601String(), ]) ->assertOk() ->assertJsonPath('data.enabled', true) ->assertJsonPath('data.message', ['es' => 'Volvemos enseguida.']); $this->assertTrue(Maintenance::isEnabled()); $this->putJson('/api/v1/maintenance', ['enabled' => false]) ->assertOk() ->assertJsonPath('data.enabled', false) ->assertJsonPath('data.until', null) ->assertJsonPath('data.message.es', 'Volvemos enseguida.'); } }