extend(Tests\TestCase::class) ->use(RefreshDatabase::class) ->in('Feature'); pest()->extend(Tests\TestCase::class) ->in('Unit'); pest()->extend(Tests\TestCase::class) ->in('Deprecation'); beforeEach(function () { putenv('INTUNE_TENANT_ID'); unset($_ENV['INTUNE_TENANT_ID'], $_SERVER['INTUNE_TENANT_ID']); }); /* |-------------------------------------------------------------------------- | Expectations |-------------------------------------------------------------------------- | | When you're writing tests, you often need to check that values meet certain conditions. The | "expect()" function gives you access to a set of "expectations" methods that you can use | to assert different things. Of course, you may extend the Expectation API at any time. | */ expect()->extend('toBeOne', function () { return $this->toBe(1); }); function fakeIdToken(string $tenantId): string { $header = rtrim(strtr(base64_encode(json_encode(['alg' => 'HS256', 'typ' => 'JWT'])), '+/', '-_'), '='); $payload = rtrim(strtr(base64_encode(json_encode(['tid' => $tenantId])), '+/', '-_'), '='); return $header.'.'.$payload.'.signature'; } /* |-------------------------------------------------------------------------- | Functions |-------------------------------------------------------------------------- | | While Pest is very powerful out-of-the-box, you may have some testing code specific to your | project that you don't want to repeat in every file. Here you can also expose helpers as | global functions to help you to reduce the number of lines of code in your test files. | */ function something() { // .. } /** * Spec test naming helper. * * Convention for focused runs: * - Prefix every Spec 081 test title with "Spec081 ". * - Keep filenames suffixed with "Spec081Test.php". * - Command: `vendor/bin/sail artisan test --compact --filter=Spec081` */ function spec081(string $description): string { $normalized = trim($description); if ($normalized === '') { return 'Spec081'; } return str_starts_with($normalized, 'Spec081 ') ? $normalized : 'Spec081 '.$normalized; } /** * Convenience wrapper for Spec 081 tests. */ function itSpec081(string $description, ?\Closure $closure = null): TestCall { $call = it(spec081($description), $closure); $call->group('spec081'); return $call; } function bindFailHardGraphClient(): void { app()->instance(GraphClientInterface::class, new FailHardGraphClient); } function assertNoOutboundHttp(\Closure $callback): mixed { return AssertsNoOutboundHttp::run($callback); } /** * @param array $attributes */ function createInventorySyncOperationRun(Tenant $tenant, array $attributes = []): \App\Models\OperationRun { $context = is_array($attributes['context'] ?? null) ? $attributes['context'] : []; if (array_key_exists('selection_hash', $attributes)) { if (is_string($attributes['selection_hash']) && $attributes['selection_hash'] !== '') { $context['selection_hash'] = $attributes['selection_hash']; } unset($attributes['selection_hash']); } if (array_key_exists('selection_payload', $attributes)) { if (is_array($attributes['selection_payload'])) { $context = array_merge($context, $attributes['selection_payload']); } unset($attributes['selection_payload']); } if (! isset($context['selection_hash']) || ! is_string($context['selection_hash']) || $context['selection_hash'] === '') { $context['selection_hash'] = hash('sha256', 'inventory-sync-selection-default'); } if (! isset($context['policy_types']) || ! is_array($context['policy_types'])) { $context['policy_types'] = ['deviceConfiguration']; } if (! isset($context['categories']) || ! is_array($context['categories'])) { $context['categories'] = []; } if (! array_key_exists('include_foundations', $context)) { $context['include_foundations'] = false; } if (! array_key_exists('include_dependencies', $context)) { $context['include_dependencies'] = false; } $finishedAt = $attributes['finished_at'] ?? null; unset($attributes['finished_at']); $providedStatus = (string) ($attributes['status'] ?? 'success'); $normalizedStatus = match ($providedStatus) { 'pending', 'queued' => 'queued', 'running' => 'running', 'completed' => 'completed', default => 'completed', }; $normalizedOutcome = match ($providedStatus) { 'success' => 'succeeded', 'partial' => 'partially_succeeded', 'skipped' => 'blocked', 'failed' => 'failed', 'pending', 'queued', 'running' => 'pending', default => $normalizedStatus === 'completed' ? 'succeeded' : 'pending', }; $attributes['type'] = (string) ($attributes['type'] ?? 'inventory_sync'); $attributes['workspace_id'] = (int) ($attributes['workspace_id'] ?? $tenant->workspace_id); $attributes['status'] = in_array($providedStatus, ['queued', 'running', 'completed'], true) ? $providedStatus : $normalizedStatus; $attributes['outcome'] = (string) ($attributes['outcome'] ?? $normalizedOutcome); $attributes['context'] = array_merge($context, is_array($attributes['context'] ?? null) ? $attributes['context'] : []); if ($finishedAt !== null && ! array_key_exists('completed_at', $attributes)) { $attributes['completed_at'] = $finishedAt; } return \App\Models\OperationRun::factory() ->for($tenant) ->create($attributes); } /** * @return array{0: User, 1: Tenant} */ function createUserWithTenant( ?Tenant $tenant = null, ?User $user = null, string $role = 'owner', ?string $workspaceRole = null, bool $ensureDefaultMicrosoftProviderConnection = true, ): array { $user ??= User::factory()->create(); $tenant ??= Tenant::factory()->create(); $workspaceRole ??= $role; $validWorkspaceRoles = array_map( static fn (\App\Support\Auth\WorkspaceRole $role): string => $role->value, \App\Support\Auth\WorkspaceRole::cases(), ); if (! in_array($workspaceRole, $validWorkspaceRoles, true)) { $workspaceRole = \App\Support\Auth\WorkspaceRole::Owner->value; } $workspace = null; if ($tenant->workspace_id !== null) { $workspace = Workspace::query()->whereKey($tenant->workspace_id)->first(); } if (! $workspace instanceof Workspace) { $workspace = Workspace::factory()->create(); $tenant->forceFill([ 'workspace_id' => (int) $workspace->getKey(), ])->save(); } WorkspaceMembership::query()->updateOrCreate([ 'workspace_id' => (int) $workspace->getKey(), 'user_id' => (int) $user->getKey(), ], [ 'role' => $workspaceRole, ]); session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey()); $user->forceFill(['last_workspace_id' => (int) $workspace->getKey()])->save(); $user->tenants()->syncWithoutDetaching([ $tenant->getKey() => ['role' => $role], ]); if ($ensureDefaultMicrosoftProviderConnection) { ensureDefaultProviderConnection($tenant, 'microsoft'); } return [$user, $tenant]; } /** * @return array{tenant: string} */ function filamentTenantRouteParams(Tenant $tenant): array { return ['tenant' => (string) $tenant->external_id]; } function ensureDefaultProviderConnection(Tenant $tenant, string $provider = 'microsoft'): ProviderConnection { $connection = ProviderConnection::query() ->where('tenant_id', (int) $tenant->getKey()) ->where('provider', $provider) ->orderByDesc('is_default') ->orderBy('id') ->first(); if (! $connection instanceof ProviderConnection) { $connection = ProviderConnection::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), 'provider' => $provider, 'entra_tenant_id' => (string) ($tenant->tenant_id ?? fake()->uuid()), 'status' => 'connected', 'health_status' => 'ok', 'is_default' => true, ]); } else { $entraTenantId = trim((string) $connection->entra_tenant_id); $updates = []; if (! $connection->is_default) { $updates['is_default'] = true; } if ($connection->status !== 'connected') { $updates['status'] = 'connected'; } if ($connection->health_status !== 'ok') { $updates['health_status'] = 'ok'; } if ($entraTenantId === '') { $updates['entra_tenant_id'] = (string) ($tenant->tenant_id ?? fake()->uuid()); } if ($updates !== []) { $connection->forceFill($updates)->save(); $connection->refresh(); } } $credential = $connection->credential()->first(); if (! $credential instanceof ProviderCredential) { ProviderCredential::factory()->create([ 'provider_connection_id' => (int) $connection->getKey(), 'type' => 'client_secret', 'payload' => [ 'client_id' => fake()->uuid(), 'client_secret' => fake()->sha1(), ], ]); $connection->refresh(); } return $connection; }