create([ 'managed_environment_id' => (int) $tenant->getKey(), 'name' => 'Nightly backup', ]); $run = OperationRun::factory()->for($tenant)->create([ 'workspace_id' => (int) $tenant->workspace_id, 'type' => 'backup_set.update', 'context' => [ 'backup_set_id' => (int) $backupSet->getKey(), ], ]); $context = new CanonicalNavigationContext( sourceSurface: 'backup_set.detail_section', canonicalRouteName: 'admin.operations.view', tenantId: (int) $tenant->getKey(), backLinkLabel: 'Back to backup set', backLinkUrl: BackupSetResource::getUrl('view', ['record' => $backupSet], tenant: $tenant), ); $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]) ->get(OperationRunLinks::tenantlessView($run, $context)) ->assertOk() ->assertSee('Monitoring detail') ->assertSee('Related drilldown') ->assertSee('Back to backup set') ->assertSee(BackupSetResource::getUrl('view', ['record' => $backupSet], tenant: $tenant), false) ->assertSee('Related context') ->assertSee($backupSet->name); }); it('preserves workspace overview lineage through operations row detail links', function (): void { [$user, $tenant] = createUserWithTenant(role: 'owner'); $run = OperationRun::factory()->for($tenant)->create([ 'workspace_id' => (int) $tenant->workspace_id, 'type' => 'provider.connection.check', 'status' => OperationRunStatus::Completed->value, 'outcome' => OperationRunOutcome::Blocked->value, 'initiator_name' => 'Context preserving run', ]); $overviewContext = new CanonicalNavigationContext( sourceSurface: 'workspace.overview', canonicalRouteName: 'admin.home', backLinkLabel: 'Back to overview', backLinkUrl: route('admin.home'), ); $operationsUrl = OperationRunLinks::index( context: $overviewContext, workspace: $tenant->workspace, ); $expectedDetailUrl = OperationRunLinks::viewFromOperationsIndex($run, $operationsUrl); $response = $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]) ->get($operationsUrl) ->assertOk() ->assertSee('Back to overview'); $html = html_entity_decode((string) $response->getContent(), ENT_QUOTES | ENT_HTML5); expect($html) ->toContain($expectedDetailUrl) ->toContain('Back%20to%20Operations'); }); it('preserves operations lineage through provider connection verification detours', function (): void { [$user, $tenant] = createUserWithTenant(role: 'owner'); $connection = ProviderConnection::factory()->platform()->create([ 'workspace_id' => (int) $tenant->workspace_id, 'managed_environment_id' => (int) $tenant->getKey(), 'is_default' => true, 'consent_status' => ProviderConsentStatus::Required->value, 'verification_status' => ProviderVerificationStatus::Unknown->value, ]); $run = OperationRun::factory()->for($tenant)->create([ 'workspace_id' => (int) $tenant->workspace_id, 'type' => 'provider.connection.check', 'status' => OperationRunStatus::Completed->value, 'outcome' => OperationRunOutcome::Blocked->value, 'context' => [ 'provider_connection_id' => (int) $connection->getKey(), ], ]); $overviewContext = new CanonicalNavigationContext( sourceSurface: 'workspace.overview', canonicalRouteName: 'admin.home', backLinkLabel: 'Back to overview', backLinkUrl: route('admin.home'), ); $operationsUrl = OperationRunLinks::index( context: $overviewContext, workspace: $tenant->workspace, ); $operationsContext = OperationRunLinks::operationsIndexNavigationContext($run, $operationsUrl); $expectedProviderUrl = OperationRunLinks::withNavigationContext( ManagedEnvironmentLinks::providerConnectionsUrl($tenant), $operationsContext, ); $expectedVerificationUrl = OperationRunLinks::view($run, $tenant, $operationsContext); $detailResponse = $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]) ->get(OperationRunLinks::tenantlessView($run, $operationsContext)) ->assertOk() ->assertSee('Back to Operations'); expect(html_entity_decode((string) $detailResponse->getContent(), ENT_QUOTES | ENT_HTML5)) ->toContain($expectedProviderUrl); $providerResponse = $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]) ->get($expectedProviderUrl) ->assertOk() ->assertSee('Provider consent required') ->assertSee('Open verification operation'); expect(html_entity_decode((string) $providerResponse->getContent(), ENT_QUOTES | ENT_HTML5)) ->toContain($expectedVerificationUrl); $verificationResponse = $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]) ->get($expectedVerificationUrl) ->assertOk() ->assertSee('Back to Operations'); expect(html_entity_decode((string) $verificationResponse->getContent(), ENT_QUOTES | ENT_HTML5)) ->toContain($operationsUrl); });