toBeGreaterThanOrEqual(2);
expect($heading)
->not->toContain('name="play-circle" class="size-3.5 text-warning"')
->not->toContain('name="play-circle" class="size-3.5 text-orange-500');
}
});
it('uses full-width split action menus on mobile resource headings', function () {
$headings = [
'application' => file_get_contents(resource_path('views/livewire/project/application/heading.blade.php')),
'database' => file_get_contents(resource_path('views/livewire/project/database/heading.blade.php')),
'service' => file_get_contents(resource_path('views/livewire/project/service/heading.blade.php')),
];
foreach ($headings as $resource => $heading) {
expect(mobileActionsAreBeforeDesktopActions($heading, "{$resource}-mobile-actions", "{$resource}-desktop-actions"))->toBeTrue();
expect($heading)
->toContain('
')
->toContain("
")
->not->toContain("{$resource}-mobile-section")
->not->toContain('', $actionsPosition);
if ($endPosition === false) {
return '';
}
return substr($heading, $actionsPosition, $endPosition - $actionsPosition);
}
function mobileActionsAreBeforeDesktopActions(string $heading, string $mobileActionsId, string $desktopActionsId): bool
{
$mobilePosition = strpos($heading, 'id="'.$mobileActionsId.'"');
$hudPosition = strpos($heading, "@teleport('#resource-action-hud-slot')");
$desktopPosition = strpos($heading, 'id="'.$desktopActionsId.'"');
return $mobilePosition !== false
&& $hudPosition !== false
&& $desktopPosition !== false
&& $mobilePosition < $hudPosition
&& $hudPosition < $desktopPosition;
}
it('places database backups immediately after configuration in navigation menus', function () {
$databaseHeading = file_get_contents(resource_path('views/livewire/project/database/heading.blade.php'));
$mobileMenuItems = str($databaseHeading)->between('$databasePageItems = [', '$databaseConfigurationItems = [')->toString();
$desktopMenuItems = str($databaseHeading)->between('class="scrollbar hidden', '')->toString();
foreach ([$mobileMenuItems, $desktopMenuItems] as $menuItems) {
expect(strpos($menuItems, 'Configuration'))
->toBeLessThan(strpos($menuItems, 'Backups'))
->and(strpos($menuItems, 'Backups'))->toBeLessThan(strpos($menuItems, 'Logs'))
->and(strpos($menuItems, 'Logs'))->toBeLessThan(strpos($menuItems, 'Terminal'));
}
});
it('shows configuration sidebars as a mobile link grid and a desktop rail instead of native selects', function () {
expect(file_get_contents(resource_path('views/livewire/project/database/configuration.blade.php')))
->toContain('
')
->toContain('xl:grid-cols-[210px_minmax(0,1fr)]')
->not->toContain('sub-menu-wrapper');
foreach ([
'views/components/database/configuration-sidebar.blade.php',
'views/livewire/project/service/configuration.blade.php',
'views/livewire/project/service/index.blade.php',
'views/components/service-database/sidebar.blade.php',
'views/components/server/sidebar.blade.php',
'views/components/server/sidebar-proxy.blade.php',
'views/components/server/sidebar-sentinel.blade.php',
'views/components/server/sidebar-security.blade.php',
] as $view) {
expect(file_get_contents(resource_path($view)))
->toContain('