feat(voucher): membuat seeder dan mendaftarkannya ke DatabaseSeeder

-membuat factory untuk kebutuhan test
-membuat test untuk memastikan tidak ada error
This commit is contained in:
Yoga Pangestu 2025-09-28 22:18:58 +07:00
parent 270a23f656
commit 32468f9e8c
6 changed files with 289 additions and 0 deletions

View File

@ -0,0 +1,44 @@
<?php
namespace Database\Factories;
use App\Enums\IsActive;
use App\Enums\VoucherType;
use App\Models\Voucher;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class VoucherFactory extends Factory
{
protected $model = Voucher::class;
public function definition(): array
{
$type = $this->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,
];
});
}
}

View File

@ -11,6 +11,7 @@ public function run(): void
$this->call([
UserSeeder::class,
MembershipSeeder::class,
VoucherSeeder::class,
]);
}
}

View File

@ -0,0 +1,108 @@
<?php
namespace Database\Seeders;
use App\Enums\IsActive;
use App\Enums\VoucherType;
use App\Models\Voucher;
use Illuminate\Database\Seeder;
class VoucherSeeder extends Seeder
{
public function run(): void
{
Voucher::insert([
[
'name' => '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,
],
]);
}
}

View File

@ -0,0 +1,43 @@
<?php
use App\Livewire\Studio\Loyalty\Voucher\Create;
use App\Livewire\Studio\Loyalty\Voucher\Index;
use App\Models\Voucher;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
uses(RefreshDatabase::class);
it('renders successfully', function () {
Livewire::test(Create::class)
->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'],
]);
});

View File

@ -0,0 +1,51 @@
<?php
use App\Enums\IsActive;
use App\Livewire\Studio\Loyalty\Voucher\Edit;
use App\Livewire\Studio\Loyalty\Voucher\Index;
use App\Models\Voucher;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
uses(RefreshDatabase::class);
it('renders successfully', function () {
$voucher = Voucher::factory()->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'],
]);
});

View File

@ -0,0 +1,42 @@
<?php
use App\Enums\IsActive;
use App\Livewire\Studio\Loyalty\Voucher\Index;
use App\Models\Voucher;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
uses(RefreshDatabase::class);
it('renders successfully', function () {
Livewire::test(Index::class)
->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);
});