refactor(outlet): menyesuaikan unit test dari segi penamaan, logika bisnis, clean code dan lainnya
-menghapus key closed_date di factory -salah menulis relasi di model -antisipasi error ketika image null atau array kosong di index -memindahkan posisi toast menjadi di atas redirect
This commit is contained in:
parent
77bce6f0eb
commit
5a49bc8ba4
@ -34,9 +34,9 @@ public function save()
|
||||
|
||||
$this->form->update();
|
||||
|
||||
$this->redirectRoute('studio.master.outlet.index', navigate: true);
|
||||
|
||||
$this->toast('Outlet berhasil diperbarui.');
|
||||
|
||||
$this->redirectRoute('studio.master.outlet.index', navigate: true);
|
||||
}
|
||||
|
||||
public function render()
|
||||
|
||||
@ -51,8 +51,11 @@ public function mount()
|
||||
'closed_ago' => $outlet->closed_date ? timeAgo($outlet->closed_date) : null,
|
||||
'edit_route' => route('studio.master.outlet.edit', $outlet->hash),
|
||||
'delete_route' => route('studio.master.outlet.delete', $outlet->hash),
|
||||
'image' => $this->mapMediaCollection($outlet->getMedia('featured_image'))[0]['temporaryUrl'],
|
||||
'images' => collect($this->mapMediaCollection($outlet->getMedia('images')))->map(fn ($image) => $image['temporaryUrl']),
|
||||
'image' => data_get($this->mapMediaCollection($outlet->getMedia('featured_image'))[0] ?? null, 'temporaryUrl', asset('images/placeholder.jpg')),
|
||||
'images' => collect($this->mapMediaCollection($outlet->getMedia('images')))
|
||||
->pluck('temporaryUrl')
|
||||
->filter()
|
||||
->values(),
|
||||
])
|
||||
->toArray();
|
||||
}
|
||||
@ -68,8 +71,6 @@ public function delete(Outlet $outlet)
|
||||
{
|
||||
$outlet->delete();
|
||||
|
||||
$this->dispatch('refreshDatatable');
|
||||
|
||||
$this->toast('Outlet berhasil dihapus.');
|
||||
|
||||
Flux::modals()->close();
|
||||
|
||||
@ -21,7 +21,7 @@ class Outlet extends Model implements HasMedia
|
||||
|
||||
protected $guarded = ['id'];
|
||||
|
||||
protected $cascadeDeletes = ['openingHours', 'facilities', 'vouchers', 'perfumes', 'products', 'bottles', 'expenses', 'users5'];
|
||||
protected $cascadeDeletes = ['openingHours', 'facilities', 'vouchers', 'perfumes', 'products', 'bottles', 'expenses', 'users'];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
|
||||
@ -21,7 +21,6 @@ public function definition(): array
|
||||
'landmark' => $this->faker->streetName(),
|
||||
'maps_url' => 'https://goo.gl/maps/'.$this->faker->regexify('[A-Za-z0-9]{6,10}'),
|
||||
'opened_date' => $this->faker->date(),
|
||||
'closed_date' => $this->faker->optional()->date(),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@ -5,68 +5,103 @@
|
||||
use App\Livewire\Studio\Master\Outlet\Index;
|
||||
use App\Models\Facility;
|
||||
use App\Models\Outlet;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Livewire\Livewire;
|
||||
use Spatie\Permission\Models\Permission;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
it('renders successfully', function () {
|
||||
Livewire::test(Create::class)
|
||||
beforeEach(function () {
|
||||
$this->user = User::factory()->create();
|
||||
});
|
||||
|
||||
function makeLivewireFile(string $name)
|
||||
{
|
||||
$file = UploadedFile::fake()->image($name, 100, 100);
|
||||
$tmpId = Str::random(32);
|
||||
$filename = $tmpId.'-'.base64_encode($file->getClientOriginalName()).'.'.$file->getClientOriginalExtension();
|
||||
$path = "livewire-tmp/{$filename}";
|
||||
|
||||
Storage::disk('local')->putFileAs('livewire-tmp', $file, $filename);
|
||||
|
||||
return [
|
||||
'tmpFilename' => $filename,
|
||||
'name' => $file->getClientOriginalName(),
|
||||
'extension' => $file->getClientOriginalExtension(),
|
||||
'path' => storage_path("app/private/{$path}"),
|
||||
'temporaryUrl' => url("livewire/preview-file/{$filename}"),
|
||||
'size' => $file->getSize(),
|
||||
];
|
||||
}
|
||||
|
||||
function mountCreateComponent(User $user)
|
||||
{
|
||||
return Livewire::actingAs($user)->test(Create::class);
|
||||
}
|
||||
|
||||
it('renders page successfully', function () {
|
||||
mountCreateComponent($this->user)
|
||||
->assertViewIs('livewire.studio.master.outlet.form')
|
||||
->assertViewHas('pageTitle', 'Tambah Outlet');
|
||||
});
|
||||
|
||||
it('can create an outlet', function () {
|
||||
it('mounts days and form opening_hours correctly', function () {
|
||||
$component = mountCreateComponent($this->user);
|
||||
$days = Day::cases();
|
||||
|
||||
expect($component->days)->toHaveCount(count($days));
|
||||
|
||||
foreach ($days as $day) {
|
||||
expect(array_key_exists($day->value, $component->form->opening_hours))->toBeTrue();
|
||||
expect($component->form->opening_hours[$day->value])->toBe(['open_time' => null, 'close_time' => null]);
|
||||
}
|
||||
});
|
||||
|
||||
it('prevents create when user is unauthorized', function () {
|
||||
Gate::define('create outlet', fn () => false);
|
||||
|
||||
mountCreateComponent($this->user)
|
||||
->call('save')
|
||||
->assertForbidden();
|
||||
});
|
||||
|
||||
it('saves outlet successfully when authorized', function () {
|
||||
$permission = Permission::create(['name' => 'create outlet']);
|
||||
$this->user->givePermissionTo($permission);
|
||||
|
||||
$outlet = Outlet::factory()->operational()->raw();
|
||||
$facilities = Facility::factory()->count(5)->raw();
|
||||
|
||||
$makeLivewireFile = function ($name) {
|
||||
$file = UploadedFile::fake()->image($name, 100, 100);
|
||||
$featuredImage = makeLivewireFile('featured.jpg');
|
||||
$images = [];
|
||||
|
||||
$tmpId = Str::random(32);
|
||||
$filename = $tmpId.'-'.base64_encode($file->getClientOriginalName()).'.'.$file->getClientOriginalExtension();
|
||||
$path = "livewire-tmp/{$filename}";
|
||||
for ($i = 1; $i <= 5; $i++) {
|
||||
$images[] = makeLivewireFile("image{$i}.jpg");
|
||||
}
|
||||
|
||||
Storage::disk('local')->putFileAs('livewire-tmp', $file, $filename);
|
||||
$openingHours = collect(Day::cases())
|
||||
->mapWithKeys(fn ($day) => [
|
||||
$day->value => [
|
||||
'day' => $day->value,
|
||||
'open_time' => fake()->time('H:i'),
|
||||
'close_time' => fake()->time('H:i'),
|
||||
],
|
||||
])
|
||||
->toArray();
|
||||
|
||||
return [
|
||||
'tmpFilename' => $filename,
|
||||
'name' => $file->getClientOriginalName(),
|
||||
'extension' => $file->getClientOriginalExtension(),
|
||||
'path' => storage_path("app/private/{$path}"),
|
||||
'temporaryUrl' => url("livewire/preview-file/{$filename}"),
|
||||
'size' => $file->getSize(),
|
||||
];
|
||||
};
|
||||
$data = array_merge($outlet, [
|
||||
'opening_hours' => $openingHours,
|
||||
'facilities' => collect($facilities)->pluck('name')->toArray(),
|
||||
'featured_image' => [$featuredImage],
|
||||
'images' => $images,
|
||||
]);
|
||||
|
||||
$featuredImage = $makeLivewireFile('featured.jpg');
|
||||
$images = [
|
||||
$makeLivewireFile('image1.jpg'),
|
||||
$makeLivewireFile('image2.png'),
|
||||
];
|
||||
|
||||
$data = array_merge(
|
||||
$outlet,
|
||||
[
|
||||
'opening_hours' => collect(Day::cases())
|
||||
->mapWithKeys(fn ($day) => [
|
||||
$day->value => [
|
||||
'day' => $day->value,
|
||||
'open_time' => fake()->time('H:i'),
|
||||
'close_time' => fake()->time('H:i'),
|
||||
],
|
||||
])
|
||||
->toArray(),
|
||||
'facilities' => collect($facilities)->pluck('name')->toArray(),
|
||||
'featured_image' => [$featuredImage],
|
||||
'images' => $images,
|
||||
]
|
||||
);
|
||||
|
||||
Livewire::test(Create::class)
|
||||
mountCreateComponent($this->user)
|
||||
->set('form.name', $data['name'])
|
||||
->set('form.phone_number', $data['phone_number'])
|
||||
->set('form.address', $data['address'])
|
||||
@ -80,7 +115,6 @@
|
||||
->set('form.images', $data['images'])
|
||||
->call('save')
|
||||
->assertHasNoErrors()
|
||||
->assertDispatched('refreshDatatable')
|
||||
->assertRedirect(Index::class);
|
||||
|
||||
$outlet = Outlet::first();
|
||||
@ -92,10 +126,9 @@
|
||||
]);
|
||||
|
||||
$this->assertCount(1, $outlet->getMedia('featured_image'));
|
||||
$this->assertCount(2, $outlet->getMedia('images'));
|
||||
$this->assertCount(5, $outlet->getMedia('images'));
|
||||
|
||||
expect($outlet->getFirstMedia('featured_image')->getPath())->toBeFile();
|
||||
|
||||
foreach ($outlet->getMedia('images') as $media) {
|
||||
expect($media->getPath())->toBeFile();
|
||||
}
|
||||
|
||||
@ -5,70 +5,102 @@
|
||||
use App\Livewire\Studio\Master\Outlet\Index;
|
||||
use App\Models\Facility;
|
||||
use App\Models\Outlet;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Livewire\Livewire;
|
||||
use Spatie\Permission\Models\Permission;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
it('renders successfully', function () {
|
||||
beforeEach(function () {
|
||||
$this->user = User::factory()->create();
|
||||
});
|
||||
|
||||
function makeLivewireFile(string $name)
|
||||
{
|
||||
$file = UploadedFile::fake()->image($name, 100, 100);
|
||||
$tmpId = Str::random(32);
|
||||
$filename = $tmpId.'-'.base64_encode($file->getClientOriginalName()).'.'.$file->getClientOriginalExtension();
|
||||
$path = "livewire-tmp/{$filename}";
|
||||
|
||||
Storage::disk('local')->putFileAs('livewire-tmp', $file, $filename);
|
||||
|
||||
return [
|
||||
'tmpFilename' => $filename,
|
||||
'name' => $file->getClientOriginalName(),
|
||||
'extension' => $file->getClientOriginalExtension(),
|
||||
'path' => storage_path("app/private/{$path}"),
|
||||
'temporaryUrl' => url("livewire/preview-file/{$filename}"),
|
||||
'size' => $file->getSize(),
|
||||
];
|
||||
}
|
||||
|
||||
function mountEditComponent(User $user, Outlet $outlet)
|
||||
{
|
||||
return Livewire::actingAs($user)->test(Edit::class, ['outlet' => $outlet]);
|
||||
}
|
||||
|
||||
it('renders page successfully', function () {
|
||||
$outlet = Outlet::factory()->operational()->create();
|
||||
|
||||
Livewire::test(Edit::class, ['outlet' => $outlet])
|
||||
mountEditComponent($this->user, $outlet)
|
||||
->assertViewIs('livewire.studio.master.outlet.form')
|
||||
->assertViewHas('pageTitle', 'Ubah Outlet');
|
||||
});
|
||||
|
||||
it('can update an outlet', function () {
|
||||
it('mounts days and sets form with outlet', function () {
|
||||
$outlet = Outlet::factory()->operational()->create();
|
||||
$component = mountEditComponent($this->user, $outlet);
|
||||
|
||||
$days = Day::cases();
|
||||
expect($component->days)->toHaveCount(count($days));
|
||||
expect($component->form->outlet->id)->toBe($outlet->id);
|
||||
});
|
||||
|
||||
it('prevents update when user is unauthorized', function () {
|
||||
$outlet = Outlet::factory()->operational()->create();
|
||||
Gate::define('update outlet', fn () => false);
|
||||
|
||||
mountEditComponent($this->user, $outlet)
|
||||
->call('save')
|
||||
->assertForbidden();
|
||||
});
|
||||
|
||||
it('updates outlet successfully when authorized', function () {
|
||||
$permission = Permission::create(['name' => 'update outlet']);
|
||||
$this->user->givePermissionTo($permission);
|
||||
|
||||
$outletModel = Outlet::factory()->operational()->create(); // model instance
|
||||
$outletData = Outlet::factory()->operational()->raw(); // data for update
|
||||
$facilities = Facility::factory()->count(5)->raw();
|
||||
|
||||
$makeLivewireFile = function ($name) {
|
||||
$file = UploadedFile::fake()->image($name, 100, 100);
|
||||
$featuredImage = makeLivewireFile('featured.jpg');
|
||||
for ($i = 1; $i <= 5; $i++) {
|
||||
$images[] = makeLivewireFile("image{$i}.jpg");
|
||||
}
|
||||
|
||||
$tmpId = Str::random(32);
|
||||
$filename = $tmpId.'-'.base64_encode($file->getClientOriginalName()).'.'.$file->getClientOriginalExtension();
|
||||
$path = "livewire-tmp/{$filename}";
|
||||
$openingHours = collect(Day::cases())
|
||||
->mapWithKeys(fn ($day) => [
|
||||
$day->value => [
|
||||
'day' => $day->value,
|
||||
'open_time' => fake()->time('H:i'),
|
||||
'close_time' => fake()->time('H:i'),
|
||||
],
|
||||
])
|
||||
->toArray();
|
||||
|
||||
Storage::disk('local')->putFileAs('livewire-tmp', $file, $filename);
|
||||
$data = array_merge($outletData, [
|
||||
'opening_hours' => $openingHours,
|
||||
'facilities' => collect($facilities)->pluck('name')->toArray(),
|
||||
'featured_image' => [$featuredImage],
|
||||
'images' => $images,
|
||||
]);
|
||||
|
||||
return [
|
||||
'tmpFilename' => $filename,
|
||||
'name' => $file->getClientOriginalName(),
|
||||
'extension' => $file->getClientOriginalExtension(),
|
||||
'path' => storage_path("app/private/{$path}"),
|
||||
'temporaryUrl' => url("livewire/preview-file/{$filename}"),
|
||||
'size' => $file->getSize(),
|
||||
];
|
||||
};
|
||||
|
||||
$featuredImage = $makeLivewireFile('featured.jpg');
|
||||
$images = [
|
||||
$makeLivewireFile('image1.jpg'),
|
||||
$makeLivewireFile('image2.png'),
|
||||
];
|
||||
|
||||
$data = array_merge(
|
||||
Outlet::factory()->operational()->raw(),
|
||||
[
|
||||
'opening_hours' => collect(Day::cases())
|
||||
->mapWithKeys(fn ($day) => [
|
||||
$day->value => [
|
||||
'day' => $day->value,
|
||||
'open_time' => fake()->time('H:i'),
|
||||
'close_time' => fake()->time('H:i'),
|
||||
],
|
||||
])
|
||||
->toArray(),
|
||||
'facilities' => collect($facilities)->pluck('name')->toArray(),
|
||||
'featured_image' => [$featuredImage],
|
||||
'images' => $images,
|
||||
]
|
||||
);
|
||||
|
||||
Livewire::test(Edit::class, ['outlet' => $outlet])
|
||||
mountEditComponent($this->user, $outletModel)
|
||||
->set('form.name', $data['name'])
|
||||
->set('form.phone_number', $data['phone_number'])
|
||||
->set('form.address', $data['address'])
|
||||
@ -82,12 +114,21 @@
|
||||
->set('form.images', $data['images'])
|
||||
->call('save')
|
||||
->assertHasNoErrors()
|
||||
->assertDispatched('refreshDatatable')
|
||||
->assertRedirect(Index::class);
|
||||
|
||||
$outletModel->refresh();
|
||||
|
||||
$this->assertDatabaseHas('outlets', [
|
||||
'id' => $outlet->id,
|
||||
'id' => $outletModel->id,
|
||||
'name' => $data['name'],
|
||||
'phone_number' => $data['phone_number'],
|
||||
]);
|
||||
|
||||
$this->assertCount(1, $outletModel->getMedia('featured_image'));
|
||||
$this->assertCount(5, $outletModel->getMedia('images'));
|
||||
|
||||
expect($outletModel->getFirstMedia('featured_image')->getPath())->toBeFile();
|
||||
foreach ($outletModel->getMedia('images') as $media) {
|
||||
expect($media->getPath())->toBeFile();
|
||||
}
|
||||
});
|
||||
|
||||
@ -5,45 +5,72 @@
|
||||
use App\Models\Facility;
|
||||
use App\Models\OpeningHour;
|
||||
use App\Models\Outlet;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Livewire\Livewire;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
it('renders successfully', function () {
|
||||
Livewire::test(Index::class)
|
||||
beforeEach(function () {
|
||||
$this->user = User::factory()->create();
|
||||
});
|
||||
|
||||
function createOutlet(array $attributes = [])
|
||||
{
|
||||
return Outlet::factory()
|
||||
->has(OpeningHour::factory()->count(7))
|
||||
->has(Facility::factory()->count(5))
|
||||
->state(fn () => array_merge([
|
||||
'status' => fake()->randomElement(OutletStatus::cases()),
|
||||
], $attributes))
|
||||
->create();
|
||||
}
|
||||
|
||||
function mountIndexComponent(User $user)
|
||||
{
|
||||
return Livewire::actingAs($user)->test(Index::class);
|
||||
}
|
||||
|
||||
it('renders page successfully', function () {
|
||||
mountIndexComponent($this->user)
|
||||
->assertViewIs('livewire.studio.master.outlet.index')
|
||||
->assertViewHas('pageTitle', 'Outlet');
|
||||
});
|
||||
|
||||
it('mounts outlets correctly', function () {
|
||||
$outlet = createOutlet();
|
||||
|
||||
mountIndexComponent($this->user)
|
||||
->assertSet('outlets.0.name', $outlet->name)
|
||||
->assertSet('outlets.0.phone_number', $outlet->phone_number);
|
||||
});
|
||||
|
||||
it('opens image modal when openImage is called', function () {
|
||||
$component = mountIndexComponent($this->user);
|
||||
|
||||
$url = 'https://example.com/test.jpg';
|
||||
$component->call('openImage', $url)->assertSet('imageUrl', $url);
|
||||
});
|
||||
|
||||
it('displays all outlets', function () {
|
||||
Outlet::factory()
|
||||
->count(10)
|
||||
->has(OpeningHour::factory()->count(7))
|
||||
->has(Facility::factory()->count(5))
|
||||
->state(fn () => [
|
||||
'status' => fake()->randomElement(OutletStatus::cases()),
|
||||
])
|
||||
->create();
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
createOutlet();
|
||||
}
|
||||
|
||||
$outlet = Outlet::first();
|
||||
$outletCount = Outlet::count();
|
||||
$firstOutlet = Outlet::first();
|
||||
|
||||
Livewire::test(Index::class)->assertSee($outlet->name);
|
||||
mountIndexComponent($this->user)
|
||||
->assertSee($firstOutlet->name)
|
||||
->assertViewHas('outlets', fn ($outlets) => count($outlets) === $outletCount);
|
||||
});
|
||||
|
||||
it('can delete an outlet', function () {
|
||||
$outlet = Outlet::factory()
|
||||
->has(OpeningHour::factory()->count(7))
|
||||
->has(Facility::factory()->count(5))
|
||||
->state(fn () => [
|
||||
'status' => fake()->randomElement(OutletStatus::cases()),
|
||||
])
|
||||
->create();
|
||||
it('deletes an outlet successfully', function () {
|
||||
$outlet = createOutlet();
|
||||
|
||||
Livewire::test(Index::class)
|
||||
mountIndexComponent($this->user)
|
||||
->call('delete', $outlet)
|
||||
->assertHasNoErrors()
|
||||
->assertDispatched('refreshDatatable');
|
||||
->assertHasNoErrors();
|
||||
|
||||
expect(Outlet::count())->toBe(0);
|
||||
$this->assertSoftDeleted('outlets', ['id' => $outlet->id]);
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user