121 lines
3.8 KiB
PHP
121 lines
3.8 KiB
PHP
<?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']]);
|
|
});
|