Files
timebank-cc-public/tests/Feature/Polls/PollPostsPageTest.php
T

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));
}
}