300 lines
9.1 KiB
PHP

<?php
namespace Vanguard\Announcements\Tests\Feature\Api;
use Carbon\Carbon;
use Facades\Tests\Setup\UserFactory;
use Mail;
use Tests\Feature\ApiTestCase;
use Vanguard\Announcements\Announcement;
use Vanguard\Announcements\Database\Seeders\AnnouncementsDatabaseSeeder;
use Vanguard\Announcements\Http\Resources\AnnouncementResource;
use Vanguard\Announcements\Mail\AnnouncementEmail;
class AnnouncementsTest extends ApiTestCase
{
protected function setUp(): void
{
parent::setUp();
$this->artisan('db:seed', ['--class' => AnnouncementsDatabaseSeeder::class]);
}
/** @test */
public function guests_cannot_paginate_announcements()
{
$this->getJson('/api/announcements')->assertStatus(401);
}
/** @test */
public function any_authenticated_users_can_paginate_announcements()
{
$user = UserFactory::user()->create();
$announcements = Announcement::factory()->times(11)->create();
$response = $this->actingAs($user, self::API_GUARD)
->getJson('/api/announcements?per_page=10')
->assertOk();
$transformed = AnnouncementResource::collection($announcements->take(10))->resolve();
$this->assertEquals($response->json('data'), $transformed);
$response->assertJson([
'meta' => [
'current_page' => 1,
'from' => 1,
'to' => 10,
'last_page' => 2,
'path' => url('api/announcements'),
'total' => 11,
'per_page' => 10,
],
]);
}
/** @test */
public function paginate_announcements_with_more_records_per_page_than_allowed()
{
$this->actingAs($this->validUser(), self::API_GUARD)
->getJson('/api/announcements?per_page=140')
->assertStatus(422);
}
/** @test */
public function guests_cannot_create_announcements()
{
$this->postJson('/api/announcements', $this->validParams())
->assertUnauthorized();
$this->assertEquals(0, Announcement::count());
}
/** @test */
public function users_without_appropriate_permission_cannot_create_announcements()
{
$user = UserFactory::user()->create();
$this->actingAs($user, self::API_GUARD)
->postJson('/api/announcements', $this->validParams())
->assertForbidden();
$this->assertEquals(0, Announcement::count());
}
/** @test */
public function users_with_appropriate_permission_can_create_announcements()
{
$user = $this->validUser();
$data = $this->validParams();
$response = $this->actingAs($user, self::API_GUARD)
->postJson('/api/announcements', $data)
->assertStatus(201);
$announcement = Announcement::first();
$response->assertExactJson([
'data' => (new AnnouncementResource($announcement))->resolve(),
]);
$this->assertEquals($user->id, $announcement->user_id);
$this->assertEquals($data['title'], $announcement->title);
$this->assertEquals($data['body'], $announcement->body);
}
/** @test */
public function an_email_notification_can_be_triggered_when_an_announcement_is_created()
{
Mail::fake();
$data = $this->validParams(['email_notification' => true]);
$this->actingAs($this->validUser(), self::API_GUARD)
->postJson('/api/announcements', $data)
->assertStatus(201);
$announcement = Announcement::first();
Mail::assertQueued(AnnouncementEmail::class, function ($mail) use ($announcement) {
return $mail->announcement->id === $announcement->id;
});
}
/** @test */
public function title_field_is_required_when_creating_an_announcement()
{
$data = $this->validParams(['title' => '']);
$this->actingAs($this->validUser(), self::API_GUARD)
->postJson('/api/announcements', $data)
->assertStatus(422)
->assertJsonValidationErrors('title');
$this->assertEquals(0, Announcement::count());
}
/** @test */
public function body_field_is_required_when_creating_an_announcement()
{
$data = $this->validParams(['body' => '']);
$this->actingAs($this->validUser(), self::API_GUARD)
->postJson('/api/announcements', $data)
->assertStatus(422)
->assertJsonValidationErrors('body');
$this->assertEquals(0, Announcement::count());
}
/** @test */
public function guests_cannot_view_an_announcement()
{
$announcement = Announcement::factory()->create();
$this->getJson("/api/announcements/{$announcement->id}")
->assertUnauthorized();
}
/** @test */
public function authenticated_users_can_view_any_announcement()
{
$user = UserFactory::user()->create();
$announcement = Announcement::factory()->create();
$this->actingAs($user, self::API_GUARD)
->getJson("/api/announcements/{$announcement->id}")
->assertOk()
->assertExactJson([
'data' => (new AnnouncementResource($announcement))->resolve(),
]);
}
/** @test */
public function guests_cannot_update_an_announcement()
{
$announcement = Announcement::factory()->create();
$this->putJson("/api/announcements/{$announcement->id}", $this->validParams())
->assertUnauthorized();
}
/** @test */
public function users_without_approprite_permission_cannot_update_an_announcement()
{
$user = UserFactory::user()->create();
$announcement = Announcement::factory()->create();
$this->actingAs($user, self::API_GUARD)
->putJson("/api/announcements/{$announcement->id}", $this->validParams())
->assertForbidden();
}
/** @test */
public function users_with_approprite_permission_can_update_an_announcement()
{
$user = $this->validUser();
$announcement = Announcement::factory()->create();
$this->actingAs($user, self::API_GUARD)
->putJson("/api/announcements/{$announcement->id}", $this->validParams())
->assertOk()
->assertExactJson([
'data' => (new AnnouncementResource($announcement->fresh()))->resolve(),
]);
}
/** @test */
public function title_field_is_required_when_updating_an_announcement()
{
$data = $this->validParams(['title' => '']);
$announcement = Announcement::factory()->create();
$this->actingAs($this->validUser(), self::API_GUARD)
->putJson("/api/announcements/{$announcement->id}", $data)
->assertStatus(422)
->assertJsonValidationErrors('title');
}
/** @test */
public function body_field_is_required_when_updating_an_announcement()
{
$data = $this->validParams(['body' => '']);
$announcement = Announcement::factory()->create();
$this->actingAs($this->validUser(), self::API_GUARD)
->putJson("/api/announcements/{$announcement->id}", $data)
->assertStatus(422)
->assertJsonValidationErrors('body');
}
/** @test */
public function guests_cannot_delete_an_announcement()
{
$announcement = Announcement::factory()->create();
$this->deleteJson("/api/announcements/{$announcement->id}")
->assertUnauthorized();
}
/** @test */
public function users_without_appropriate_permission_cannot_delete_an_announcement()
{
$user = UserFactory::user()->create();
$announcement = Announcement::factory()->create();
$this->actingAs($user, self::API_GUARD)
->deleteJson("/api/announcements/{$announcement->id}")
->assertForbidden();
}
/** @test */
public function users_with_appropriate_permission_can_delete_an_announcement()
{
$announcement = Announcement::factory()->create();
$this->actingAs($this->validUser(), self::API_GUARD)
->deleteJson("/api/announcements/{$announcement->id}")
->assertOk();
$this->assertNull($announcement->fresh());
}
/** @test */
public function user_announcements_can_be_marked_as_read()
{
$user = UserFactory::user()->create([
'announcements_last_read_at' => null,
]);
Carbon::setTestNow(now());
$this->actingAs($user, self::API_GUARD)
->post('/api/announcements/read');
$this->assertEquals(
now()->format('Y-m-d H:i:s'),
$user->fresh()->announcements_last_read_at
);
}
/**
* @return mixed
*/
private function validUser()
{
return UserFactory::user()->withPermissions('announcements.manage')->create();
}
/**
* @return array
*/
private function validParams(array $overrides = [])
{
return array_merge([
'title' => 'Foo Announcement',
'body' => 'This is the announcement body.',
'email_notification' => false,
], $overrides);
}
}