use App\Models\Tip;
use App\Models\User;
use App\Models\Banner;
use App\Storage\Image;
use App\Enums\UserType;
use App\Types\ServerTest;
use Illuminate\Support\Str;
class TipTest extends ServerTest
{
/** @test */
public function a_user_can_view_the_tips_page() : void
{
$user = User::factory()->create();
$this->actingAs($user)
->get(route('tips'))
->assertSuccessful()
->assertPage('tips.view.index');
}
/** @test */
public function a_user_can_create_a_tip() : void
{
$user = User::factory()->create();
$this->actingAs($user)
->get(route('tips.create'))
->assertSuccessful()
->assertPage('tips.create.index');
}
/** @test */
public function a_user_can_edit_a_tip() : void
{
$user = User::factory()->create();
$tip = Tip::factory()
->belongsTo($user)
->create();
$this->actingAs($user)
->get(route('tips.edit', ['tip' => $tip]))
->assertSuccessful()
->assertPage('tips.edit.index');
}
/** @test */
public function a_user_can_store_a_tip() : void
{
$user = User::factory()->create();
$banner = Banner::factory()
->belongsTo($user)
->create();
$tip = Tip::factory()
->belongsTo($user, $banner)
->make(['published_at' => now()->addDays(rand(1, 100))]);
Image::fakeTemporary($tip->card);
$this->actingAs($user)
->postJson(route('tips.store'), $tip->toArray())
->assertRedirect(route('tips.edit', ['tip' => Tip::first()]))
->assertNotification('The tip has been created');
$this->assertCount(1, Tip::get());
$this->assertTrue(Tip::first()->user->is($user));
$this->assertTrue(Tip::first()->banner->is($banner));
$this->assertEquals(Tip::first()->title, $tip->title);
$this->assertEquals(Tip::first()->summary, $tip->summary);
$this->assertEquals(Tip::first()->teaser, $tip->teaser);
$this->assertEquals(Tip::first()->content, $tip->content);
$this->assertEquals(Tip::first()->theme, $tip->theme);
$this->assertEquals(Tip::first()->gradient, $tip->gradient);
$this->assertEquals(Tip::first()->first_tag, $tip->first_tag);
$this->assertEquals(Tip::first()->second_tag, $tip->second_tag);
$this->assertEquals(Tip::first()->third_tag, $tip->third_tag);
$this->assertEquals(Tip::first()->fourth_tag, $tip->fourth_tag);
$this->assertEquals(Tip::first()->attribution, $tip->attribution);
$this->assertEquals(Tip::first()->shared, $tip->shared);
$this->assertEquals(Tip::first()->published_at, $tip->published_at);
$this->assertEquals(Tip::first()->slug, Str::slug(implode('-', [Tip::first()->id, $tip->title])));
Image::assertExists(Tip::first()->card);
}
/** @test */
public function a_user_can_update_a_tip() : void
{
$user = User::factory()->create();
$banner = Banner::factory()
->belongsTo($user)
->create();
$tip = Tip::factory()
->belongsTo($user, $banner)
->create(['published_at' => now()->addDays(10)]);
$payload = Tip::factory()
->belongsTo($user, $banner)
->make(['published_at' => now()->addDays(5)]);
Image::fake($tip->card);
Image::fakeTemporary($payload->card);
$this->actingAs($user)
->patchJson(route('tips.update', ['tip' => $tip]), $payload->toArray())
->assertRedirect(route('tips.edit', ['tip' => $tip]))
->assertNotification('The tip has been updated');
$this->assertTrue($tip->fresh()->user->is($user));
$this->assertTrue($tip->fresh()->banner->is($banner));
$this->assertEquals($tip->fresh()->title, $payload->title);
$this->assertEquals($tip->fresh()->summary, $payload->summary);
$this->assertEquals($tip->fresh()->teaser, $payload->teaser);
$this->assertEquals($tip->fresh()->content, $payload->content);
$this->assertEquals($tip->fresh()->theme, $payload->theme);
$this->assertEquals($tip->fresh()->gradient, $payload->gradient);
$this->assertEquals($tip->fresh()->first_tag, $payload->first_tag);
$this->assertEquals($tip->fresh()->second_tag, $payload->second_tag);
$this->assertEquals($tip->fresh()->third_tag, $payload->third_tag);
$this->assertEquals($tip->fresh()->fourth_tag, $payload->fourth_tag);
$this->assertEquals($tip->fresh()->attribution, $payload->attribution);
$this->assertEquals($tip->fresh()->shared, $payload->shared);
$this->assertEquals($tip->fresh()->published_at, $payload->published_at);
Image::assertMissing($tip->card);
Image::assertExists($tip->fresh()->card);
}
/** @test */
public function a_user_can_delete_a_tip() : void
{
$user = User::factory()->create(['type' => UserType::CUSTOMER]);
$tip = Tip::factory()
->belongsTo($user)
->create();
Image::fake($tip->card);
$this->actingAs($user)
->deleteJson(route('tips.delete', ['tip' => $tip]))
->assertRedirect(route('tips'))
->assertNotification('The tip has been deleted');
$this->assertCount(0, Tip::get());
Image::assertMissing($tip->card);
}
/** @test */
public function a_user_cannot_delete_a_tip_that_does_not_belong_to_them() : void
{
$user_1 = User::factory()->create(['type' => UserType::CUSTOMER]);
$user_2 = User::factory()->create(['type' => UserType::CUSTOMER]);
$tip = Tip::factory()
->belongsTo($user_2)
->create();
$this->actingAs($user_1)
->deleteJson(route('tips.delete', ['tip' => $tip]))
->assertForbidden();
}
/** @test */
public function a_user_can_delete_a_tip_that_does_not_belong_to_them_when_they_are_an_employee() : void
{
$user_1 = User::factory()->create(['type' => UserType::EMPLOYEE]);
$user_2 = User::factory()->create(['type' => UserType::CUSTOMER]);
$tip = Tip::factory()
->belongsTo($user_2)
->create();
Image::fake($tip->card);
$this->actingAs($user_1)
->deleteJson(route('tips.delete', ['tip' => $tip]))
->assertRedirect(route('tips'))
->assertNotification('The tip has been deleted');
$this->assertCount(0, Tip::get());
Image::assertMissing($tip->card);
}
}