239 lines
9.9 KiB
PHP
239 lines
9.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
|
|
use App\Models\ManagedEnvironment;
|
|
use App\Models\ReviewPack;
|
|
use App\Models\User;
|
|
use App\Support\EnvironmentReviewStatus;
|
|
use App\Support\Governance\Controls\ComplianceEvidenceMappingV1;
|
|
use App\Support\Workspaces\WorkspaceContext;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
pest()->browser()->timeout(60_000);
|
|
|
|
beforeEach(function (): void {
|
|
Storage::fake('exports');
|
|
});
|
|
|
|
it('Spec326 smokes clean customer review workspace entry', function (): void {
|
|
[$user, $environmentA, $environmentB] = spec326CustomerReviewWorkspaceFixture();
|
|
spec326AuthenticateCustomerReviewWorkspaceBrowser($this, $user, $environmentA);
|
|
|
|
visit(CustomerReviewWorkspace::getUrl(panel: 'admin'))
|
|
->waitForText('Customer-safe review packages')
|
|
->assertDontSee('No environment selected')
|
|
->assertDontSee('Environment filter:')
|
|
->assertSee('Is this review ready to share?')
|
|
->assertSee('Evidence path')
|
|
->assertSee('Review pack state')
|
|
->assertSee('Accepted risks')
|
|
->assertSee('Disclosure rule')
|
|
->assertSee('Diagnostics')
|
|
->assertSee('Collapsed')
|
|
->assertSee('Raw/support')
|
|
->assertSee('Review package index')
|
|
->assertSee('Decision trail')
|
|
->assertSee('Customer-safe follow-ups')
|
|
->assertScript('(() => {
|
|
const decision = document.querySelector("[data-testid=\"customer-review-decision-card\"]");
|
|
const aside = document.querySelector("[data-testid=\"customer-review-evidence-aside\"]");
|
|
|
|
if (! decision || ! aside) {
|
|
return false;
|
|
}
|
|
|
|
const decisionBox = decision.getBoundingClientRect();
|
|
const asideBox = aside.getBoundingClientRect();
|
|
|
|
return window.innerWidth < 768 || asideBox.left > decisionBox.left;
|
|
})()', true)
|
|
->assertSee($environmentB->name)
|
|
->assertDontSee('entitled tenant')
|
|
->assertDontSee('tenant filter')
|
|
->assertDontSee('raw payload should stay hidden')
|
|
->assertDontSee('stack trace should stay hidden')
|
|
->assertDontSee('provider secret should stay hidden')
|
|
->assertDontSee('debug metadata should stay hidden')
|
|
->assertDontSee('source fingerprint should stay hidden')
|
|
->assertScript('document.querySelector("[data-testid=\"customer-review-diagnostics\"]")?.open === false', true)
|
|
->assertNoJavaScriptErrors()
|
|
->assertNoConsoleLogs()
|
|
->screenshot(true, spec326CustomerReviewWorkspaceScreenshot('customer-review-workspace--clean'));
|
|
});
|
|
|
|
it('Spec326 smokes filtered customer review workspace clear and reload behavior', function (): void {
|
|
[$user, $environmentA, $environmentB] = spec326CustomerReviewWorkspaceFixture();
|
|
$cleanPath = json_encode((string) parse_url(CustomerReviewWorkspace::getUrl(panel: 'admin'), PHP_URL_PATH), JSON_THROW_ON_ERROR);
|
|
spec326AuthenticateCustomerReviewWorkspaceBrowser($this, $user, $environmentA);
|
|
|
|
$page = visit(CustomerReviewWorkspace::environmentFilterUrl($environmentA))
|
|
->waitForText('Environment filter:')
|
|
->assertSee($environmentA->name)
|
|
->assertDontSee($environmentB->name)
|
|
->assertSee('Environment filter: '.$environmentA->name)
|
|
->assertSee('Is this review ready to share?')
|
|
->assertSee('Evidence path')
|
|
->assertSee('Review package index')
|
|
->assertScript('document.querySelector("[data-testid=\"customer-review-diagnostics\"]")?.open === false', true)
|
|
->assertNoJavaScriptErrors()
|
|
->assertNoConsoleLogs()
|
|
->screenshot(true, spec326CustomerReviewWorkspaceScreenshot('customer-review-workspace--filtered'));
|
|
|
|
$page
|
|
->click('[data-testid="workspace-hub-environment-filter-clear"]')
|
|
->waitForText($environmentB->name)
|
|
->assertDontSee('Environment filter:')
|
|
->assertSee($environmentB->name)
|
|
->assertScript("window.location.pathname === {$cleanPath}", true)
|
|
->assertScript('! window.location.search.includes("environment_id=")', true)
|
|
->assertNoJavaScriptErrors()
|
|
->assertNoConsoleLogs()
|
|
->screenshot(true, spec326CustomerReviewWorkspaceScreenshot('customer-review-workspace--after-clear'));
|
|
|
|
$page->script('window.location.reload();');
|
|
|
|
$page
|
|
->waitForText($environmentB->name)
|
|
->assertDontSee('Environment filter:')
|
|
->assertSee($environmentB->name)
|
|
->assertScript("window.location.pathname === {$cleanPath}", true)
|
|
->assertScript('! window.location.search.includes("environment_id=")', true)
|
|
->assertNoJavaScriptErrors()
|
|
->assertNoConsoleLogs()
|
|
->screenshot(true, spec326CustomerReviewWorkspaceScreenshot('customer-review-workspace--after-reload'));
|
|
});
|
|
|
|
it('Spec326 smokes customer-safe diagnostics disclosure', function (): void {
|
|
[$user, $environmentA] = spec326CustomerReviewWorkspaceFixture();
|
|
spec326AuthenticateCustomerReviewWorkspaceBrowser($this, $user, $environmentA);
|
|
|
|
visit(CustomerReviewWorkspace::getUrl(panel: 'admin'))
|
|
->waitForText('Diagnostics')
|
|
->assertScript('document.querySelector("[data-testid=\"customer-review-diagnostics\"]")?.open === false', true)
|
|
->click('[data-testid="customer-review-diagnostics"] summary')
|
|
->assertScript('document.querySelector("[data-testid=\"customer-review-diagnostics\"]")?.open === true', true)
|
|
->assertSee('Support details stay on authorized diagnostic surfaces')
|
|
->assertDontSee('raw payload should stay hidden')
|
|
->assertDontSee('internal exception should stay hidden')
|
|
->assertDontSee('source fingerprint should stay hidden')
|
|
->assertNoJavaScriptErrors()
|
|
->assertNoConsoleLogs()
|
|
->screenshot(true, spec326CustomerReviewWorkspaceScreenshot('customer-review-workspace--diagnostics'));
|
|
});
|
|
|
|
/**
|
|
* @return array{0: User, 1: ManagedEnvironment, 2: ManagedEnvironment}
|
|
*/
|
|
function spec326CustomerReviewWorkspaceFixture(): array
|
|
{
|
|
$environmentA = ManagedEnvironment::factory()->active()->create([
|
|
'name' => 'Spec326 Browser Environment A',
|
|
'external_id' => 'spec326-browser-environment-a',
|
|
]);
|
|
|
|
[$user, $environmentA] = createUserWithTenant(
|
|
tenant: $environmentA,
|
|
role: 'owner',
|
|
workspaceRole: 'manager',
|
|
);
|
|
|
|
$environmentB = ManagedEnvironment::factory()->active()->create([
|
|
'workspace_id' => (int) $environmentA->workspace_id,
|
|
'name' => 'Spec326 Browser Environment B',
|
|
'external_id' => 'spec326-browser-environment-b',
|
|
]);
|
|
|
|
createUserWithTenant(
|
|
tenant: $environmentB,
|
|
user: $user,
|
|
role: 'owner',
|
|
workspaceRole: 'manager',
|
|
);
|
|
|
|
spec326CreatePublishedReview($environmentA, $user, 'review-packs/spec326-browser-a.zip', now());
|
|
spec326CreatePublishedReview($environmentB, $user, 'review-packs/spec326-browser-b.zip', now()->subHour());
|
|
|
|
return [$user, $environmentA, $environmentB];
|
|
}
|
|
|
|
function spec326AuthenticateCustomerReviewWorkspaceBrowser(
|
|
mixed $test,
|
|
User $user,
|
|
ManagedEnvironment $environment,
|
|
): void {
|
|
$workspaceId = (int) $environment->workspace_id;
|
|
|
|
$test->actingAs($user)->withSession([
|
|
WorkspaceContext::SESSION_KEY => $workspaceId,
|
|
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
|
|
(string) $workspaceId => (int) $environment->getKey(),
|
|
],
|
|
]);
|
|
|
|
session()->put(WorkspaceContext::SESSION_KEY, $workspaceId);
|
|
session()->put(WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY, [
|
|
(string) $workspaceId => (int) $environment->getKey(),
|
|
]);
|
|
}
|
|
|
|
function spec326CreatePublishedReview(
|
|
ManagedEnvironment $environment,
|
|
User $user,
|
|
string $filePath,
|
|
\Illuminate\Support\Carbon $publishedAt,
|
|
): void {
|
|
$snapshot = seedEnvironmentReviewEvidence($environment);
|
|
$review = composeEnvironmentReviewForTest($environment, $user, $snapshot);
|
|
$summary = is_array($review->summary) ? $review->summary : [];
|
|
$summary['debug_payload'] = 'raw payload should stay hidden';
|
|
$summary['stack_trace'] = 'stack trace should stay hidden';
|
|
$summary['provider_secret'] = 'provider secret should stay hidden';
|
|
$summary['debug_metadata'] = 'debug metadata should stay hidden';
|
|
$summary['internal_exception'] = 'internal exception should stay hidden';
|
|
$summary['source_fingerprint'] = 'source fingerprint should stay hidden';
|
|
$summary['control_interpretation']['version_key'] = ComplianceEvidenceMappingV1::VERSION_KEY;
|
|
$summary['control_interpretation']['controls'] = [
|
|
[
|
|
'control_key' => 'customer-handoff-readiness',
|
|
'title' => 'Customer handoff readiness',
|
|
'readiness_bucket' => 'evidence_on_record',
|
|
'readiness_label' => 'Evidence on record',
|
|
'primary_reason' => 'Evidence path is complete.',
|
|
'recommended_next_action' => 'Share the current review pack.',
|
|
],
|
|
];
|
|
|
|
$review->forceFill([
|
|
'status' => EnvironmentReviewStatus::Published->value,
|
|
'summary' => $summary,
|
|
'generated_at' => $publishedAt,
|
|
'published_at' => $publishedAt,
|
|
'published_by_user_id' => (int) $user->getKey(),
|
|
])->save();
|
|
|
|
Storage::disk('exports')->put($filePath, 'PK-test');
|
|
|
|
$pack = ReviewPack::factory()->ready()->create([
|
|
'managed_environment_id' => (int) $environment->getKey(),
|
|
'workspace_id' => (int) $environment->workspace_id,
|
|
'environment_review_id' => (int) $review->getKey(),
|
|
'evidence_snapshot_id' => (int) $snapshot->getKey(),
|
|
'initiated_by_user_id' => (int) $user->getKey(),
|
|
'file_path' => $filePath,
|
|
'file_disk' => 'exports',
|
|
'generated_at' => $publishedAt,
|
|
]);
|
|
|
|
$review->forceFill(['current_export_review_pack_id' => (int) $pack->getKey()])->save();
|
|
}
|
|
|
|
function spec326CustomerReviewWorkspaceScreenshot(string $name): string
|
|
{
|
|
return 'spec326-'.$name;
|
|
}
|