94 خطوط
4.6 KiB
PHP
94 خطوط
4.6 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\Subscriptions;
|
|
|
|
use App\Models\User;
|
|
use App\Modules\Identity\Domain\Enums\UserRole;
|
|
use App\Modules\Organizations\Domain\Organization;
|
|
use App\Modules\Subscriptions\Domain\Subscription;
|
|
use App\Modules\System\Domain\DeploymentCapabilities;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Laravel\Sanctum\Sanctum;
|
|
use Tests\TestCase;
|
|
|
|
class SubscriptionAuthorizationTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
public function test_designer_reads_only_current_tenant_subscription(): void
|
|
{
|
|
$designer = User::factory()->create(['role' => UserRole::CourseDesigner]);
|
|
$current = Subscription::query()->create([
|
|
'organization_id' => $designer->organization_id,
|
|
'plan_key' => 'enterprise',
|
|
'status' => 'active',
|
|
'starts_at' => now()->subDay(),
|
|
'seat_limit' => 250,
|
|
'storage_quota_bytes' => 1000,
|
|
'storage_used_bytes' => 400,
|
|
'ai_credit_quota' => 500,
|
|
'ai_credits_used' => 125,
|
|
'enabled_features' => ['taxonomy', 'exports'],
|
|
]);
|
|
$otherDesigner = User::factory()->create(['role' => UserRole::CourseDesigner]);
|
|
Subscription::query()->create([
|
|
'organization_id' => $otherDesigner->organization_id,
|
|
'plan_key' => 'private-plan',
|
|
'status' => 'active',
|
|
'starts_at' => now()->subDay(),
|
|
]);
|
|
Sanctum::actingAs($designer);
|
|
|
|
$this->getJson('/api/v1/subscription?organization_id='.$otherDesigner->organization_id)
|
|
->assertOk()
|
|
->assertJsonPath('data.id', $current->getKey())
|
|
->assertJsonPath('data.seatLimit', 250)
|
|
->assertJsonPath('data.seatUsed', 1)
|
|
->assertJsonPath('data.storageUsedBytes', 400)
|
|
->assertJsonPath('data.aiCreditsUsed', 125)
|
|
->assertJsonPath('data.enabledFeatures.0', 'taxonomy')
|
|
->assertJsonMissing(['planKey' => 'private-plan']);
|
|
}
|
|
|
|
public function test_manager_cannot_view_subscription_configuration(): void
|
|
{
|
|
$manager = User::factory()->create(['role' => UserRole::Manager]);
|
|
Sanctum::actingAs($manager);
|
|
|
|
$this->getJson('/api/v1/subscription')->assertForbidden();
|
|
}
|
|
|
|
public function test_super_admin_can_list_create_and_update_platform_subscriptions_with_audit(): void
|
|
{
|
|
$organization = Organization::factory()->create(['name' => 'Acme Platform']);
|
|
Sanctum::actingAs(User::factory()->create(['organization_id' => null, 'role' => UserRole::SuperAdmin]));
|
|
|
|
$id = $this->postJson('/api/v1/platform/subscriptions', [
|
|
'organizationId' => $organization->getKey(), 'planKey' => 'enterprise', 'status' => 'active',
|
|
'startsAt' => now()->subDay()->toISOString(), 'expiresAt' => now()->addMonth()->toISOString(),
|
|
'seatLimit' => 100, 'storageQuotaBytes' => 100000, 'aiCreditQuota' => 2000, 'enabledFeatures' => ['exports', 'taxonomy'],
|
|
])->assertCreated()->assertJsonPath('data.organization.name', 'Acme Platform')->json('data.id');
|
|
|
|
$this->getJson('/api/v1/platform/subscriptions?search=acme&status=active&plan=enterprise&perPage=10')
|
|
->assertOk()->assertJsonPath('meta.total', 1)->assertJsonPath('data.0.id', $id)->assertJsonPath('data.0.seatLimit', 100);
|
|
|
|
$this->patchJson('/api/v1/platform/subscriptions/'.$id, ['planKey' => 'enterprise-plus', 'seatLimit' => 150, 'expiresAt' => null, 'status' => 'suspended'])
|
|
->assertOk()->assertJsonPath('data.planKey', 'enterprise-plus')->assertJsonPath('data.status', 'suspended')->assertJsonPath('data.seatLimit', 150);
|
|
$this->assertDatabaseHas('subscriptions', ['id' => $id, 'expires_at' => null]);
|
|
|
|
$this->assertDatabaseHas('audit_logs', ['organization_id' => $organization->getKey(), 'action' => 'subscription.created', 'entity_id' => $id]);
|
|
$this->assertDatabaseHas('audit_logs', ['organization_id' => $organization->getKey(), 'action' => 'subscription.updated', 'entity_id' => $id]);
|
|
}
|
|
|
|
public function test_tenant_roles_and_unsupported_deployments_cannot_manage_platform_subscriptions(): void
|
|
{
|
|
Sanctum::actingAs(User::factory()->create(['role' => UserRole::CourseDesigner]));
|
|
$this->getJson('/api/v1/platform/subscriptions')->assertForbidden();
|
|
|
|
config()->set('deployment.mode', 'on_premise');
|
|
$this->app->forgetInstance(DeploymentCapabilities::class);
|
|
Sanctum::actingAs(User::factory()->create(['organization_id' => null, 'role' => UserRole::SuperAdmin]));
|
|
$this->getJson('/api/v1/platform/subscriptions')->assertNotFound();
|
|
}
|
|
}
|