client = new AltumClient( baseUrl: 'https://test.example.com', adminApiKey: 'test-admin-key', userApiKey: 'test-user-key', ); }); it('builds correct user API GET URL', function () { Http::fake([ 'test.example.com/api/user' => Http::response(['data' => ['id' => 1]], 200), ]); $result = $this->client->user(); expect($result)->toHaveKey('data'); expect($result['data']['id'])->toBe(1); }); it('lists resources with pagination params', function () { Http::fake([ 'test.example.com/api/websites/*' => Http::response(['data' => []], 200), ]); $result = $this->client->listResource('websites', ['page' => 2, 'results_per_page' => 10]); expect($result)->toHaveKey('data'); Http::assertSent(fn ($request) => str_contains($request->url(), 'page=2') && str_contains($request->url(), 'results_per_page=10') ); }); it('creates resources via POST', function () { Http::fake([ 'test.example.com/api/links' => Http::response(['data' => ['id' => 42]], 200), ]); $result = $this->client->createResource('links', ['url' => 'https://example.com']); expect($result['data']['id'])->toBe(42); Http::assertSent(fn ($request) => $request->method() === 'POST' && str_contains($request->url(), '/api/links') ); }); it('updates resources via POST with ID', function () { Http::fake([ 'test.example.com/api/links/42' => Http::response(['data' => ['id' => 42]], 200), ]); $this->client->updateResource('links', 42, ['url' => 'https://new.com']); Http::assertSent(fn ($request) => $request->method() === 'POST' && str_contains($request->url(), '/api/links/42') ); }); it('deletes resources', function () { Http::fake([ 'test.example.com/api/links/42' => Http::response([], 200), ]); $this->client->deleteResource('links', 42); Http::assertSent(fn ($request) => $request->method() === 'DELETE' && str_contains($request->url(), '/api/links/42') ); }); it('sends Bearer auth for user API', function () { Http::fake(['*' => Http::response([], 200)]); $this->client->user(); Http::assertSent(fn ($request) => $request->hasHeader('Authorization', 'Bearer test-user-key') ); }); it('sends Bearer auth for admin API', function () { Http::fake(['*' => Http::response([], 200)]); $this->client->listAdminUsers(); Http::assertSent(fn ($request) => $request->hasHeader('Authorization', 'Bearer test-admin-key') ); }); it('throws when user API called without key', function () { $client = new AltumClient( baseUrl: 'https://test.example.com', adminApiKey: 'test-admin-key', ); $client->user(); })->throws(\RuntimeException::class, 'User API key not set'); it('returns new instance with withUserKey', function () { $client = new AltumClient( baseUrl: 'https://test.example.com', adminApiKey: 'admin-key', ); $withKey = $client->withUserKey('new-key'); expect($withKey)->not->toBe($client); Http::fake(['*' => Http::response([], 200)]); $withKey->user(); Http::assertSent(fn ($request) => $request->hasHeader('Authorization', 'Bearer new-key') ); }); it('returns error array on HTTP failure', function () { Http::fake(['*' => Http::response('Unauthorized', 401)]); $result = $this->client->user(); expect($result)->toHaveKey('error', true); expect($result)->toHaveKey('status', 401); }); it('returns error array on exception', function () { Http::fake(['*' => fn () => throw new \Exception('Connection refused')]); $result = $this->client->user(); expect($result)->toHaveKey('error', true); expect($result['message'])->toContain('Connection refused'); }); it('creates user with named params', function () { Http::fake(['*' => Http::response(['data' => ['id' => 5]], 200)]); $this->client->createUser('Test User', 'test@example.com', 'secret123'); Http::assertSent(fn ($request) => $request->method() === 'POST' && str_contains($request->url(), '/admin-api/users') && $request['name'] === 'Test User' && $request['email'] === 'test@example.com' && $request['password'] === 'secret123' ); }); it('assigns VIP plan with correct defaults', function () { Http::fake(['*' => Http::response([], 200)]); $this->client->assignVipPlan(5); Http::assertSent(fn ($request) => $request->method() === 'POST' && str_contains($request->url(), '/admin-api/users/5') && $request['plan_id'] == 2 && $request['plan_expiration_date'] === '2056-01-01' ); }); it('uses form encoding for POST requests', function () { Http::fake(['*' => Http::response([], 200)]); $this->client->createResource('links', ['url' => 'https://example.com']); Http::assertSent(fn ($request) => str_contains($request->header('Content-Type')[0] ?? '', 'application/x-www-form-urlencoded') ); });