test: add Pest tests for AltumClient, product clients, and AltumManager

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Snider 2026-03-10 08:53:09 +00:00
parent afbd7bb3b8
commit 25a2903db3
7 changed files with 379 additions and 0 deletions

181
tests/AltumClientTest.php Normal file
View file

@ -0,0 +1,181 @@
<?php
declare(strict_types=1);
use Core\Plug\Altum\AltumClient;
use Illuminate\Support\Facades\Http;
beforeEach(function () {
$this->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')
);
});

View file

@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
use Core\Plug\Altum\AltumManager;
use Core\Plug\Altum\Analytics\Client as AnalyticsClient;
use Core\Plug\Altum\Biolinks\Client as BiolinksClient;
use Core\Plug\Altum\Pusher\Client as PusherClient;
use Core\Plug\Altum\Socialproof\Client as SocialproofClient;
beforeEach(function () {
$this->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');

View file

@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
use Core\Plug\Altum\Analytics\Client;
use Illuminate\Support\Facades\Http;
beforeEach(function () {
$this->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'));
});

View file

@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
use Core\Plug\Altum\Biolinks\Client;
use Illuminate\Support\Facades\Http;
beforeEach(function () {
$this->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'));
});

3
tests/Pest.php Normal file
View file

@ -0,0 +1,3 @@
<?php
declare(strict_types=1);

View file

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
use Core\Plug\Altum\Pusher\Client;
use Illuminate\Support\Facades\Http;
beforeEach(function () {
$this->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'));
});

View file

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
use Core\Plug\Altum\Socialproof\Client;
use Illuminate\Support\Facades\Http;
beforeEach(function () {
$this->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/'));
});