['account' => self::API_KEY]]); } protected function tearDown(): void { Carbon::setTestNow(); parent::tearDown(); } public function test_platform_can_assign_hosting_package_to_user(): void { Carbon::setTestNow('2026-04-05 10:00:00'); $owner = User::query()->create([ 'public_id' => (string) \Illuminate\Support\Str::uuid(), 'name' => 'Hosting Owner', 'email' => 'owner@example.com', ]); $product = $this->createHostingProduct(); $response = $this->withToken(self::API_KEY) ->postJson('/api/platform/users/'.$owner->public_id.'/hosting-accounts', [ 'hosting_product_id' => $product->id, 'duration_months' => 6, 'primary_domain' => 'example.com', 'username' => 'exampleuser', 'owner_email' => $owner->email, 'owner_name' => $owner->name, 'assigned_by_admin' => 99, ]); $response->assertCreated() ->assertJsonPath('data.account.username', 'exampleuser') ->assertJsonPath('data.account.primary_domain', 'example.com') ->assertJsonPath('data.account.status', 'active') ->assertJsonPath('data.account.metadata.assigned_duration_months', 6) ->assertJsonPath('data.account.metadata.assigned_by_admin', 99); $account = HostingAccount::query()->where('user_id', $owner->id)->firstOrFail(); $this->assertTrue($account->expires_at->equalTo(Carbon::parse('2026-10-05 10:00:00'))); } public function test_platform_can_list_user_hosting_accounts(): void { $owner = User::query()->create([ 'public_id' => (string) \Illuminate\Support\Str::uuid(), 'name' => 'Hosting Owner', 'email' => 'owner@example.com', ]); $product = $this->createHostingProduct(); HostingAccount::query()->create([ 'user_id' => $owner->id, 'hosting_product_id' => $product->id, 'username' => 'listeduser', 'type' => 'shared', 'status' => 'active', 'metadata' => ['assigned_duration_months' => 3], ]); $response = $this->withToken(self::API_KEY) ->getJson('/api/platform/users/'.$owner->public_id.'/hosting-accounts'); $response->assertOk() ->assertJsonCount(1, 'data') ->assertJsonPath('data.0.username', 'listeduser'); } public function test_platform_can_update_duration_and_renew(): void { Carbon::setTestNow('2026-04-05 10:00:00'); $owner = User::query()->create([ 'public_id' => (string) \Illuminate\Support\Str::uuid(), 'name' => 'Hosting Owner', 'email' => 'owner@example.com', ]); $product = $this->createHostingProduct(); $account = HostingAccount::query()->create([ 'user_id' => $owner->id, 'hosting_product_id' => $product->id, 'username' => 'durationuser', 'type' => 'shared', 'status' => 'active', 'expires_at' => Carbon::parse('2026-05-05 10:00:00'), 'metadata' => ['assigned_duration_months' => 1], ]); $this->withToken(self::API_KEY) ->patchJson('/api/platform/hosting-accounts/'.$account->id.'/duration', [ 'duration_months' => 12, 'admin_id' => 7, ]) ->assertOk() ->assertJsonPath('data.metadata.assigned_duration_months', 12); $account->refresh(); $this->assertTrue($account->expires_at->equalTo(Carbon::parse('2027-04-05 10:00:00'))); $this->withToken(self::API_KEY) ->postJson('/api/platform/hosting-accounts/'.$account->id.'/renew', ['admin_id' => 7]) ->assertOk(); $account->refresh(); $this->assertTrue($account->expires_at->equalTo(Carbon::parse('2028-04-05 10:00:00'))); } public function test_unauthenticated_platform_requests_are_rejected(): void { $this->getJson('/api/platform/hosting-products')->assertUnauthorized(); } private function createHostingProduct(): HostingProduct { return HostingProduct::query()->create([ 'name' => 'Admin Assigned Shared Hosting', 'slug' => 'admin-assigned-shared-hosting', 'category' => 'shared', 'type' => 'single_domain', 'price_monthly' => 10, 'price_quarterly' => 30, 'price_yearly' => 120, 'price_biennial' => 240, 'currency' => 'GHS', 'max_domains' => 1, 'is_active' => true, 'is_visible' => true, 'sort_order' => 1, ]); } }