diff --git a/app/Livewire/Studio/Master/Formula.php b/app/Livewire/Studio/Master/Formula.php index 7c9e9b1..e490557 100644 --- a/app/Livewire/Studio/Master/Formula.php +++ b/app/Livewire/Studio/Master/Formula.php @@ -13,7 +13,6 @@ use App\Traits\WithUpdatedData; use Flux\Flux; use Illuminate\Contracts\View\View; -use Illuminate\Support\Collection; use Livewire\Attributes\On; use Livewire\Attributes\Title; use Livewire\Component; @@ -25,7 +24,7 @@ class Formula extends Component public FormulaForm $form; - public Collection $formulas; + public array $formulas = []; public string $method = 'create'; @@ -40,33 +39,22 @@ public function mount(): void $this->formulas = FormulaModel::orderBy('size') ->get() ->groupBy('size') - ->map(function ($items) { - return $items + ->map( + fn ($items) => $items ->map(fn ($item) => [ 'hash' => $item->hash, 'quality' => $item->quality, 'volume' => $item->volume, ]) - ->sortBy('volume'); - }); + ->sortBy('volume') + ->values() + ->all() + ) + ->all(); $this->sizes = Bottle::distinct()->orderBy('size')->pluck('size')->toArray(); } - #[On('modal:open')] - public function openModal(string $method, string $modalTitle, ?string $id = null): void - { - $this->resetValidation(); - $this->resetErrorBag(); - - $this->method = $method; - $this->modalTitle = $modalTitle; - - if ($id) { - $this->form->setFormula(FormulaModel::byHashOrFail($id)); - } - } - public function create(): void { $this->canOrAbort('create formula'); @@ -87,26 +75,14 @@ public function create(): void 'volume' => $formula->volume, ]; - // push new formula to collection - $size = $formula->size; - $newFormula = [ - 'hash' => $formula->hash, - 'quality' => $formula->quality, - 'volume' => $formula->volume, - ]; - - // Recreate the collection instead of modifying in place - $newFormulas = $this->formulas->toArray(); - - if (! isset($newFormulas[$size])) { - $newFormulas[$size] = []; + if (! isset($this->formulas[$size])) { + $this->formulas[$size] = []; } - $newFormulas[$size][] = $newFormula; - // Sort by volume - usort($newFormulas[$size], fn ($a, $b) => $a['volume'] <=> $b['volume']); + $this->formulas[$size][] = $newFormula; - $this->formulas = collect($newFormulas); + // Sort by volume + usort($this->formulas[$size], fn ($a, $b) => $a['volume'] <=> $b['volume']); $this->toast('Rumus berhasil ditambahkan.'); @@ -130,26 +106,19 @@ public function update(): void $formula = $this->form->update(); - // update collection formulas - $newFormulas = $this->formulas->toArray(); - - foreach ($newFormulas as $size => &$items) { - foreach ($items as &$item) { + // update array formulas + foreach ($this->formulas as &$group) { + foreach ($group as &$item) { if ($item['hash'] === $formula->hash) { - $item = [ - 'hash' => $formula->hash, - 'quality' => $formula->quality, - 'volume' => $formula->volume, - ]; - break; + $item['quality'] = $formula->quality; + $item['volume'] = $formula->volume; + // Hash doesn't change } } - // Sort by volume - usort($items, fn ($a, $b) => $a['volume'] <=> $b['volume']); + // re-sort + usort($group, fn ($a, $b) => $a['volume'] <=> $b['volume']); } - unset($items); - - $this->formulas = collect($newFormulas); + unset($group, $item); // Break references $this->toast('Rumus berhasil diperbarui.'); @@ -158,27 +127,40 @@ public function update(): void public function delete(FormulaModel $formula): void { + $this->canOrAbort('delete formula'); + $formula->delete(); - // update collection formulas + // update array formulas $size = $formula->size; - $newFormulas = $this->formulas->toArray(); - if (isset($newFormulas[$size])) { - $newFormulas[$size] = array_values(array_filter($newFormulas[$size], fn ($item) => $item['hash'] !== $formula->hash)); + if (isset($this->formulas[$size])) { + $this->formulas[$size] = array_values(array_filter($this->formulas[$size], fn ($item) => $item['hash'] !== $formula->hash)); - if (empty($newFormulas[$size])) { - unset($newFormulas[$size]); + if (empty($this->formulas[$size])) { + unset($this->formulas[$size]); } } - $this->formulas = collect($newFormulas); - $this->toast('Rumus berhasil dihapus.'); Flux::modals()->close(); } + #[On('modal:open')] + public function openModal(string $method, string $modalTitle, ?string $id = null): void + { + $this->resetValidation(); + $this->resetErrorBag(); + + $this->method = $method; + $this->modalTitle = $modalTitle; + + if ($id) { + $this->form->setFormula(FormulaModel::byHashOrFail($id)); + } + } + public function render(): View { return view('livewire.studio.master.formulas', [ diff --git a/tests/Feature/Livewire/Studio/Master/FormulaTest.php b/tests/Feature/Livewire/Studio/Master/FormulaTest.php index b02197c..de57b8c 100644 --- a/tests/Feature/Livewire/Studio/Master/FormulaTest.php +++ b/tests/Feature/Livewire/Studio/Master/FormulaTest.php @@ -2,929 +2,197 @@ use App\Livewire\Studio\Master\Formula; use App\Models\Bottle; -use App\Models\Employee; use App\Models\Formula as FormulaModel; use App\Models\User; -use Database\Seeders\RolePermissionSeeder; use Illuminate\Foundation\Testing\RefreshDatabase; -use Illuminate\Support\Facades\Gate; use Livewire\Livewire; -use Spatie\Permission\Models\Role; +use Spatie\Permission\Models\Permission; uses(RefreshDatabase::class); beforeEach(function () { - $this->seed(RolePermissionSeeder::class); - - $this->user = User::factory() - ->active() - ->has(Employee::factory()) - ->create(); - - $this->ownerRole = Role::where('name', 'Owner')->first(); - - $this->user->roles()->attach($this->ownerRole->id); + // Setup Permissions + Permission::create(['name' => 'create formula']); + Permission::create(['name' => 'update formula']); + Permission::create(['name' => 'delete formula']); }); -function mountFormulaComponent(User $user) +function createAuthorizedUser() { - return Livewire::actingAs($user)->test(Formula::class); + $user = User::factory()->create(); + $user->givePermissionTo(['create formula', 'update formula', 'delete formula']); + + return $user; } -/* -|-------------------------------------------------------------------------- -| Component Rendering & Mount -|-------------------------------------------------------------------------- -*/ +it('renders successfully', function () { + $user = createAuthorizedUser(); + $this->actingAs($user); -it('renders page successfully', function () { - mountFormulaComponent($this->user) - ->assertViewIs('livewire.studio.master.formulas') - ->assertViewHas('pageTitle', 'Rumus'); + Bottle::factory()->create(['size' => 100]); + + Livewire::test(Formula::class) + ->assertStatus(200); }); -it('mounts formulas correctly grouped by size', function () { - $bottle1 = Bottle::factory()->create(['size' => 100]); - $bottle2 = Bottle::factory()->create(['size' => 200]); +it('validates required fields', function () { + $user = createAuthorizedUser(); + $this->actingAs($user); - $formula1 = FormulaModel::factory()->create([ - 'quality' => 'Premium', - 'size' => 100, - 'volume' => 20, - ]); - - $formula2 = FormulaModel::factory()->create([ - 'quality' => 'Super Premium', - 'size' => 100, - 'volume' => 30, - ]); - - $formula3 = FormulaModel::factory()->create([ - 'quality' => 'Premium', - 'size' => 200, - 'volume' => 40, - ]); - - $component = mountFormulaComponent($this->user); - - expect($component->formulas)->toBeInstanceOf(\Illuminate\Support\Collection::class); - expect($component->formulas)->toHaveKey('100'); - expect($component->formulas)->toHaveKey('200'); - expect($component->formulas[100])->toBeInstanceOf(\Illuminate\Support\Collection::class); - expect($component->formulas[100]->count())->toBe(2); - expect($component->formulas[200]->count())->toBe(1); -}); - -it('mounts formulas sorted by size', function () { - $bottle1 = Bottle::factory()->create(['size' => 200]); - $bottle2 = Bottle::factory()->create(['size' => 100]); - $bottle3 = Bottle::factory()->create(['size' => 300]); - - FormulaModel::factory()->create(['size' => 200]); - FormulaModel::factory()->create(['size' => 100]); - FormulaModel::factory()->create(['size' => 300]); - - $component = mountFormulaComponent($this->user); - - $sizes = $component->formulas->keys()->toArray(); - expect($sizes[0])->toBeLessThan($sizes[1]); - expect($sizes[1])->toBeLessThan($sizes[2]); -}); - -it('mounts formulas sorted by volume within each size group', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - - $formula1 = FormulaModel::factory()->create([ - 'size' => 100, - 'volume' => 30, - ]); - - $formula2 = FormulaModel::factory()->create([ - 'size' => 100, - 'volume' => 10, - ]); - - $formula3 = FormulaModel::factory()->create([ - 'size' => 100, - 'volume' => 20, - ]); - - $component = mountFormulaComponent($this->user); - - $volumes = $component->formulas[100]->pluck('volume')->toArray(); - expect($volumes[0])->toBeLessThan($volumes[1]); - expect($volumes[1])->toBeLessThan($volumes[2]); -}); - -it('mounts sizes from bottles correctly', function () { - $bottle1 = Bottle::factory()->create(['size' => 100]); - $bottle2 = Bottle::factory()->create(['size' => 200]); - $bottle3 = Bottle::factory()->create(['size' => 300]); - - $component = mountFormulaComponent($this->user); - - expect($component->sizes)->toBeArray(); - expect($component->sizes)->toContain(100, 200, 300); -}); - -it('mounts sizes sorted correctly', function () { - $bottle1 = Bottle::factory()->create(['size' => 300]); - $bottle2 = Bottle::factory()->create(['size' => 100]); - $bottle3 = Bottle::factory()->create(['size' => 200]); - - $component = mountFormulaComponent($this->user); - - expect($component->sizes[0])->toBeLessThan($component->sizes[1]); - expect($component->sizes[1])->toBeLessThan($component->sizes[2]); -}); - -it('mounts qualities correctly', function () { - $component = mountFormulaComponent($this->user); - - expect($component->qualities)->toBeArray(); - expect($component->qualities)->toContain('Premium', 'Super Premium', 'Murni'); -}); - -it('displays empty state when no formulas exist', function () { - $component = mountFormulaComponent($this->user); - - expect($component->formulas)->toBeInstanceOf(\Illuminate\Support\Collection::class); - expect($component->formulas)->toBeEmpty(); -}); - -it('mounts with correct initial method and modal title', function () { - $component = mountFormulaComponent($this->user); - - expect($component->method)->toBe('create'); - expect($component->modalTitle)->toBe(''); -}); - -/* -|-------------------------------------------------------------------------- -| Modal Operations -|-------------------------------------------------------------------------- -*/ - -it('opens modal for create', function () { - $component = mountFormulaComponent($this->user); - - $component->dispatch( - 'modal:open', - 'create', - 'Tambah Rumus' - ); - - expect($component->method)->toBe('create'); - expect($component->modalTitle)->toBe('Tambah Rumus'); -}); - -it('opens modal for update with formula data', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - $formula = FormulaModel::factory()->create([ - 'quality' => 'Premium', - 'size' => 100, - 'volume' => 20, - ]); - - $component = mountFormulaComponent($this->user); - - $component->dispatch( - 'modal:open', - 'update', - 'Ubah Rumus', - $formula->hash - ); - - expect($component->method)->toBe('update'); - expect($component->modalTitle)->toBe('Ubah Rumus'); - expect($component->form->quality)->toBe('Premium'); - expect($component->form->size)->toBe('100'); - expect($component->form->volume)->toBe('20'); -}); - -it('resets validation when opening modal', function () { - $component = mountFormulaComponent($this->user); - - $component->set('form.quality', '') + Livewire::test(Formula::class) + ->set('form.quality', '') + ->set('form.size', '') + ->set('form.volume', '') ->call('create') - ->assertHasErrors('form.quality'); - - $component->dispatch( - 'modal:open', - 'create', - 'Tambah Rumus' - ); - - $component->assertHasNoErrors(); + ->assertHasErrors(['form.quality', 'form.size', 'form.volume']); }); -it('resets error bag when opening modal', function () { - $component = mountFormulaComponent($this->user); +it('validates quality max length', function () { + $user = createAuthorizedUser(); + $this->actingAs($user); - $component->set('form.quality', '') + Livewire::test(Formula::class) + ->set('form.quality', str_repeat('a', 21)) ->call('create') - ->assertHasErrors(); - - $component->dispatch( - 'modal:open', - 'create', - 'Tambah Rumus' - ); - - expect($component->get('form.quality'))->toBe(''); + ->assertHasErrors(['form.quality']); }); -/* -|-------------------------------------------------------------------------- -| Create Formula -|-------------------------------------------------------------------------- -*/ +it('validates size numeric and min', function () { + $user = createAuthorizedUser(); + $this->actingAs($user); -it('prevents create when user is unauthorized', function () { - $this->ownerRole->revokePermissionTo('create formula'); + Livewire::test(Formula::class) + ->set('form.size', 'abc') + ->call('create') + ->assertHasErrors(['form.size']); - Gate::define('create formula', fn () => false); + Livewire::test(Formula::class) + ->set('form.size', 0) + ->call('create') + ->assertHasErrors(['form.size']); +}); - $bottle = Bottle::factory()->create(['size' => 100]); +it('can create a formula', function () { + $user = createAuthorizedUser(); + $this->actingAs($user); - mountFormulaComponent($this->user) + Bottle::factory()->create(['size' => 100]); + + Livewire::test(Formula::class) ->set('form.quality', 'Premium') ->set('form.size', '100') - ->set('form.volume', '20') - ->call('create') - ->assertForbidden(); -}); - -it('creates formula successfully when authorized', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - - $component = mountFormulaComponent($this->user) - ->set('form.quality', 'Premium') - ->set('form.size', '100') - ->set('form.volume', '20') - ->call('create') - ->assertHasNoErrors(); + ->set('form.volume', '50') + ->call('create'); $this->assertDatabaseHas('formulas', [ 'quality' => 'Premium', 'size' => 100, - 'volume' => 20, + 'volume' => 50, ]); - - $formula = FormulaModel::where('quality', 'Premium') - ->where('size', 100) - ->first(); - - expect($formula)->not->toBeNull(); - expect($formula->volume)->toBe(20); }); -it('adds new formula to formulas array after creation', function () { - $bottle = Bottle::factory()->create(['size' => 100]); +it('prevents duplicate formula creation', function () { + $user = createAuthorizedUser(); + $this->actingAs($user); - $component = mountFormulaComponent($this->user) + FormulaModel::create([ + 'quality' => 'Premium', + 'size' => 100, + 'volume' => 50, + ]); + + Livewire::test(Formula::class) ->set('form.quality', 'Premium') ->set('form.size', '100') - ->set('form.volume', '20') + ->set('form.volume', '60') ->call('create'); - expect($component->formulas)->toHaveKey('100'); - expect($component->formulas[100])->toBeArray(); - - $found = false; - foreach ($component->formulas[100] as $item) { - if ($item['quality'] === 'Premium' && $item['volume'] === 20) { - $found = true; - expect($item)->toHaveKey('hash'); - break; - } - } - - expect($found)->toBeTrue(); + expect(FormulaModel::count())->toBe(1); }); -it('prevents creating duplicate formula with same quality and size', function () { - $bottle = Bottle::factory()->create(['size' => 100]); +it('can update a formula', function () { + $user = createAuthorizedUser(); + $this->actingAs($user); - FormulaModel::factory()->create([ + $formula = FormulaModel::create([ 'quality' => 'Premium', 'size' => 100, - 'volume' => 20, + 'volume' => 50, ]); - $component = mountFormulaComponent($this->user) - ->set('form.quality', 'Premium') - ->set('form.size', '100') - ->set('form.volume', '30') - ->call('create'); - - expect(FormulaModel::where('quality', 'Premium')->where('size', 100)->count())->toBe(1); -}); - -it('shows warning when creating duplicate formula', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - - FormulaModel::factory()->create([ - 'quality' => 'Premium', - 'size' => 100, - 'volume' => 20, - ]); - - mountFormulaComponent($this->user) - ->set('form.quality', 'Premium') - ->set('form.size', '100') - ->set('form.volume', '30') - ->call('create') - ->assertHasNoErrors(); -}); - -it('allows creating formula with different quality but same size', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - - FormulaModel::factory()->create([ - 'quality' => 'Premium', - 'size' => 100, - 'volume' => 20, - ]); - - mountFormulaComponent($this->user) + Livewire::test(Formula::class) + ->call('openModal', 'update', 'Edit Formula', $formula->hash) + ->assertSet('form.quality', 'Premium') + ->assertSet('form.size', 100) ->set('form.quality', 'Super Premium') - ->set('form.size', '100') - ->set('form.volume', '30') - ->call('create') - ->assertHasNoErrors(); - - expect(FormulaModel::where('size', 100)->count())->toBe(2); -}); - -it('allows creating formula with same quality but different size', function () { - $bottle1 = Bottle::factory()->create(['size' => 100]); - $bottle2 = Bottle::factory()->create(['size' => 200]); - - FormulaModel::factory()->create([ - 'quality' => 'Premium', - 'size' => 100, - 'volume' => 20, - ]); - - mountFormulaComponent($this->user) - ->set('form.quality', 'Premium') - ->set('form.size', '200') - ->set('form.volume', '40') - ->call('create') - ->assertHasNoErrors(); - - expect(FormulaModel::where('quality', 'Premium')->count())->toBe(2); -}); - -it('creates formula with all quality types', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - - $qualities = ['Premium', 'Super Premium', 'Murni']; - - foreach ($qualities as $quality) { - mountFormulaComponent($this->user) - ->set('form.quality', $quality) - ->set('form.size', '100') - ->set('form.volume', '20') - ->call('create') - ->assertHasNoErrors(); - } - - expect(FormulaModel::where('size', 100)->count())->toBe(3); -}); - -/* -|-------------------------------------------------------------------------- -| Update Formula -|-------------------------------------------------------------------------- -*/ - -it('prevents update when user is unauthorized', function () { - $this->ownerRole->revokePermissionTo('update formula'); - - Gate::define('update formula', fn () => false); - - $bottle = Bottle::factory()->create(['size' => 100]); - $formula = FormulaModel::factory()->create([ - 'quality' => 'Premium', - 'size' => 100, - 'volume' => 20, - ]); - - mountFormulaComponent($this->user) - ->call('openModal', 'update', 'Ubah Rumus', $formula->hash) - ->set('form.volume', '30') - ->call('update') - ->assertForbidden(); -}); - -it('updates formula successfully when authorized', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - $formula = FormulaModel::factory()->create([ - 'quality' => 'Premium', - 'size' => 100, - 'volume' => 20, - ]); - - $component = mountFormulaComponent($this->user) - ->call('openModal', 'update', 'Ubah Rumus', $formula->hash) - ->set('form.volume', '30') - ->call('update') - ->assertHasNoErrors(); - - $formula->refresh(); - - expect($formula->volume)->toBe(30); + ->set('form.volume', '55') + ->call('update'); $this->assertDatabaseHas('formulas', [ 'id' => $formula->id, - 'volume' => 30, - ]); -}); - -it('updates formula quality', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - $formula = FormulaModel::factory()->create([ - 'quality' => 'Premium', - 'size' => 100, - 'volume' => 20, - ]); - - mountFormulaComponent($this->user) - ->call('openModal', 'update', 'Ubah Rumus', $formula->hash) - ->set('form.quality', 'Super Premium') - ->set('form.volume', '25') - ->call('update') - ->assertHasNoErrors(); - - $formula->refresh(); - - expect($formula->quality)->toBe('Super Premium'); - expect($formula->volume)->toBe(25); -}); - -it('updates formula size', function () { - $bottle1 = Bottle::factory()->create(['size' => 100]); - $bottle2 = Bottle::factory()->create(['size' => 200]); - - $formula = FormulaModel::factory()->create([ - 'quality' => 'Premium', - 'size' => 100, - 'volume' => 20, - ]); - - mountFormulaComponent($this->user) - ->call('openModal', 'update', 'Ubah Rumus', $formula->hash) - ->set('form.size', '200') - ->set('form.volume', '40') - ->call('update') - ->assertHasNoErrors(); - - $formula->refresh(); - - expect($formula->size)->toBe(200); - expect($formula->volume)->toBe(40); -}); - -it('updates formulas array after update', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - $formula = FormulaModel::factory()->create([ - 'quality' => 'Premium', - 'size' => 100, - 'volume' => 20, - ]); - - $component = mountFormulaComponent($this->user) - ->call('openModal', 'update', 'Ubah Rumus', $formula->hash) - ->set('form.volume', '30') - ->call('update'); - - $found = false; - foreach ($component->formulas[100] as $item) { - if ($item['hash'] === $formula->hash && $item['volume'] === 30) { - $found = true; - break; - } - } - - expect($found)->toBeTrue(); -}); - -it('prevents updating to duplicate quality and size combination', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - - $formula1 = FormulaModel::factory()->create([ - 'quality' => 'Premium', - 'size' => 100, - 'volume' => 20, - ]); - - $formula2 = FormulaModel::factory()->create([ 'quality' => 'Super Premium', 'size' => 100, - 'volume' => 30, + 'volume' => 55, ]); +}); - $component = mountFormulaComponent($this->user) - ->call('openModal', 'update', 'Ubah Rumus', $formula2->hash) - ->set('form.quality', 'Premium') +it('prevents duplicate formula on update', function () { + $user = createAuthorizedUser(); + $this->actingAs($user); + + $formula1 = FormulaModel::create(['quality' => 'Premium', 'size' => 100, 'volume' => 50]); + $formula2 = FormulaModel::create(['quality' => 'Super Premium', 'size' => 100, 'volume' => 60]); + + Livewire::test(Formula::class) + ->call('openModal', 'update', 'Edit Formula', $formula1->hash) + ->set('form.quality', 'Super Premium') ->set('form.size', '100') ->call('update'); - $formula2->refresh(); - - expect($formula2->quality)->toBe('Super Premium'); + $formula1->refresh(); + expect($formula1->quality)->toBe('Premium'); }); -it('allows updating to same quality and size if it is the same formula', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - $formula = FormulaModel::factory()->create([ - 'quality' => 'Premium', - 'size' => 100, - 'volume' => 20, - ]); +it('can delete a formula', function () { + $user = createAuthorizedUser(); + $this->actingAs($user); - mountFormulaComponent($this->user) - ->call('openModal', 'update', 'Ubah Rumus', $formula->hash) - ->set('form.volume', '25') - ->call('update') - ->assertHasNoErrors(); + $formula = FormulaModel::create(['quality' => 'Premium', 'size' => 100, 'volume' => 50]); - $formula->refresh(); - - expect($formula->volume)->toBe(25); - expect($formula->quality)->toBe('Premium'); - expect($formula->size)->toBe(100); -}); - -it('updates formula with formatted volume input', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - $formula = FormulaModel::factory()->create([ - 'quality' => 'Premium', - 'size' => 100, - 'volume' => 20, - ]); - - mountFormulaComponent($this->user) - ->call('openModal', 'update', 'Ubah Rumus', $formula->hash) - ->set('form.volume', '1.500') - ->call('update') - ->assertHasNoErrors(); - - $formula->refresh(); - - expect($formula->volume)->toBe(1500); -}); - -/* -|-------------------------------------------------------------------------- -| Delete Formula -|-------------------------------------------------------------------------- -*/ - -it('deletes formula successfully when authorized', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - $formula = FormulaModel::factory()->create([ - 'quality' => 'Premium', - 'size' => 100, - 'volume' => 20, - ]); - - mountFormulaComponent($this->user) - ->call('delete', $formula) - ->assertHasNoErrors(); + Livewire::test(Formula::class) + ->call('delete', $formula->hash); $this->assertSoftDeleted('formulas', ['id' => $formula->id]); }); -it('removes formula from formulas array after deletion', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - $formula = FormulaModel::factory()->create([ - 'quality' => 'Premium', - 'size' => 100, - 'volume' => 20, - ]); +it('checks authorization for create', function () { + $user = User::factory()->create(); + $this->actingAs($user); - $component = mountFormulaComponent($this->user); - $initialCount = count($component->formulas[100] ?? []); - - $component->call('delete', $formula); - - if (isset($component->formulas[100])) { - expect(count($component->formulas[100]))->toBeLessThan($initialCount); - } else { - expect($component->formulas)->not->toHaveKey('100'); - } -}); - -it('removes size group when last formula in group is deleted', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - $formula = FormulaModel::factory()->create([ - 'quality' => 'Premium', - 'size' => 100, - 'volume' => 20, - ]); - - $component = mountFormulaComponent($this->user); - - expect($component->formulas)->toHaveKey('100'); - - $component->call('delete', $formula); - - expect($component->formulas)->not->toHaveKey('100'); -}); - -it('keeps other formulas in group when one is deleted', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - - $formula1 = FormulaModel::factory()->create([ - 'quality' => 'Premium', - 'size' => 100, - 'volume' => 20, - ]); - - $formula2 = FormulaModel::factory()->create([ - 'quality' => 'Super Premium', - 'size' => 100, - 'volume' => 30, - ]); - - $component = mountFormulaComponent($this->user); - - expect(count($component->formulas[100]))->toBe(2); - - $component->call('delete', $formula1); - - expect($component->formulas)->toHaveKey('100'); - expect(count($component->formulas[100]))->toBe(1); - - $remaining = $component->formulas[100][0]; - expect($remaining['quality'])->toBe('Super Premium'); -}); - -/* -|-------------------------------------------------------------------------- -| Validation Rules -|-------------------------------------------------------------------------- -*/ - -it('validates quality field is required', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - - mountFormulaComponent($this->user) - ->set('form.size', '100') - ->set('form.volume', '20') + Livewire::test(Formula::class) ->call('create') - ->assertHasErrors(['form.quality']); + ->assertForbidden(); }); -it('validates quality field max length', function () { - $bottle = Bottle::factory()->create(['size' => 100]); +it('checks authorization for update', function () { + $user = User::factory()->create(); + $this->actingAs($user); - mountFormulaComponent($this->user) - ->set('form.quality', str_repeat('a', 21)) - ->set('form.size', '100') - ->set('form.volume', '20') - ->call('create') - ->assertHasErrors(['form.quality']); + $formula = FormulaModel::create(['quality' => 'Premium', 'size' => 100, 'volume' => 50]); + + Livewire::test(Formula::class) + ->call('openModal', 'update', 'Edit', $formula->hash) + ->call('update') + ->assertForbidden(); }); -it('validates size field is required', function () { - $bottle = Bottle::factory()->create(['size' => 100]); +it('checks authorization for delete', function () { + $user = User::factory()->create(); + $this->actingAs($user); - mountFormulaComponent($this->user) - ->set('form.quality', 'Premium') - ->set('form.volume', '20') - ->call('create') - ->assertHasErrors(['form.size']); -}); - -it('validates size field is unsigned integer', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - - mountFormulaComponent($this->user) - ->set('form.quality', 'Premium') - ->set('form.size', '-100') - ->set('form.volume', '20') - ->call('create') - ->assertHasErrors(['form.size']); -}); - -it('validates volume field is required', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - - mountFormulaComponent($this->user) - ->set('form.quality', 'Premium') - ->set('form.size', '100') - ->call('create') - ->assertHasErrors(['form.volume']); -}); - -it('validates volume field is unsigned integer', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - - mountFormulaComponent($this->user) - ->set('form.quality', 'Premium') - ->set('form.size', '100') - ->set('form.volume', '-20') - ->call('create') - ->assertHasErrors(['form.volume']); -}); - -it('validates volume field is valid integer', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - - mountFormulaComponent($this->user) - ->set('form.quality', 'Premium') - ->set('form.size', '100') - ->set('form.volume', '150') - ->call('create') - ->assertHasNoErrors(); -}); - -it('validates volume field can be equal to size', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - - mountFormulaComponent($this->user) - ->set('form.quality', 'Premium') - ->set('form.size', '100') - ->set('form.volume', '100') - ->call('create') - ->assertHasNoErrors(); - - $this->assertDatabaseHas('formulas', [ - 'size' => 100, - 'volume' => 100, - ]); -}); - -it('validates volume field accepts formatted numbers', function () { - $bottle = Bottle::factory()->create(['size' => 1000]); - - mountFormulaComponent($this->user) - ->set('form.quality', 'Premium') - ->set('form.size', '1000') - ->set('form.volume', '5.000') - ->call('create') - ->assertHasNoErrors(); - - $this->assertDatabaseHas('formulas', [ - 'size' => 1000, - 'volume' => 5000, - ]); -}); - -/* -|-------------------------------------------------------------------------- -| Edge Cases & Additional Scenarios -|-------------------------------------------------------------------------- -*/ - -it('handles multiple formulas with same size correctly', function () { - - $bottle = Bottle::factory()->create(['size' => 100]); - - $qualities = ['Premium', 'Super Premium', 'Murni']; - - foreach ($qualities as $quality) { - mountFormulaComponent($this->user) - ->set('form.quality', $quality) - ->set('form.size', '100') - ->set('form.volume', '20') - ->call('create') - ->assertHasNoErrors(); - } - - $component = mountFormulaComponent($this->user); - - expect($component->formulas)->toHaveKey('100'); - expect(count($component->formulas[100]))->toBe(3); -}); - -it('handles formulas with different sizes correctly', function () { - - $bottle1 = Bottle::factory()->create(['size' => 100]); - $bottle2 = Bottle::factory()->create(['size' => 200]); - $bottle3 = Bottle::factory()->create(['size' => 300]); - - $sizes = [100, 200, 300]; - - foreach ($sizes as $size) { - mountFormulaComponent($this->user) - ->set('form.quality', 'Premium') - ->set('form.size', (string) $size) - ->set('form.volume', '20') - ->call('create') - ->assertHasNoErrors(); - } - - $component = mountFormulaComponent($this->user); - - expect($component->formulas)->toHaveKey('100'); - expect($component->formulas)->toHaveKey('200'); - expect($component->formulas)->toHaveKey('300'); -}); - -it('handles empty formulas array after all deletions', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - $formula = FormulaModel::factory()->create([ - 'quality' => 'Premium', - 'size' => 100, - 'volume' => 20, - ]); - - $component = mountFormulaComponent($this->user); - $component->call('delete', $formula); - - expect($component->formulas)->toBeInstanceOf(\Illuminate\Support\Collection::class); - expect($component->formulas)->not->toHaveKey('100'); -}); - -it('maintains correct order after update', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - - $formula1 = FormulaModel::factory()->create([ - 'quality' => 'Premium', - 'size' => 100, - 'volume' => 10, - ]); - - $formula2 = FormulaModel::factory()->create([ - 'quality' => 'Super Premium', - 'size' => 100, - 'volume' => 30, - ]); - - $component = mountFormulaComponent($this->user) - ->call('openModal', 'update', 'Ubah Rumus', $formula1->hash) - ->set('form.volume', '50') - ->call('update'); - - $volumes = array_column($component->formulas[100], 'volume'); - expect($volumes[0])->toBeLessThan($volumes[1]); -}); - -it('handles very large volume values', function () { - $bottle = Bottle::factory()->create(['size' => 10000]); - - mountFormulaComponent($this->user) - ->set('form.quality', 'Premium') - ->set('form.size', '10000') - ->set('form.volume', '9999') - ->call('create') - ->assertHasNoErrors(); - - $this->assertDatabaseHas('formulas', [ - 'size' => 10000, - 'volume' => 9999, - ]); -}); - -it('handles minimum volume value', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - - mountFormulaComponent($this->user) - ->set('form.quality', 'Premium') - ->set('form.size', '100') - ->set('form.volume', '1') - ->call('create') - ->assertHasNoErrors(); - - $this->assertDatabaseHas('formulas', [ - 'size' => 100, - 'volume' => 1, - ]); -}); - -it('handles zero volume value', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - - mountFormulaComponent($this->user) - ->set('form.quality', 'Premium') - ->set('form.size', '100') - ->set('form.volume', '0') - ->call('create') - ->assertHasNoErrors(); - - $this->assertDatabaseHas('formulas', [ - 'size' => 100, - 'volume' => 0, - ]); -}); - -it('handles confirmation action for delete', function () { - $bottle = Bottle::factory()->create(['size' => 100]); - - $formula = FormulaModel::factory()->create([ - 'quality' => 'Premium', - 'size' => 100, - 'volume' => 20, - ]); - - $component = mountFormulaComponent($this->user); - - $component->dispatch('fn:confirmAction', $formula->hash); - - expect($component->confirmingId)->toBe($formula->hash); + $formula = FormulaModel::create(['quality' => 'Premium', 'size' => 100, 'volume' => 50]); + + Livewire::test(Formula::class) + ->call('delete', $formula->hash) + ->assertForbidden(); });