diff --git a/tests/AltumClientTest.php b/tests/AltumClientTest.php new file mode 100644 index 0000000..03ed10a --- /dev/null +++ b/tests/AltumClientTest.php @@ -0,0 +1,181 @@ +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') + ); +}); diff --git a/tests/AltumManagerTest.php b/tests/AltumManagerTest.php new file mode 100644 index 0000000..1330d80 --- /dev/null +++ b/tests/AltumManagerTest.php @@ -0,0 +1,45 @@ +manager = new AltumManager([ + 'analytics' => ['url' => 'https://analytics.test', 'admin_key' => 'akey'], + 'biolinks' => ['url' => 'https://bio.test', 'admin_key' => 'bkey'], + 'pusher' => ['url' => 'https://push.test', 'admin_key' => 'pkey'], + 'socialproof' => ['url' => 'https://trust.test', 'admin_key' => 'skey'], + ]); +}); + +it('creates analytics client', function () { + expect($this->manager->analytics())->toBeInstanceOf(AnalyticsClient::class); +}); + +it('creates biolinks client', function () { + expect($this->manager->biolinks())->toBeInstanceOf(BiolinksClient::class); +}); + +it('creates pusher client', function () { + expect($this->manager->pusher())->toBeInstanceOf(PusherClient::class); +}); + +it('creates socialproof client', function () { + expect($this->manager->socialproof())->toBeInstanceOf(SocialproofClient::class); +}); + +it('passes user API key to client', function () { + $client = $this->manager->analytics('my-user-key'); + \Illuminate\Support\Facades\Http::fake(['*' => \Illuminate\Support\Facades\Http::response([], 200)]); + $client->user(); +})->throwsNoExceptions(); + +it('throws on unconfigured product', function () { + $mgr = new AltumManager([]); + $mgr->analytics(); +})->throws(\RuntimeException::class, 'not configured'); diff --git a/tests/Analytics/ClientTest.php b/tests/Analytics/ClientTest.php new file mode 100644 index 0000000..573a880 --- /dev/null +++ b/tests/Analytics/ClientTest.php @@ -0,0 +1,40 @@ +client = new Client( + baseUrl: 'https://analytics.test', + adminApiKey: 'admin-key', + userApiKey: 'user-key', + ); + Http::fake(['*' => Http::response(['data' => []], 200)]); +}); + +it('lists websites', function () { + $this->client->websites(); + Http::assertSent(fn ($r) => str_contains($r->url(), '/api/websites/')); +}); + +it('gets a website', function () { + $this->client->website(1); + Http::assertSent(fn ($r) => str_contains($r->url(), '/api/websites/1')); +}); + +it('creates a website', function () { + $this->client->createWebsite(['name' => 'Test', 'host' => 'example.com']); + Http::assertSent(fn ($r) => $r->method() === 'POST' && str_contains($r->url(), '/api/websites')); +}); + +it('fetches statistics', function () { + $this->client->statistics(['website_id' => 1]); + Http::assertSent(fn ($r) => str_contains($r->url(), '/api/statistics/')); +}); + +it('creates annotations', function () { + $this->client->createAnnotation(['website_id' => 1, 'title' => 'Deploy']); + Http::assertSent(fn ($r) => str_contains($r->url(), '/api/annotations')); +}); diff --git a/tests/Biolinks/ClientTest.php b/tests/Biolinks/ClientTest.php new file mode 100644 index 0000000..659d72e --- /dev/null +++ b/tests/Biolinks/ClientTest.php @@ -0,0 +1,40 @@ +client = new Client( + baseUrl: 'https://bio.test', + adminApiKey: 'admin-key', + userApiKey: 'user-key', + ); + Http::fake(['*' => Http::response(['data' => []], 200)]); +}); + +it('lists links', function () { + $this->client->links(); + Http::assertSent(fn ($r) => str_contains($r->url(), '/api/links/')); +}); + +it('creates a link', function () { + $this->client->createLink(['url' => 'https://example.com', 'type' => 'link']); + Http::assertSent(fn ($r) => $r->method() === 'POST' && str_contains($r->url(), '/api/links')); +}); + +it('gets link statistics', function () { + $this->client->linkStatistics(42); + Http::assertSent(fn ($r) => str_contains($r->url(), '/api/statistics/42')); +}); + +it('lists projects', function () { + $this->client->projects(); + Http::assertSent(fn ($r) => str_contains($r->url(), '/api/projects/')); +}); + +it('creates QR codes', function () { + $this->client->createQrCode(['name' => 'Test QR', 'link_id' => 1]); + Http::assertSent(fn ($r) => $r->method() === 'POST' && str_contains($r->url(), '/api/qr-codes')); +}); diff --git a/tests/Pest.php b/tests/Pest.php new file mode 100644 index 0000000..174d7fd --- /dev/null +++ b/tests/Pest.php @@ -0,0 +1,3 @@ +client = new Client( + baseUrl: 'https://push.test', + adminApiKey: 'admin-key', + userApiKey: 'user-key', + ); + Http::fake(['*' => Http::response(['data' => []], 200)]); +}); + +it('lists subscribers', function () { + $this->client->subscribers(); + Http::assertSent(fn ($r) => str_contains($r->url(), '/api/subscribers/')); +}); + +it('creates a campaign', function () { + $this->client->createCampaign(['title' => 'Test', 'url' => 'https://example.com']); + Http::assertSent(fn ($r) => $r->method() === 'POST' && str_contains($r->url(), '/api/campaigns')); +}); + +it('lists flows', function () { + $this->client->flows(); + Http::assertSent(fn ($r) => str_contains($r->url(), '/api/flows/')); +}); + +it('creates segments', function () { + $this->client->createSegment(['name' => 'VIP']); + Http::assertSent(fn ($r) => $r->method() === 'POST' && str_contains($r->url(), '/api/segments')); +}); diff --git a/tests/Socialproof/ClientTest.php b/tests/Socialproof/ClientTest.php new file mode 100644 index 0000000..244d967 --- /dev/null +++ b/tests/Socialproof/ClientTest.php @@ -0,0 +1,35 @@ +client = new Client( + baseUrl: 'https://trust.test', + adminApiKey: 'admin-key', + userApiKey: 'user-key', + ); + Http::fake(['*' => Http::response(['data' => []], 200)]); +}); + +it('lists campaigns', function () { + $this->client->campaigns(); + Http::assertSent(fn ($r) => str_contains($r->url(), '/api/campaigns/')); +}); + +it('creates a campaign', function () { + $this->client->createCampaign(['name' => 'Test Campaign', 'type' => 'recent_activity']); + Http::assertSent(fn ($r) => $r->method() === 'POST' && str_contains($r->url(), '/api/campaigns')); +}); + +it('manages notifications within campaigns', function () { + $this->client->createNotification(['campaign_id' => 1, 'title' => 'New sale']); + Http::assertSent(fn ($r) => $r->method() === 'POST' && str_contains($r->url(), '/api/notifications')); +}); + +it('fetches statistics', function () { + $this->client->statistics(); + Http::assertSent(fn ($r) => str_contains($r->url(), '/api/statistics/')); +});