create(); [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner'); $snapshot = seedTenantReviewEvidence($tenant); $review = composeTenantReviewForTest($tenant, $user, $snapshot); $review->forceFill([ 'status' => TenantReviewStatus::Published->value, 'published_at' => now(), 'published_by_user_id' => (int) $user->getKey(), ])->save(); $this->actingAs($user) ->get(TenantReviewResource::tenantScopedUrl('view', ['record' => $review], $tenant)) ->assertOk() ->assertSee(CustomerReviewWorkspace::tenantPrefilterUrl($tenant), false); }); it('adds a customer workspace entry to evidence snapshot related context', function (): void { $tenant = Tenant::factory()->create(); $snapshot = EvidenceSnapshot::query()->create([ 'tenant_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'status' => EvidenceSnapshotStatus::Active->value, 'summary' => [], 'generated_at' => now(), ]); $entry = collect(EvidenceSnapshotResource::relatedContextEntries($snapshot)) ->firstWhere('key', 'customer_review_workspace'); expect($entry)->not->toBeNull() ->and($entry['targetUrl'] ?? null)->toBe(CustomerReviewWorkspace::tenantPrefilterUrl($tenant)); }); it('renders a customer workspace link from review pack detail context', function (): void { $tenant = Tenant::factory()->create(); [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner'); $snapshot = seedTenantReviewEvidence($tenant); $review = composeTenantReviewForTest($tenant, $user, $snapshot); $review->forceFill([ 'status' => TenantReviewStatus::Published->value, 'published_at' => now(), 'published_by_user_id' => (int) $user->getKey(), ])->save(); Storage::disk('exports')->put('review-packs/customer-workspace-link.zip', 'PK-test'); $pack = ReviewPack::factory()->ready()->create([ 'tenant_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'tenant_review_id' => (int) $review->getKey(), 'evidence_snapshot_id' => (int) $snapshot->getKey(), 'initiated_by_user_id' => (int) $user->getKey(), 'file_path' => 'review-packs/customer-workspace-link.zip', 'file_disk' => 'exports', ]); $this->actingAs($user) ->get(ReviewPackResource::getUrl('view', ['record' => $pack], tenant: $tenant, panel: 'tenant')) ->assertOk() ->assertSee(CustomerReviewWorkspace::tenantPrefilterUrl($tenant), false); }); it('renders a customer workspace launch button on the tenant review pack widget', function (): void { $tenant = Tenant::factory()->create(); [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner'); $snapshot = seedTenantReviewEvidence($tenant); $review = composeTenantReviewForTest($tenant, $user, $snapshot); $review->forceFill([ 'status' => TenantReviewStatus::Published->value, 'published_at' => now(), 'published_by_user_id' => (int) $user->getKey(), ])->save(); Storage::disk('exports')->put('review-packs/widget-customer-workspace.zip', 'PK-test'); ReviewPack::factory()->ready()->create([ 'tenant_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'tenant_review_id' => (int) $review->getKey(), 'evidence_snapshot_id' => (int) $snapshot->getKey(), 'initiated_by_user_id' => (int) $user->getKey(), 'file_path' => 'review-packs/widget-customer-workspace.zip', 'file_disk' => 'exports', ]); setTenantPanelContext($tenant); Livewire::actingAs($user) ->test(TenantReviewPackCard::class, ['record' => $tenant]) ->assertSee('Customer workspace') ->assertSee(CustomerReviewWorkspace::tenantPrefilterUrl($tenant), false); }); it('keeps the linked tenant review detail read-only for a readonly-capable actor', function (): void { $tenant = Tenant::factory()->create(); [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'readonly'); $snapshot = seedTenantReviewEvidence($tenant); $review = composeTenantReviewForTest($tenant, $user, $snapshot); $review->forceFill([ 'status' => TenantReviewStatus::Published->value, 'published_at' => now(), 'published_by_user_id' => (int) $user->getKey(), ])->save(); setTenantPanelContext($tenant); Livewire::withQueryParams([CustomerReviewWorkspace::DETAIL_CONTEXT_QUERY_KEY => 1]) ->actingAs($user) ->test(ViewTenantReview::class, ['record' => $review->getKey()]) ->assertSee('Outcome summary') ->assertActionDoesNotExist('publish_review') ->assertActionDoesNotExist('refresh_review') ->assertActionDoesNotExist('create_next_review') ->assertActionDoesNotExist('export_executive_pack') ->assertActionHidden('archive_review'); $audit = AuditLog::query() ->where('action', AuditActionId::TenantReviewOpened->value) ->latest('id') ->first(); expect($audit)->not->toBeNull() ->and($audit?->resource_type)->toBe('tenant_review') ->and(data_get($audit?->metadata, 'review_id'))->toBe((int) $review->getKey()) ->and(data_get($audit?->metadata, 'source_surface'))->toBe('customer_review_workspace'); });