187 lines
5.6 KiB
PHP
187 lines
5.6 KiB
PHP
<?php
|
|
|
|
use App\Enums\OutletStatus;
|
|
use App\Livewire\Studio\Master\Outlet\Index;
|
|
use App\Models\Employee;
|
|
use App\Models\Facility;
|
|
use App\Models\OpeningHour;
|
|
use App\Models\Outlet;
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Livewire\Livewire;
|
|
use Spatie\Permission\Models\Role;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
beforeEach(function () {
|
|
$roles = collect(['Developer', 'Owner', 'Leader', 'Admin', 'Partner', 'Customer'])
|
|
->map(fn ($role) => Role::create(['name' => $role]));
|
|
|
|
$this->user = User::factory()
|
|
->active()
|
|
->has(Employee::factory())
|
|
// ->has(Outlet::factory()->count(5))
|
|
->create();
|
|
|
|
$this->user->roles()->attach($roles->pluck('id'));
|
|
});
|
|
|
|
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)
|
|
->assertViewHas('outlets', function ($outlets) use ($outlet) {
|
|
return collect($outlets)->contains(
|
|
fn ($o) => $o['name'] === $outlet->name &&
|
|
$o['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 () {
|
|
for ($i = 0; $i < 5; $i++) {
|
|
createOutlet();
|
|
}
|
|
|
|
$outletCount = Outlet::count();
|
|
$firstOutlet = Outlet::first();
|
|
|
|
mountIndexComponent($this->user)
|
|
->assertSee($firstOutlet->name)
|
|
->assertViewHas('outlets', fn ($outlets) => count($outlets) === $outletCount);
|
|
});
|
|
|
|
it('deletes an outlet successfully', function () {
|
|
$outlet = createOutlet();
|
|
|
|
mountIndexComponent($this->user)
|
|
->call('delete', $outlet)
|
|
->assertHasNoErrors();
|
|
|
|
$this->assertSoftDeleted('outlets', ['id' => $outlet->id]);
|
|
});
|
|
|
|
it('filters outlets by search query', function () {
|
|
$outlet1 = createOutlet(['name' => 'Outlet Jakarta']);
|
|
$outlet2 = createOutlet(['name' => 'Outlet Bandung']);
|
|
$outlet3 = createOutlet(['name' => 'Toko Surabaya']);
|
|
|
|
$component = mountIndexComponent($this->user);
|
|
|
|
expect(count($component->get('outlets')))->toBe(3);
|
|
|
|
$component->set('search', 'Jakarta')
|
|
->assertSet('search', 'Jakarta');
|
|
|
|
expect(count($component->get('outlets')))->toBe(1);
|
|
expect($component->get('outlets.0.name'))->toBe('Outlet Jakarta');
|
|
|
|
$component->set('search', 'Outlet')
|
|
->assertSet('search', 'Outlet');
|
|
|
|
expect(count($component->get('outlets')))->toBe(2);
|
|
});
|
|
|
|
it('filters outlets by status', function () {
|
|
$outlet1 = createOutlet(['status' => OutletStatus::OPERATIONAL]);
|
|
$outlet2 = createOutlet(['status' => OutletStatus::UNDER_CONSTRUCTION]);
|
|
$outlet3 = createOutlet(['status' => OutletStatus::TERMINATED]);
|
|
|
|
$component = mountIndexComponent($this->user);
|
|
|
|
expect(count($component->get('outlets')))->toBe(3);
|
|
|
|
$component->set('status', [OutletStatus::OPERATIONAL->value])
|
|
->assertSet('status', [OutletStatus::OPERATIONAL->value]);
|
|
|
|
expect(count($component->get('outlets')))->toBe(1);
|
|
expect($component->get('outlets.0.name'))->toBe($outlet1->name);
|
|
|
|
$component->set('status', [
|
|
OutletStatus::OPERATIONAL->value,
|
|
OutletStatus::UNDER_CONSTRUCTION->value,
|
|
]);
|
|
|
|
expect(count($component->get('outlets')))->toBe(2);
|
|
});
|
|
|
|
it('filters outlets by both search and status', function () {
|
|
$outlet1 = createOutlet(['name' => 'Outlet A', 'status' => OutletStatus::OPERATIONAL]);
|
|
$outlet2 = createOutlet(['name' => 'Outlet B', 'status' => OutletStatus::OPERATIONAL]);
|
|
$outlet3 = createOutlet(['name' => 'Outlet C', 'status' => OutletStatus::UNDER_CONSTRUCTION]);
|
|
|
|
$component = mountIndexComponent($this->user)
|
|
->set('search', 'Outlet')
|
|
->set('status', [OutletStatus::OPERATIONAL->value]);
|
|
|
|
expect(count($component->get('outlets')))->toBe(2);
|
|
});
|
|
|
|
it('loads outlet data with all required fields', function () {
|
|
$outlet = createOutlet();
|
|
|
|
$component = mountIndexComponent($this->user);
|
|
$outletData = $component->get('outlets.0');
|
|
|
|
expect($outletData)->toHaveKeys([
|
|
'hash',
|
|
'name',
|
|
'phone_number',
|
|
'landmark',
|
|
'address',
|
|
'status',
|
|
'opening_hours',
|
|
'facilities',
|
|
'opened_date',
|
|
'opened_ago',
|
|
'closed_date',
|
|
'closed_ago',
|
|
'image',
|
|
'images',
|
|
]);
|
|
|
|
expect($outletData['status'])->toHaveKeys(['label', 'color']);
|
|
expect($outletData['name'])->toBe($outlet->name);
|
|
expect($outletData['phone_number'])->toBe($outlet->phone_number);
|
|
});
|
|
|
|
it('loads outlets ordered by latest', function () {
|
|
$outlet1 = createOutlet(['name' => 'First']);
|
|
sleep(1);
|
|
$outlet2 = createOutlet(['name' => 'Second']);
|
|
|
|
$component = mountIndexComponent($this->user);
|
|
|
|
expect($component->get('outlets.0.name'))->toBe('Second');
|
|
expect($component->get('outlets.1.name'))->toBe('First');
|
|
});
|