fakeTransferBillingApi(); config([ 'transfer.service_api_keys' => ['sms' => 'test-sms-key'], 'identity.api_url' => 'https://ladill.com/api', 'identity.api_key' => 'test-identity-key', ]); } public function test_sms_service_can_upload_voice_recording(): void { $publicId = (string) Str::uuid(); Http::fake([ rtrim((string) config('identity.api_url'), '/').'/identity/profile*' => Http::response([ 'data' => [ 'public_id' => $publicId, 'name' => 'SMS User', 'email' => 'sms@acme.com', 'picture' => null, ], ]), ]); $voice = UploadedFile::fake()->create('greeting.mp3', 120, 'audio/mpeg'); $this->withToken('test-sms-key') ->post('/api/v1/transfers/voice', [ 'user' => $publicId, 'title' => 'SMS voice: greeting.mp3', 'voice' => $voice, ]) ->assertCreated() ->assertJsonPath('data.direct_file_url', fn (string $url) => str_contains($url, '/transfer/files/')) ->assertJsonStructure([ 'data' => [ 'direct_file_url', 'public_url', 'transfer_id', 'file_id', 'paid_until', 'storage_gb', 'monthly_cost_ghs', ], ]); $this->assertDatabaseHas('users', ['public_id' => $publicId]); $this->assertDatabaseCount('transfers', 1); } public function test_voice_upload_rejects_non_sms_callers(): void { config(['transfer.service_api_keys' => ['webmail' => 'test-webmail-key']]); $this->withToken('test-webmail-key') ->post('/api/v1/transfers/voice', [ 'user' => (string) Str::uuid(), 'voice' => UploadedFile::fake()->create('greeting.mp3', 120, 'audio/mpeg'), ]) ->assertForbidden(); } public function test_voice_upload_returns_insufficient_wallet_error_code(): void { $publicId = (string) Str::uuid(); User::factory()->create(['public_id' => $publicId]); $this->mock(TransferBillingService::class, function ($mock): void { $mock->shouldReceive('chargeInitialPeriod') ->once() ->andThrow(new \RuntimeException( 'Insufficient wallet balance for the first month of storage. Top up your Ladill wallet and try again.' )); }); $voice = UploadedFile::fake()->create('greeting.mp3', 120, 'audio/mpeg'); $this->withToken('test-sms-key') ->post('/api/v1/transfers/voice', [ 'user' => $publicId, 'voice' => $voice, ]) ->assertStatus(422) ->assertJsonPath('error_code', 'insufficient_wallet'); $this->assertDatabaseCount('transfers', 0); } }