whisper-money/tests/Feature/ResendSyncLeadsCommandTest.php

168 lines
5.5 KiB
PHP

<?php
use App\Models\UserLead;
use App\Services\ResendService;
use Resend\Exceptions\ErrorException;
use function Pest\Laravel\artisan;
use function Pest\Laravel\mock;
const TEST_RESEND_LEADS_SEGMENT_ID = 'test-segment-id';
test('resend:sync-leads syncs leads created in the last 24h by default', function () {
config([
'services.resend.key' => 'test-api-key',
'services.resend.leads_segment_id' => TEST_RESEND_LEADS_SEGMENT_ID,
]);
UserLead::factory()->count(2)->create();
UserLead::factory()->count(3)->create(['created_at' => now()->subDays(2)]);
$resendService = mock(ResendService::class);
$resendService->shouldReceive('syncLead')->times(2);
artisan('resend:sync-leads')
->expectsOutputToContain('Syncing 2 user leads to Resend...')
->expectsOutputToContain('Synced 2 user leads to Resend.')
->assertSuccessful();
});
test('resend:sync-leads syncs all leads when --since=0', function () {
config([
'services.resend.key' => 'test-api-key',
'services.resend.leads_segment_id' => TEST_RESEND_LEADS_SEGMENT_ID,
]);
UserLead::factory()->count(2)->create();
UserLead::factory()->count(3)->create(['created_at' => now()->subDays(2)]);
$resendService = mock(ResendService::class);
$resendService->shouldReceive('syncLead')->times(5);
artisan('resend:sync-leads', ['--since' => 0])
->expectsOutputToContain('Syncing 5 user leads to Resend...')
->expectsOutputToContain('Synced 5 user leads to Resend.')
->assertSuccessful();
});
test('resend:sync-leads only syncs verified user leads to resend', function () {
config([
'services.resend.key' => 'test-api-key',
'services.resend.leads_segment_id' => TEST_RESEND_LEADS_SEGMENT_ID,
]);
UserLead::factory()->count(2)->create();
UserLead::factory()->unverified()->count(2)->create();
$resendService = mock(ResendService::class);
$resendService->shouldReceive('syncLead')->times(2);
artisan('resend:sync-leads')
->expectsOutputToContain('Syncing 2 user leads to Resend...')
->expectsOutputToContain('Synced 2 user leads to Resend.')
->assertSuccessful();
});
test('resend:sync-leads fails when api key is not configured', function () {
config([
'services.resend.key' => null,
'services.resend.leads_segment_id' => TEST_RESEND_LEADS_SEGMENT_ID,
]);
artisan('resend:sync-leads')
->expectsOutputToContain('Resend API key not configured.')
->assertFailed();
});
test('resend:sync-leads fails when leads segment id is not configured', function () {
config([
'services.resend.key' => 'test-api-key',
'services.resend.leads_segment_id' => null,
]);
artisan('resend:sync-leads')
->expectsOutputToContain('Resend leads segment ID not configured.')
->assertFailed();
});
test('resend:sync-leads handles empty user leads', function () {
config([
'services.resend.key' => 'test-api-key',
'services.resend.leads_segment_id' => TEST_RESEND_LEADS_SEGMENT_ID,
]);
artisan('resend:sync-leads')
->expectsOutputToContain('No user leads to sync.')
->assertSuccessful();
});
test('resend:sync-leads reports failures and continues syncing', function () {
config([
'services.resend.key' => 'test-api-key',
'services.resend.leads_segment_id' => TEST_RESEND_LEADS_SEGMENT_ID,
]);
$firstLead = UserLead::factory()->create(['email' => 'first@example.com']);
$secondLead = UserLead::factory()->create(['email' => 'second@example.com']);
$resendService = mock(ResendService::class);
$resendService->shouldReceive('syncLead')->once()->with(Mockery::on(fn (UserLead $lead) => $lead->is($firstLead)));
$resendService->shouldReceive('syncLead')
->once()
->with(Mockery::on(fn (UserLead $lead) => $lead->is($secondLead)))
->andThrow(new RuntimeException('Duplicate request failed'));
artisan('resend:sync-leads')
->expectsOutputToContain('Failed to sync second@example.com: Duplicate request failed')
->expectsOutputToContain('Synced 1 user leads to Resend.')
->expectsOutputToContain('Failed to sync 1 user leads.')
->assertFailed();
});
test('syncLead adds an existing resend contact to the leads segment', function () {
config([
'services.resend.key' => 'test-api-key',
'services.resend.leads_segment_id' => TEST_RESEND_LEADS_SEGMENT_ID,
]);
$lead = UserLead::factory()->create(['email' => 'lead@example.com']);
$segmentsService = Mockery::mock();
$segmentsService->shouldReceive('add')
->once()
->with('lead@example.com', TEST_RESEND_LEADS_SEGMENT_ID);
$contactsService = new class($segmentsService)
{
public function __construct(public object $segments) {}
public function create(array $parameters): never
{
throw new ErrorException([
'message' => 'Contact already exists',
'name' => 'conflict_error',
'statusCode' => 409,
]);
}
};
$client = new class($contactsService)
{
public function __construct(public object $contacts) {}
};
$service = new class($client) extends ResendService
{
public function __construct(private readonly object $client) {}
protected function client(string $apiKey): object
{
expect($apiKey)->toBe('test-api-key');
return $this->client;
}
};
$service->syncLead($lead);
});