seed(RolePermissionSeeder::class); }); // ─── Helper ─────────────────────────────────────────────── function createCustomerUserWithPermission(PermissionEnum ...$permissions): User { $user = User::factory()->create(); $user->givePermissionTo( array_merge( [PermissionEnum::DASHBOARD_VIEW->value], array_map(fn (PermissionEnum $p) => $p->value, $permissions) ) ); $user->forgetCachedPermissions(); return $user; } // ─── Index ──────────────────────────────────────────────── describe('Customer Index', function () { test('authenticated user with permission can view customer index', function () { $user = createCustomerUserWithPermission(PermissionEnum::CUSTOMERS_VIEW); Customer::factory()->count(3)->create(); $this->actingAs($user) ->get(route('admin.master.customers.index')) ->assertOk(); }); test('guest is redirected to login', function () { $this->get(route('admin.master.customers.index')) ->assertRedirect(route('login')); }); test('user without permission is forbidden', function () { $user = User::factory()->create(); $this->actingAs($user) ->get(route('admin.master.customers.index')) ->assertForbidden(); }); test('index returns customers with pagination', function () { $user = createCustomerUserWithPermission(PermissionEnum::CUSTOMERS_VIEW); Customer::factory()->count(15)->create(); $this->actingAs($user) ->get(route('admin.master.customers.index')) ->assertOk(); }); test('index can search customers by name', function () { $user = createCustomerUserWithPermission(PermissionEnum::CUSTOMERS_VIEW); Customer::factory()->create(['name' => 'Budi']); Customer::factory()->create(['name' => 'Ucup']); $this->actingAs($user) ->get(route('admin.master.customers.index', ['search' => 'Maju'])) ->assertOk(); }); }); // ─── Store ──────────────────────────────────────────────── describe('Customer Store', function () { test('authenticated user with permission can create a customer', function () { $user = createCustomerUserWithPermission(PermissionEnum::CUSTOMERS_VIEW, PermissionEnum::CUSTOMERS_CREATE); $this->actingAs($user) ->post(route('admin.master.customers.store'), [ 'name' => 'Ujang', 'phone_number' => '081234567890', 'address' => 'Jl. Merdeka No. 1', ]) ->assertRedirect(route('admin.master.customers.index')); $this->assertDatabaseHas('customers', [ 'name' => 'Ujang', 'phone_number' => '081234567890', 'address' => 'Jl. Merdeka No. 1', ]); }); test('guest cannot create a customer', function () { $this->post(route('admin.master.customers.store'), [ 'name' => 'Ujang', ])->assertRedirect(route('login')); }); test('user without create permission is forbidden', function () { $user = createCustomerUserWithPermission(PermissionEnum::CUSTOMERS_VIEW); $this->actingAs($user) ->post(route('admin.master.customers.store'), [ 'name' => 'Ujang', ]) ->assertForbidden(); $this->assertDatabaseCount('customers', 0); }); test('name is required', function () { $user = createCustomerUserWithPermission(PermissionEnum::CUSTOMERS_VIEW, PermissionEnum::CUSTOMERS_CREATE); $this->actingAs($user) ->post(route('admin.master.customers.store'), [ 'name' => '', ]) ->assertSessionHasErrors('name'); $this->assertDatabaseCount('customers', 0); }); test('name must not exceed 200 characters', function () { $user = createCustomerUserWithPermission(PermissionEnum::CUSTOMERS_VIEW, PermissionEnum::CUSTOMERS_CREATE); $this->actingAs($user) ->post(route('admin.master.customers.store'), [ 'name' => str_repeat('a', 201), ]) ->assertSessionHasErrors('name'); $this->assertDatabaseCount('customers', 0); }); test('phone number must start with 08', function () { $user = createCustomerUserWithPermission(PermissionEnum::CUSTOMERS_VIEW, PermissionEnum::CUSTOMERS_CREATE); $this->actingAs($user) ->post(route('admin.master.customers.store'), [ 'name' => 'Ujang', 'phone_number' => '0211234567', ]) ->assertSessionHasErrors('phone_number'); $this->assertDatabaseCount('customers', 0); }); test('phone number can be null', function () { $user = createCustomerUserWithPermission(PermissionEnum::CUSTOMERS_VIEW, PermissionEnum::CUSTOMERS_CREATE); $this->actingAs($user) ->post(route('admin.master.customers.store'), [ 'name' => 'Ujang', 'phone_number' => null, ]) ->assertRedirect(route('admin.master.customers.index')); $this->assertDatabaseHas('customers', [ 'name' => 'Ujang', 'phone_number' => null, ]); }); test('address can be null', function () { $user = createCustomerUserWithPermission(PermissionEnum::CUSTOMERS_VIEW, PermissionEnum::CUSTOMERS_CREATE); $this->actingAs($user) ->post(route('admin.master.customers.store'), [ 'name' => 'Ujang', 'address' => null, ]) ->assertRedirect(route('admin.master.customers.index')); $this->assertDatabaseHas('customers', [ 'name' => 'Ujang', 'address' => null, ]); }); }); // ─── Update ─────────────────────────────────────────────── describe('Customer Update', function () { test('authenticated user with permission can update a customer', function () { $user = createCustomerUserWithPermission(PermissionEnum::CUSTOMERS_VIEW, PermissionEnum::CUSTOMERS_UPDATE); $customer = Customer::factory()->create(['name' => 'Nama Lama']); $this->actingAs($user) ->put(route('admin.master.customers.update', $customer), [ 'name' => 'Nama Baru', 'phone_number' => '089876543210', 'address' => 'Jl. Baru No. 2', ]) ->assertRedirect(route('admin.master.customers.index')); $this->assertDatabaseHas('customers', [ 'id' => $customer->id, 'name' => 'Nama Baru', 'phone_number' => '089876543210', 'address' => 'Jl. Baru No. 2', ]); }); test('guest cannot update a customer', function () { $customer = Customer::factory()->create(); $this->put(route('admin.master.customers.update', $customer), [ 'name' => 'Nama Baru', ])->assertRedirect(route('login')); }); test('user without update permission is forbidden', function () { $user = createCustomerUserWithPermission(PermissionEnum::CUSTOMERS_VIEW); $customer = Customer::factory()->create(['name' => 'Nama Lama']); $this->actingAs($user) ->put(route('admin.master.customers.update', $customer), [ 'name' => 'Nama Baru', ]) ->assertForbidden(); $this->assertDatabaseHas('customers', [ 'id' => $customer->id, 'name' => 'Nama Lama', ]); }); test('name is required on update', function () { $user = createCustomerUserWithPermission(PermissionEnum::CUSTOMERS_VIEW, PermissionEnum::CUSTOMERS_UPDATE); $customer = Customer::factory()->create(); $this->actingAs($user) ->put(route('admin.master.customers.update', $customer), [ 'name' => '', ]) ->assertSessionHasErrors('name'); }); test('name must not exceed 200 characters on update', function () { $user = createCustomerUserWithPermission(PermissionEnum::CUSTOMERS_VIEW, PermissionEnum::CUSTOMERS_UPDATE); $customer = Customer::factory()->create(); $this->actingAs($user) ->put(route('admin.master.customers.update', $customer), [ 'name' => str_repeat('a', 201), ]) ->assertSessionHasErrors('name'); }); test('phone number validation on update', function () { $user = createCustomerUserWithPermission(PermissionEnum::CUSTOMERS_VIEW, PermissionEnum::CUSTOMERS_UPDATE); $customer = Customer::factory()->create(); $this->actingAs($user) ->put(route('admin.master.customers.update', $customer), [ 'name' => 'Nama Valid', 'phone_number' => '123invalid', ]) ->assertSessionHasErrors('phone_number'); }); }); // ─── Destroy ────────────────────────────────────────────── describe('Customer Destroy', function () { test('authenticated user with permission can delete a customer', function () { $user = createCustomerUserWithPermission(PermissionEnum::CUSTOMERS_VIEW, PermissionEnum::CUSTOMERS_DELETE); $customer = Customer::factory()->create(); $this->actingAs($user) ->delete(route('admin.master.customers.destroy', $customer)) ->assertRedirect(route('admin.master.customers.index')); $this->assertSoftDeleted('customers', [ 'id' => $customer->id, ]); }); test('guest cannot delete a customer', function () { $customer = Customer::factory()->create(); $this->delete(route('admin.master.customers.destroy', $customer)) ->assertRedirect(route('login')); $this->assertNotSoftDeleted('customers', [ 'id' => $customer->id, ]); }); test('user without delete permission is forbidden', function () { $user = createCustomerUserWithPermission(PermissionEnum::CUSTOMERS_VIEW); $customer = Customer::factory()->create(); $this->actingAs($user) ->delete(route('admin.master.customers.destroy', $customer)) ->assertForbidden(); $this->assertNotSoftDeleted('customers', [ 'id' => $customer->id, ]); }); test('deleted customer is soft deleted', function () { $user = createCustomerUserWithPermission(PermissionEnum::CUSTOMERS_VIEW, PermissionEnum::CUSTOMERS_DELETE); $customer = Customer::factory()->create(); $this->actingAs($user) ->delete(route('admin.master.customers.destroy', $customer)); $this->assertSoftDeleted('customers', ['id' => $customer->id]); $this->assertDatabaseHas('customers', ['id' => $customer->id]); }); }); // ─── Customer Model ─────────────────────────────────────── describe('Customer Model', function () { test('customer uses soft deletes', function () { $customer = Customer::factory()->create(); $customer->delete(); expect($customer->trashed())->toBeTrue(); }); test('customer can have orders', function () { $customer = Customer::factory()->create(); expect($customer->orders)->toBeInstanceOf(Collection::class); }); });