118 lines
4.9 KiB
PHP
118 lines
4.9 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\Polls;
|
|
|
|
use App\Http\Livewire\Posts\Manage as PostsManage;
|
|
use App\Models\Admin;
|
|
use App\Models\Poll;
|
|
use App\Models\PollResponse;
|
|
use App\Models\Post;
|
|
use App\Models\PostTranslation;
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Livewire\Livewire;
|
|
use Spatie\Permission\Models\Permission;
|
|
use Spatie\Permission\Models\Role;
|
|
use Tests\TestCase;
|
|
|
|
/**
|
|
* The Posts page cannot delete or (un)publish the post of an opened poll (security audit R1).
|
|
*/
|
|
class PollPostsPageTest extends TestCase
|
|
{
|
|
use DatabaseTransactions;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
// phpunit.xml configures Redis, which is the dev site's cache too
|
|
config(['cache.default' => 'array', 'scout.driver' => null]);
|
|
}
|
|
|
|
private function actAsPostsAdmin(array $extra = []): void
|
|
{
|
|
$permissions = array_merge(['view posts', 'delete posts', 'publish posts', 'unpublish posts'], $extra);
|
|
$user = User::factory()->create();
|
|
$admin = Admin::factory()->create();
|
|
$admin->users()->attach($user);
|
|
$role = Role::firstOrCreate(['name' => "Admin\\{$admin->id}\\posts-only", 'guard_name' => 'web']);
|
|
foreach ($permissions as $name) {
|
|
Permission::firstOrCreate(['name' => $name, 'guard_name' => 'web']);
|
|
}
|
|
$role->syncPermissions($permissions);
|
|
$user->assignRole($role);
|
|
$this->actingAs($user, 'web');
|
|
$this->actingAs($admin, 'admin');
|
|
session(['activeProfileType' => Admin::class, 'activeProfileId' => $admin->id]);
|
|
}
|
|
|
|
/** @return array{0: ?Poll, 1: int} the poll (if any) and the translation id */
|
|
private function makePost(?string $pollStatus, bool $withVote = false): array
|
|
{
|
|
$postId = DB::table('posts')->insertGetId(['postable_id' => 1, 'postable_type' => Admin::class, 'created_at' => now(), 'updated_at' => now()]);
|
|
$translationId = DB::table('post_translations')->insertGetId([
|
|
'post_id' => $postId, 'locale' => 'en', 'slug' => 'posts-page-' . $postId, 'title' => 'Post ' . $postId,
|
|
'from' => now()->subDay(), 'created_at' => now(), 'updated_at' => now(),
|
|
]);
|
|
$poll = $pollStatus ? Poll::create(['post_id' => $postId, 'status' => $pollStatus]) : null;
|
|
if ($poll && $withVote) {
|
|
$voter = User::factory()->create();
|
|
PollResponse::create(['poll_id' => $poll->id, 'voter_id' => $voter->id, 'voter_type' => User::class, 'user_id' => $voter->id,
|
|
'dedupe_key' => $poll->dedupeKey($voter, $voter->id), 'submitted_at' => now()]);
|
|
}
|
|
|
|
return [$poll, $translationId];
|
|
}
|
|
|
|
public function test_an_open_poll_post_cannot_be_unpublished_or_deleted(): void
|
|
{
|
|
$this->actAsPostsAdmin(['manage polls']);
|
|
[$poll, $translationId] = $this->makePost(Poll::STATUS_OPEN, true);
|
|
|
|
Livewire::test(PostsManage::class)->call('stopPublication', $translationId);
|
|
$this->assertNull(PostTranslation::find($translationId)->till);
|
|
|
|
Livewire::test(PostsManage::class)->set('bulkSelected', [$translationId])->call('deleteSelected');
|
|
$this->assertNotNull(PostTranslation::find($translationId));
|
|
$this->assertNotNull(Post::find($poll->post_id));
|
|
}
|
|
|
|
public function test_a_closed_poll_post_cannot_be_republished(): void
|
|
{
|
|
$this->actAsPostsAdmin();
|
|
[, $translationId] = $this->makePost(Poll::STATUS_CLOSED, true);
|
|
PostTranslation::whereKey($translationId)->update(['till' => now()->subHour()]);
|
|
$till = PostTranslation::find($translationId)->till;
|
|
|
|
Livewire::test(PostsManage::class)->call('startPublication', $translationId);
|
|
$this->assertEquals($till, PostTranslation::find($translationId)->till);
|
|
}
|
|
|
|
public function test_a_draft_poll_post_needs_delete_polls_to_be_deleted(): void
|
|
{
|
|
$this->actAsPostsAdmin();
|
|
[$draft, $translationId] = $this->makePost(Poll::STATUS_DRAFT);
|
|
Livewire::test(PostsManage::class)->set('bulkSelected', [$translationId])->call('deleteSelected');
|
|
$this->assertNotNull(PostTranslation::find($translationId));
|
|
|
|
$this->actAsPostsAdmin(['delete polls']);
|
|
Livewire::test(PostsManage::class)->set('bulkSelected', [$translationId])->call('deleteSelected');
|
|
$this->assertNull(PostTranslation::find($translationId));
|
|
$this->assertNull(Post::find($draft->post_id));
|
|
}
|
|
|
|
public function test_other_posts_are_unaffected(): void
|
|
{
|
|
$this->actAsPostsAdmin();
|
|
[, $translationId] = $this->makePost(null);
|
|
|
|
Livewire::test(PostsManage::class)->call('stopPublication', $translationId);
|
|
$this->assertNotNull(PostTranslation::find($translationId)->till);
|
|
|
|
Livewire::test(PostsManage::class)->set('bulkSelected', [$translationId])->call('deleteSelected');
|
|
$this->assertNull(PostTranslation::find($translationId));
|
|
}
|
|
}
|