155 lines
4.4 KiB
PHP
155 lines
4.4 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use App\Enums\SmsSendStatus;
|
|
use App\Jobs\SendSmsToCouponJob;
|
|
use App\Models\Coupon;
|
|
use App\Models\SmsCampaign;
|
|
use App\Models\SmsSendLog;
|
|
use App\Models\User;
|
|
use App\Services\SmsBroadcastService;
|
|
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
|
|
use Illuminate\Support\Facades\Bus;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Support\Facades\Queue;
|
|
use Tests\TestCase;
|
|
|
|
class SmsBroadcastServiceTest extends TestCase
|
|
{
|
|
use LazilyRefreshDatabase;
|
|
|
|
private SmsBroadcastService $service;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
Http::fake([
|
|
config('services.sms.url') => Http::response('ok', 200),
|
|
]);
|
|
|
|
$this->service = app(SmsBroadcastService::class);
|
|
}
|
|
|
|
public function test_resolve_recipients_for_all_excluding_ids(): void
|
|
{
|
|
$included = Coupon::factory()->count(2)->create();
|
|
$excluded = Coupon::factory()->create();
|
|
|
|
$recipients = $this->service->resolveRecipients(
|
|
sendToAll: true,
|
|
excludedIds: [$excluded->id],
|
|
);
|
|
|
|
$this->assertCount(2, $recipients);
|
|
$this->assertTrue($recipients->pluck('id')->contains($included->first()->id));
|
|
$this->assertFalse($recipients->pluck('id')->contains($excluded->id));
|
|
}
|
|
|
|
public function test_resolve_recipients_for_selected_only(): void
|
|
{
|
|
$selected = Coupon::factory()->create();
|
|
Coupon::factory()->create();
|
|
|
|
$recipients = $this->service->resolveRecipients(
|
|
sendToAll: false,
|
|
selectedIds: [$selected->id],
|
|
);
|
|
|
|
$this->assertCount(1, $recipients);
|
|
$this->assertSame($selected->id, $recipients->first()->id);
|
|
}
|
|
|
|
public function test_start_campaign_queues_chain_and_creates_logs(): void
|
|
{
|
|
Bus::fake();
|
|
|
|
$admin = User::factory()->create();
|
|
$coupons = Coupon::factory()->count(2)->create();
|
|
|
|
$campaign = $this->service->startCampaign(
|
|
admin: $admin,
|
|
message: 'Test broadcast',
|
|
sendToAll: false,
|
|
selectedIds: $coupons->pluck('id')->all(),
|
|
);
|
|
|
|
$this->assertSame(2, $campaign->recipient_count);
|
|
$this->assertDatabaseCount(SmsSendLog::class, 2);
|
|
$this->assertDatabaseHas(SmsSendLog::class, [
|
|
'sms_campaign_id' => $campaign->id,
|
|
'status' => SmsSendStatus::Pending->value,
|
|
]);
|
|
|
|
Bus::assertChained([
|
|
SendSmsToCouponJob::class,
|
|
SendSmsToCouponJob::class,
|
|
]);
|
|
}
|
|
|
|
public function test_invalid_phone_is_skipped_without_queue_job(): void
|
|
{
|
|
Bus::fake();
|
|
|
|
$admin = User::factory()->create();
|
|
$invalid = Coupon::factory()->create(['phone' => '81234567']);
|
|
$valid = Coupon::factory()->create();
|
|
|
|
$campaign = $this->service->startCampaign(
|
|
admin: $admin,
|
|
message: 'Test',
|
|
sendToAll: false,
|
|
selectedIds: [$invalid->id, $valid->id],
|
|
);
|
|
|
|
$this->assertSame(2, $campaign->recipient_count);
|
|
$this->assertSame(1, $campaign->skipped_count);
|
|
|
|
$this->assertDatabaseHas(SmsSendLog::class, [
|
|
'coupon_id' => $invalid->id,
|
|
'status' => SmsSendStatus::SkippedInvalid->value,
|
|
]);
|
|
|
|
Bus::assertChained([
|
|
SendSmsToCouponJob::class,
|
|
]);
|
|
}
|
|
|
|
public function test_send_job_marks_success_and_completes_campaign(): void
|
|
{
|
|
Queue::fake();
|
|
|
|
$admin = User::factory()->create();
|
|
$coupon = Coupon::factory()->create(['phone' => '61929248']);
|
|
|
|
$campaign = SmsCampaign::factory()->create([
|
|
'message' => 'Queued hello',
|
|
'recipient_count' => 1,
|
|
'created_by' => $admin->id,
|
|
]);
|
|
|
|
SmsSendLog::factory()->create([
|
|
'sms_campaign_id' => $campaign->id,
|
|
'coupon_id' => $coupon->id,
|
|
'phone' => $coupon->phone,
|
|
'message' => $campaign->message,
|
|
'status' => SmsSendStatus::Pending,
|
|
]);
|
|
|
|
$job = new SendSmsToCouponJob($campaign, $coupon);
|
|
$job->handle();
|
|
|
|
Http::assertSentCount(1);
|
|
|
|
$campaign->refresh();
|
|
|
|
$this->assertSame(1, $campaign->sent_count);
|
|
$this->assertNotNull($campaign->completed_at);
|
|
$this->assertDatabaseHas(SmsSendLog::class, [
|
|
'sms_campaign_id' => $campaign->id,
|
|
'status' => SmsSendStatus::Sent->value,
|
|
]);
|
|
}
|
|
}
|