parfum/tests/Feature/Studio/Loyalty/TierTest.php

159 lines
5.0 KiB
PHP

<?php
use App\Livewire\Studio\Loyalty\Tier;
use App\Models\Tier as TierModel;
use Livewire\Livewire;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
beforeEach(function () {
$this->setupUser();
$role = Role::firstOrCreate(['name' => 'Owner']);
Permission::firstOrCreate(['name' => 'view tier']);
Permission::firstOrCreate(['name' => 'create tier']);
Permission::firstOrCreate(['name' => 'update tier']);
Permission::firstOrCreate(['name' => 'delete tier']);
$role->givePermissionTo(['view tier', 'create tier', 'update tier', 'delete tier']);
$this->user->assignRole($role);
});
it('renders the tier index page correctly', function () {
$this->actingAs($this->user)
->get(route('studio.loyalty.tier.index'))
->assertOk()
->assertSeeLivewire(Tier::class);
});
it('can open create modal', function () {
Livewire::actingAs($this->user)
->test(Tier::class)
->dispatch('modal:open', method: 'create', modalTitle: 'Tambah Tier')
->assertSet('method', 'create')
->assertSet('modalTitle', 'Tambah Tier');
});
it('validates required fields on create', function () {
Livewire::actingAs($this->user)
->test(Tier::class)
->call('create')
->assertHasErrors(['form.name' => 'required', 'form.min_spending' => 'required']);
});
it('can store a new tier', function () {
// Ensure no tiers exist first
TierModel::query()->delete();
Livewire::actingAs($this->user)
->test(Tier::class)
->set('form.name', 'Bronze')
->set('form.min_spending', '0')
->call('create')
->assertHasNoErrors();
$this->assertDatabaseHas('tiers', [
'name' => 'Bronze',
'min_spending' => 0,
]);
});
it('automatically reorders tier chain on create', function () {
TierModel::query()->delete();
// Create first tier manually
TierModel::create(['name' => 'Bronze', 'min_spending' => 0]);
// Create second tier via Livewire
Livewire::actingAs($this->user)
->test(Tier::class)
->set('form.name', 'Silver')
->set('form.min_spending', '10.000') // 10,000
->call('create')
->assertHasNoErrors();
// First tier should now have max_spending = 9999
$bronze = TierModel::where('name', 'Bronze')->first();
expect($bronze->max_spending)->toBe(9999);
// Silver should have null max_spending
$silver = TierModel::where('name', 'Silver')->first();
expect($silver->max_spending)->toBeNull();
});
it('can open edit modal and load data', function () {
$tier = TierModel::factory()->create([
'name' => 'Gold',
'min_spending' => 50000,
'max_spending' => null,
]);
Livewire::actingAs($this->user)
->test(Tier::class)
->call('openModal', 'update', 'Ubah Tier', $tier->hash_id)
->set('form.tier', $tier)
->set('form.name', 'Gold')
->set('form.min_spending', formatCurrencyNumber(50000))
->assertSet('method', 'update')
->assertSet('modalTitle', 'Ubah Tier')
->assertSet('form.name', 'Gold')
->assertSet('form.min_spending', formatCurrencyNumber(50000));
});
it('can update a tier', function () {
$tier = TierModel::factory()->create(['name' => 'Old Name', 'min_spending' => 0]);
Livewire::actingAs($this->user)
->test(Tier::class)
->call('openModal', 'update', 'Ubah Tier', $tier->hash_id)
->set('form.tier', $tier)
->set('form.name', 'New Name')
->set('form.min_spending', '0')
->call('update')
->assertHasNoErrors();
$this->assertDatabaseHas('tiers', [
'id' => $tier->id,
'name' => 'New Name',
]);
});
it('can delete the last tier', function () {
TierModel::query()->delete();
$tier1 = TierModel::create(['name' => 'Bronze', 'min_spending' => 0]);
$tier2 = TierModel::create(['name' => 'Silver', 'min_spending' => 10000]);
TierModel::reorderTierChain();
Livewire::actingAs($this->user)
->test(Tier::class)
->call('delete', $tier2->id); // Deleting highest tier (Silver)
$this->assertSoftDeleted('tiers', ['id' => $tier2->id]);
// Bronze should now be the last tier with null max_spending
$tier1->refresh();
expect($tier1->max_spending)->toBeNull();
});
it('cannot delete a middle tier', function () {
TierModel::query()->delete();
$tier1 = TierModel::create(['name' => 'Bronze', 'min_spending' => 0]);
$tier2 = TierModel::create(['name' => 'Silver', 'min_spending' => 10000]);
$tier3 = TierModel::create(['name' => 'Gold', 'min_spending' => 20000]);
TierModel::reorderTierChain();
Livewire::actingAs($this->user)
->test(Tier::class)
->call('delete', $tier2->id);
$this->assertDatabaseHas('tiers', ['id' => $tier2->id]);
});
it('cannot access tier page without permission', function () {
$this->user->roles()->detach();
$this->user->permissions()->detach();
$this->actingAs($this->user)
->get(route('studio.loyalty.tier.index'))
->assertForbidden();
});