diff --git a/database/factories/VoucherFactory.php b/database/factories/VoucherFactory.php new file mode 100644 index 0000000..e7d4445 --- /dev/null +++ b/database/factories/VoucherFactory.php @@ -0,0 +1,44 @@ +faker->randomElement(VoucherType::values()); + + return [ + 'name' => $this->faker->words(2, true), + 'code' => Str::upper(Str::random(8)), + 'terms_conditions' => $this->faker->optional()->sentence(), + 'type' => $type, + 'discount_amount' => $type === VoucherType::PERCENTAGE->value + ? $this->faker->numberBetween(5, 50) + : $this->faker->numberBetween(10000, 100000), + 'min_purchase' => $this->faker->optional()->numberBetween(50000, 200000), + 'max_discount' => $type === VoucherType::PERCENTAGE->value ? $this->faker->numberBetween(10000, 50000) : null, + 'quota' => $this->faker->optional()->numberBetween(50, 500), + 'limit_per_user' => $this->faker->optional()->numberBetween(1, 5), + 'start_date' => $this->faker->dateTimeBetween('-1 week', '+1 week')->format('Y-m-d'), + 'end_date' => $this->faker->optional()->dateTimeBetween('+1 day', '+2 months')?->format('Y-m-d'), + ]; + } + + public function active(): Factory + { + return $this->state(function (array $attributes) { + return [ + 'is_active' => IsActive::ACTIVE, + ]; + }); + } +} diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index a62809a..9365482 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -11,6 +11,7 @@ public function run(): void $this->call([ UserSeeder::class, MembershipSeeder::class, + VoucherSeeder::class, ]); } } diff --git a/database/seeders/VoucherSeeder.php b/database/seeders/VoucherSeeder.php new file mode 100644 index 0000000..9aa42a9 --- /dev/null +++ b/database/seeders/VoucherSeeder.php @@ -0,0 +1,108 @@ + 'Diskon 10%', + 'code' => 'DISC10', + 'type' => VoucherType::PERCENTAGE, + 'discount_amount' => 10, + 'min_purchase' => 50000, + 'max_discount' => 20000, + 'quota' => 100, + 'limit_per_user' => 2, + 'start_date' => now()->subDays(5), + 'end_date' => now()->addMonth(), + 'is_active' => IsActive::ACTIVE, + ], + [ + 'name' => 'Diskon 20%', + 'code' => 'DISC20', + 'type' => VoucherType::PERCENTAGE, + 'discount_amount' => 20, + 'min_purchase' => 100000, + 'max_discount' => 50000, + 'quota' => 50, + 'limit_per_user' => 1, + 'start_date' => now(), + 'end_date' => now()->addDays(30), + 'is_active' => IsActive::ACTIVE, + ], + [ + 'name' => 'Potongan Rp25K', + 'code' => 'SAVE25K', + 'type' => VoucherType::FIXED, + 'discount_amount' => 25000, + 'min_purchase' => 100000, + 'max_discount' => null, + 'quota' => 200, + 'limit_per_user' => 3, + 'start_date' => now(), + 'end_date' => now()->addDays(15), + 'is_active' => IsActive::ACTIVE, + ], + [ + 'name' => 'Potongan Rp50K', + 'code' => 'SAVE50K', + 'type' => VoucherType::FIXED, + 'discount_amount' => 50000, + 'min_purchase' => 200000, + 'max_discount' => null, + 'quota' => 80, + 'limit_per_user' => 1, + 'start_date' => now()->addDays(3), + 'end_date' => now()->addDays(60), + 'is_active' => IsActive::ACTIVE, + ], + [ + 'name' => 'Gratis Ongkir', + 'code' => 'ONGKIR', + 'type' => VoucherType::FIXED, + 'discount_amount' => 15000, + 'min_purchase' => 50000, + 'max_discount' => 15000, + 'quota' => 500, + 'limit_per_user' => 5, + 'start_date' => now(), + 'end_date' => now()->addDays(90), + 'is_active' => IsActive::ACTIVE, + ], + [ + 'name' => 'Flash Sale 30%', + 'code' => 'FLASH30', + 'type' => VoucherType::PERCENTAGE, + 'discount_amount' => 30, + 'min_purchase' => 75000, + 'max_discount' => 40000, + 'quota' => 30, + 'limit_per_user' => 1, + 'start_date' => now()->subDay(), + 'end_date' => now()->addDay(), + 'is_active' => IsActive::ACTIVE, + ], + [ + 'name' => 'Spesial Member', + 'code' => 'MEMBER15', + 'type' => VoucherType::PERCENTAGE, + 'discount_amount' => 15, + 'min_purchase' => 50000, + 'max_discount' => 25000, + 'quota' => null, + 'limit_per_user' => null, + 'start_date' => now(), + 'end_date' => null, + 'is_active' => IsActive::ACTIVE, + ], + ]); + } +} diff --git a/tests/Feature/Livewire/Studio/Loyalty/Voucher/CreateTest.php b/tests/Feature/Livewire/Studio/Loyalty/Voucher/CreateTest.php new file mode 100644 index 0000000..a19ec94 --- /dev/null +++ b/tests/Feature/Livewire/Studio/Loyalty/Voucher/CreateTest.php @@ -0,0 +1,43 @@ +assertViewIs('livewire.studio.loyalty.voucher.form') + ->assertViewHas('pageTitle', 'Tambah Voucher'); +}); + +it('can create a voucher', function () { + $data = Voucher::factory() + ->active() + ->raw(); + + Livewire::test(Create::class) + ->set('form.name', $data['name']) + ->set('form.code', $data['code']) + ->set('form.min_purchase', $data['min_purchase']) + ->set('form.quota', $data['quota']) + ->set('form.limit_per_user', $data['limit_per_user']) + ->set('form.start_date', $data['start_date']) + ->set('form.end_date', $data['end_date']) + ->set('form.terms_conditions', $data['terms_conditions']) + ->set('form.type', $data['type']) + ->set('form.discount_amount', $data['discount_amount']) + ->set('form.max_discount', $data['max_discount']) + ->set('form.is_active', $data['is_active']->value) + ->call('save') + ->assertHasNoErrors() + ->assertRedirect(Index::class); + + $this->assertDatabaseHas('vouchers', [ + 'name' => $data['name'], + 'code' => $data['code'], + ]); +}); diff --git a/tests/Feature/Livewire/Studio/Loyalty/Voucher/EditTest.php b/tests/Feature/Livewire/Studio/Loyalty/Voucher/EditTest.php new file mode 100644 index 0000000..c34e655 --- /dev/null +++ b/tests/Feature/Livewire/Studio/Loyalty/Voucher/EditTest.php @@ -0,0 +1,51 @@ +active()->create(); + + Livewire::test(Edit::class, ['voucher' => $voucher]) + ->assertViewIs('livewire.studio.loyalty.voucher.form') + ->assertViewHas('pageTitle', 'Ubah Voucher'); +}); + +it('can update a voucher', function () { + $voucher = Voucher::factory()->active()->create(); + + $data = Voucher::factory() + ->state(fn () => [ + 'is_active' => fake()->randomElement(IsActive::cases()), + ]) + ->raw(); + + Livewire::test(Edit::class, ['voucher' => $voucher]) + ->set('form.name', $data['name']) + ->set('form.code', $data['code']) + ->set('form.min_purchase', $data['min_purchase']) + ->set('form.quota', $data['quota']) + ->set('form.limit_per_user', $data['limit_per_user']) + ->set('form.start_date', $data['start_date']) + ->set('form.end_date', $data['end_date']) + ->set('form.terms_conditions', $data['terms_conditions']) + ->set('form.type', $data['type']) + ->set('form.discount_amount', $data['discount_amount']) + ->set('form.max_discount', $data['max_discount']) + ->set('form.is_active', $data['is_active']->value) + ->call('save') + ->assertDispatched('refreshDatatable') + ->assertRedirect(Index::class); + + $this->assertDatabaseHas('vouchers', [ + 'id' => $voucher->id, + 'name' => $data['name'], + 'code' => $data['code'], + ]); +}); diff --git a/tests/Feature/Livewire/Studio/Loyalty/Voucher/IndexTest.php b/tests/Feature/Livewire/Studio/Loyalty/Voucher/IndexTest.php new file mode 100644 index 0000000..80de996 --- /dev/null +++ b/tests/Feature/Livewire/Studio/Loyalty/Voucher/IndexTest.php @@ -0,0 +1,42 @@ +assertViewIs('livewire.studio.loyalty.voucher.index') + ->assertViewHas('pageTitle', 'Voucher'); +}); + +it('displays all vouchers', function () { + Voucher::factory() + ->count(10) + ->state(fn () => [ + 'is_active' => fake()->randomElement(IsActive::cases()), + ]) + ->create(); + + $voucher = Voucher::first(); + + Livewire::test(Index::class)->assertSee($voucher->name); +}); + +it('can delete a voucher', function () { + $voucher = Voucher::factory() + ->state(fn () => [ + 'is_active' => fake()->randomElement(IsActive::cases()), + ]) + ->create(); + + Livewire::test(Index::class) + ->call('delete', $voucher) + ->assertDispatched('refreshDatatable'); + + expect(Voucher::count())->toBe(0); +});