Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 1m12s
Added BaselineSubjectResolution page and supporting logic to visualize missing identities, ambiguous matches, and skipped coverages per Spec 384.
165 lines
6.1 KiB
PHP
165 lines
6.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Models\ManagedEnvironment;
|
|
use App\Models\User;
|
|
use App\Support\Baselines\SubjectClass;
|
|
use App\Support\ManagedEnvironmentLinks;
|
|
use App\Support\OperationRunOutcome;
|
|
use App\Support\OperationRunStatus;
|
|
use App\Support\Resources\ResourceIdentity;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Tests\Feature\Baselines\Support\BaselineSubjectResolutionFixtures;
|
|
|
|
pest()->browser()->timeout(45_000);
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
it('Spec384 smokes baseline subject resolution reachability and action modal', function (): void {
|
|
[$user, $tenant] = createUserWithTenant(role: 'owner', workspaceRole: 'manager');
|
|
$tenant->forceFill(['name' => 'Spec384 Subject Resolution Environment'])->save();
|
|
|
|
$run = spec384BrowserSubjectResolutionRun($tenant);
|
|
$resolutionPath = spec384BrowserPath(ManagedEnvironmentLinks::baselineSubjectResolutionUrl($tenant, [
|
|
'operation_run_id' => (int) $run->getKey(),
|
|
]));
|
|
|
|
$page = visit(spec384BrowserLoginUrl($user, $tenant, $resolutionPath))
|
|
->resize(1440, 1100)
|
|
->waitForText('Baseline subject resolution')
|
|
->assertSee('Spec384 Subject Resolution Environment')
|
|
->assertSee('1 decision required')
|
|
->assertSee('Decision worklist')
|
|
->assertSee('Duplicate policy')
|
|
->assertSee('Unresolved Duplicate Candidates')
|
|
->assertSee('Binding required')
|
|
->assertSee('TenantPilot-only')
|
|
->assertSee('Open operation')
|
|
->assertSee('Open baseline compare')
|
|
->assertSee('Bind subject')
|
|
->assertNoJavaScriptErrors()
|
|
->assertNoConsoleLogs()
|
|
->screenshot(true, spec384BrowserScreenshotName('01-baseline-subject-resolution'));
|
|
|
|
spec384BrowserCopyScreenshot('01-baseline-subject-resolution');
|
|
|
|
$page
|
|
->click('Bind subject')
|
|
->waitForText('Record a TenantPilot-only subject binding')
|
|
->assertSee('Provider resource')
|
|
->assertSee('Operator note')
|
|
->assertSee('This does not mutate the provider tenant')
|
|
->assertNoJavaScriptErrors()
|
|
->assertNoConsoleLogs()
|
|
->screenshot(true, spec384BrowserScreenshotName('02-baseline-subject-resolution-bind-modal'));
|
|
|
|
spec384BrowserCopyScreenshot('02-baseline-subject-resolution-bind-modal');
|
|
|
|
$page
|
|
->resize(430, 900)
|
|
->assertScript('document.documentElement.scrollWidth <= window.innerWidth', true)
|
|
->assertNoJavaScriptErrors()
|
|
->screenshot(true, spec384BrowserScreenshotName('03-baseline-subject-resolution-mobile'));
|
|
|
|
spec384BrowserCopyScreenshot('03-baseline-subject-resolution-mobile');
|
|
});
|
|
|
|
function spec384BrowserSubjectResolutionRun(ManagedEnvironment $tenant)
|
|
{
|
|
[$profile, $snapshot] = seedActiveBaselineForTenant($tenant);
|
|
$leftIdentity = ResourceIdentity::providerResource('fake-provider', 'policy', 'candidate-left');
|
|
$rightIdentity = ResourceIdentity::providerResource('fake-provider', 'policy', 'candidate-right');
|
|
$leftDescriptor = BaselineSubjectResolutionFixtures::providerDescriptor($leftIdentity, 'Duplicate policy');
|
|
$rightDescriptor = BaselineSubjectResolutionFixtures::providerDescriptor($rightIdentity, 'Duplicate policy');
|
|
|
|
BaselineSubjectResolutionFixtures::inventoryCandidate(
|
|
$tenant,
|
|
$leftIdentity,
|
|
'Duplicate policy',
|
|
);
|
|
BaselineSubjectResolutionFixtures::inventoryCandidate(
|
|
$tenant,
|
|
$rightIdentity,
|
|
'Duplicate policy',
|
|
);
|
|
|
|
return seedBaselineCompareRun(
|
|
tenant: $tenant,
|
|
profile: $profile,
|
|
snapshot: $snapshot,
|
|
compareContext: [
|
|
'result_semantics' => [
|
|
'version' => 1,
|
|
'subject_outcomes' => [
|
|
BaselineSubjectResolutionFixtures::semanticOutcome([
|
|
'reason' => 'unresolved_duplicate_candidates',
|
|
'actionability' => 'binding_required',
|
|
'readiness_impact' => 'customer_blocker',
|
|
'subject' => [
|
|
'subject_domain' => 'baseline',
|
|
'subject_class' => SubjectClass::PolicyBacked->value,
|
|
'subject_type_key' => 'deviceConfiguration',
|
|
'subject_key' => 'legacy-display-key',
|
|
'display_label' => 'Duplicate policy',
|
|
'candidate_descriptors' => [
|
|
$leftDescriptor->toArray(),
|
|
$rightDescriptor->toArray(),
|
|
],
|
|
],
|
|
]),
|
|
],
|
|
],
|
|
],
|
|
status: OperationRunStatus::Completed->value,
|
|
outcome: OperationRunOutcome::PartiallySucceeded->value,
|
|
);
|
|
}
|
|
|
|
function spec384BrowserLoginUrl(User $user, ManagedEnvironment $tenant, string $redirect): string
|
|
{
|
|
return route('admin.local.smoke-login', [
|
|
'email' => $user->email,
|
|
'tenant' => $tenant->external_id,
|
|
'workspace' => $tenant->workspace->slug,
|
|
'redirect' => $redirect,
|
|
]);
|
|
}
|
|
|
|
function spec384BrowserPath(string $url): string
|
|
{
|
|
$path = parse_url($url, PHP_URL_PATH) ?: '/admin';
|
|
$query = parse_url($url, PHP_URL_QUERY);
|
|
|
|
return is_string($query) && $query !== '' ? $path.'?'.$query : $path;
|
|
}
|
|
|
|
function spec384BrowserScreenshotName(string $name): string
|
|
{
|
|
return 'spec384-'.$name;
|
|
}
|
|
|
|
function spec384BrowserCopyScreenshot(string $name): void
|
|
{
|
|
$filename = spec384BrowserScreenshotName($name).'.png';
|
|
$source = base_path('tests/Browser/Screenshots/'.$filename);
|
|
$targetDirectory = repo_path('specs/384-baseline-subject-resolution-ui/artifacts/screenshots');
|
|
|
|
if (! is_dir($targetDirectory)) {
|
|
@mkdir($targetDirectory, 0755, true);
|
|
}
|
|
|
|
if (! is_file($source)) {
|
|
$source = \Pest\Browser\Support\Screenshot::path($filename);
|
|
}
|
|
|
|
for ($attempt = 0; $attempt < 10 && ! is_file($source); $attempt++) {
|
|
usleep(100_000);
|
|
clearstatcache(true, $source);
|
|
}
|
|
|
|
if (is_file($source) && is_dir($targetDirectory) && is_writable($targetDirectory)) {
|
|
@copy($source, $targetDirectory.DIRECTORY_SEPARATOR.$filename);
|
|
}
|
|
}
|