SMS service
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
use App\Jobs\SendSmsJob;
|
||||
use App\Models\Permission;
|
||||
use App\Models\Role;
|
||||
use App\Models\SmsLog;
|
||||
use App\Models\SmsProfile;
|
||||
use App\Models\SmsSender;
|
||||
use App\Models\User;
|
||||
use App\Services\Sms\SmsClient;
|
||||
use App\Services\Sms\SmsMessage;
|
||||
use App\Services\Sms\SmsResult;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
function adminUserForSms(): User
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
// Ensure admin role & manage-settings permission exist
|
||||
$role = Role::firstOrCreate(['slug' => 'admin'], ['name' => 'Admin']);
|
||||
$permission = Permission::firstOrCreate(['slug' => 'manage-settings'], ['name' => 'Manage Settings']);
|
||||
$user->roles()->syncWithoutDetaching([$role->id]);
|
||||
if (method_exists($user, 'givePermissionTo')) {
|
||||
$user->givePermissionTo('manage-settings');
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
it('creates an sms profile and encrypts password', function () {
|
||||
$user = adminUserForSms();
|
||||
test()->actingAs($user);
|
||||
|
||||
$resp = test()->postJson(route('admin.sms-profiles.store'), [
|
||||
'name' => 'Primary SMS',
|
||||
'active' => true,
|
||||
'api_username' => 'testuser',
|
||||
'api_password' => 'super-secret',
|
||||
]);
|
||||
|
||||
$resp->assertCreated();
|
||||
$resp->assertJsonStructure(['profile' => ['id', 'uuid', 'name', 'active', 'api_username', 'created_at', 'updated_at']]);
|
||||
|
||||
$profile = SmsProfile::first();
|
||||
expect($profile)->not->toBeNull();
|
||||
// Attribute is hidden, but verify decrypt roundtrip via model method
|
||||
expect($profile->decryptApiPassword())->toBe('super-secret');
|
||||
});
|
||||
|
||||
it('queues a job to send sms and logs as sent', function () {
|
||||
$user = adminUserForSms();
|
||||
test()->actingAs($user);
|
||||
|
||||
$profile = SmsProfile::factory()->create([
|
||||
'api_username' => 'apiuser',
|
||||
'api_password' => 'apipass',
|
||||
]);
|
||||
$sender = SmsSender::factory()->create(['profile_id' => $profile->id]);
|
||||
|
||||
// Bind a fake client that always returns sent with provider id
|
||||
app()->instance(SmsClient::class, new class implements SmsClient
|
||||
{
|
||||
public function send(App\Models\SmsProfile $profile, SmsMessage $message): SmsResult
|
||||
{
|
||||
return new SmsResult('sent', '123456');
|
||||
}
|
||||
|
||||
public function getCreditBalance(App\Models\SmsProfile $profile): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPriceQuotes(App\Models\SmsProfile $profile): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
// Run the job synchronously
|
||||
(new SendSmsJob(
|
||||
profileId: $profile->id,
|
||||
to: '+38640111222',
|
||||
content: 'Hello from test',
|
||||
senderId: null,
|
||||
countryCode: null,
|
||||
deliveryReport: true,
|
||||
clientReference: null,
|
||||
))->handle(app(\App\Services\Sms\SmsService::class));
|
||||
|
||||
$log = SmsLog::first();
|
||||
expect($log)->not->toBeNull();
|
||||
expect($log->status)->toBe('sent');
|
||||
expect($log->provider_message_id)->toBe('123456');
|
||||
});
|
||||
|
||||
it('returns balance and price quotes', function () {
|
||||
$user = adminUserForSms();
|
||||
test()->actingAs($user);
|
||||
|
||||
$profile = SmsProfile::factory()->create([
|
||||
'api_username' => 'apiuser',
|
||||
'api_password' => 'apipass',
|
||||
]);
|
||||
|
||||
$base = config('services.sms.providers.smsapi_si.base_url');
|
||||
$creditsUrl = rtrim($base, '/').config('services.sms.providers.smsapi_si.credits_endpoint', '/preveri-stanje-kreditov');
|
||||
$priceUrl = rtrim($base, '/').config('services.sms.providers.smsapi_si.price_endpoint', '/dobi-ceno');
|
||||
|
||||
Http::fake([
|
||||
$creditsUrl => Http::response('42', 200),
|
||||
$priceUrl => Http::response('0.05 EUR##0.07 EUR', 200),
|
||||
]);
|
||||
|
||||
test()->postJson(route('admin.sms-profiles.balance', $profile))
|
||||
->assertSuccessful()
|
||||
->assertJson(['balance' => '42']);
|
||||
|
||||
test()->postJson(route('admin.sms-profiles.price', $profile))
|
||||
->assertSuccessful()
|
||||
->assertJson(['quotes' => ['0.05 EUR', '0.07 EUR']]);
|
||||
});
|
||||
Reference in New Issue
Block a user