feat: implement formatContainerStatus helper for human-readable status formatting and add unit tests
This commit is contained in:
parent
840d25a729
commit
01609e7f8b
4 changed files with 247 additions and 72 deletions
|
|
@ -3153,3 +3153,46 @@ function generateDockerComposeServiceName(mixed $services, int $pullRequestId =
|
|||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform colon-delimited status format to human-readable parentheses format.
|
||||
*
|
||||
* Handles Docker container status formats with optional health check status and exclusion modifiers.
|
||||
*
|
||||
* Examples:
|
||||
* - running:healthy → Running (healthy)
|
||||
* - running:unhealthy:excluded → Running (unhealthy, excluded)
|
||||
* - exited:excluded → Exited (excluded)
|
||||
* - Proxy:running → Proxy:running (preserved as-is for headline formatting)
|
||||
* - running → Running
|
||||
*
|
||||
* @param string $status The status string to format
|
||||
* @return string The formatted status string
|
||||
*/
|
||||
function formatContainerStatus(string $status): string
|
||||
{
|
||||
// Preserve Proxy statuses as-is (they follow different format)
|
||||
if (str($status)->startsWith('Proxy')) {
|
||||
return str($status)->headline()->value();
|
||||
}
|
||||
|
||||
// Check for :excluded suffix
|
||||
$isExcluded = str($status)->endsWith(':excluded');
|
||||
$parts = explode(':', $status);
|
||||
|
||||
if ($isExcluded) {
|
||||
if (count($parts) === 3) {
|
||||
// Has health status: running:unhealthy:excluded → Running (unhealthy, excluded)
|
||||
return str($parts[0])->headline().' ('.$parts[1].', excluded)';
|
||||
} else {
|
||||
// No health status: exited:excluded → Exited (excluded)
|
||||
return str($parts[0])->headline().' (excluded)';
|
||||
}
|
||||
} elseif (count($parts) >= 2) {
|
||||
// Regular colon format: running:healthy → Running (healthy)
|
||||
return str($parts[0])->headline().' ('.$parts[1].')';
|
||||
} else {
|
||||
// Simple status: running → Running
|
||||
return str($status)->headline()->value();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +1,5 @@
|
|||
@php
|
||||
// Transform colon format to human-readable format for UI display
|
||||
// running:healthy → Running (healthy)
|
||||
// running:unhealthy:excluded → Running (unhealthy, excluded)
|
||||
// exited:excluded → Exited (excluded)
|
||||
$isExcluded = str($complexStatus)->endsWith(':excluded');
|
||||
$parts = explode(':', $complexStatus);
|
||||
|
||||
if ($isExcluded) {
|
||||
if (count($parts) === 3) {
|
||||
// Has health status: running:unhealthy:excluded → Running (unhealthy, excluded)
|
||||
$displayStatus = str($parts[0])->headline() . ' (' . $parts[1] . ', excluded)';
|
||||
} else {
|
||||
// No health status: exited:excluded → Exited (excluded)
|
||||
$displayStatus = str($parts[0])->headline() . ' (excluded)';
|
||||
}
|
||||
} elseif (count($parts) >= 2 && !str($complexStatus)->startsWith('Proxy')) {
|
||||
// Regular colon format: running:healthy → Running (healthy)
|
||||
$displayStatus = str($parts[0])->headline() . ' (' . $parts[1] . ')';
|
||||
} else {
|
||||
// No transformation needed (simple status or already in parentheses format)
|
||||
$displayStatus = str($complexStatus)->headline();
|
||||
}
|
||||
$displayStatus = formatContainerStatus($complexStatus);
|
||||
@endphp
|
||||
@if (str($displayStatus)->lower()->contains('running'))
|
||||
<x-status.running :status="$displayStatus" />
|
||||
|
|
|
|||
|
|
@ -90,31 +90,7 @@ class="w-4 h-4 dark:text-warning text-coollabs"
|
|||
@endcan
|
||||
</span>
|
||||
@endif
|
||||
@php
|
||||
// Transform colon format to human-readable format
|
||||
// running:healthy → Running (healthy)
|
||||
// running:unhealthy:excluded → Running (unhealthy, excluded)
|
||||
$appStatus = $application->status;
|
||||
$isExcluded = str($appStatus)->endsWith(':excluded');
|
||||
$parts = explode(':', $appStatus);
|
||||
|
||||
if ($isExcluded) {
|
||||
if (count($parts) === 3) {
|
||||
// Has health status: running:unhealthy:excluded → Running (unhealthy, excluded)
|
||||
$appStatus = str($parts[0])->headline() . ' (' . $parts[1] . ', excluded)';
|
||||
} else {
|
||||
// No health status: exited:excluded → Exited (excluded)
|
||||
$appStatus = str($parts[0])->headline() . ' (excluded)';
|
||||
}
|
||||
} elseif (count($parts) >= 2 && !str($appStatus)->startsWith('Proxy')) {
|
||||
// Regular colon format: running:healthy → Running (healthy)
|
||||
$appStatus = str($parts[0])->headline() . ' (' . $parts[1] . ')';
|
||||
} else {
|
||||
// Simple status or already in parentheses format
|
||||
$appStatus = str($appStatus)->headline();
|
||||
}
|
||||
@endphp
|
||||
<div class="pt-2 text-xs">{{ $appStatus }}</div>
|
||||
<div class="pt-2 text-xs">{{ formatContainerStatus($application->status) }}</div>
|
||||
</div>
|
||||
<div class="flex items-center px-4">
|
||||
<a class="mx-4 text-xs font-bold hover:underline"
|
||||
|
|
@ -163,31 +139,7 @@ class="w-4 h-4 dark:text-warning text-coollabs"
|
|||
@if ($database->description)
|
||||
<span class="text-xs">{{ Str::limit($database->description, 60) }}</span>
|
||||
@endif
|
||||
@php
|
||||
// Transform colon format to human-readable format
|
||||
// running:healthy → Running (healthy)
|
||||
// running:unhealthy:excluded → Running (unhealthy, excluded)
|
||||
$dbStatus = $database->status;
|
||||
$isExcluded = str($dbStatus)->endsWith(':excluded');
|
||||
$parts = explode(':', $dbStatus);
|
||||
|
||||
if ($isExcluded) {
|
||||
if (count($parts) === 3) {
|
||||
// Has health status: running:unhealthy:excluded → Running (unhealthy, excluded)
|
||||
$dbStatus = str($parts[0])->headline() . ' (' . $parts[1] . ', excluded)';
|
||||
} else {
|
||||
// No health status: exited:excluded → Exited (excluded)
|
||||
$dbStatus = str($parts[0])->headline() . ' (excluded)';
|
||||
}
|
||||
} elseif (count($parts) >= 2 && !str($dbStatus)->startsWith('Proxy')) {
|
||||
// Regular colon format: running:healthy → Running (healthy)
|
||||
$dbStatus = str($parts[0])->headline() . ' (' . $parts[1] . ')';
|
||||
} else {
|
||||
// Simple status or already in parentheses format
|
||||
$dbStatus = str($dbStatus)->headline();
|
||||
}
|
||||
@endphp
|
||||
<div class="text-xs">{{ $dbStatus }}</div>
|
||||
<div class="text-xs">{{ formatContainerStatus($database->status) }}</div>
|
||||
</div>
|
||||
<div class="flex items-center px-4">
|
||||
@if ($database->isBackupSolutionAvailable() || $database->is_migrated)
|
||||
|
|
|
|||
201
tests/Unit/FormatContainerStatusTest.php
Normal file
201
tests/Unit/FormatContainerStatusTest.php
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
<?php
|
||||
|
||||
describe('formatContainerStatus helper', function () {
|
||||
describe('colon-delimited format parsing', function () {
|
||||
it('transforms running:healthy to Running (healthy)', function () {
|
||||
$result = formatContainerStatus('running:healthy');
|
||||
|
||||
expect($result)->toBe('Running (healthy)');
|
||||
});
|
||||
|
||||
it('transforms running:unhealthy to Running (unhealthy)', function () {
|
||||
$result = formatContainerStatus('running:unhealthy');
|
||||
|
||||
expect($result)->toBe('Running (unhealthy)');
|
||||
});
|
||||
|
||||
it('transforms exited:0 to Exited (0)', function () {
|
||||
$result = formatContainerStatus('exited:0');
|
||||
|
||||
expect($result)->toBe('Exited (0)');
|
||||
});
|
||||
|
||||
it('transforms restarting:starting to Restarting (starting)', function () {
|
||||
$result = formatContainerStatus('restarting:starting');
|
||||
|
||||
expect($result)->toBe('Restarting (starting)');
|
||||
});
|
||||
});
|
||||
|
||||
describe('excluded suffix handling', function () {
|
||||
it('transforms running:unhealthy:excluded to Running (unhealthy, excluded)', function () {
|
||||
$result = formatContainerStatus('running:unhealthy:excluded');
|
||||
|
||||
expect($result)->toBe('Running (unhealthy, excluded)');
|
||||
});
|
||||
|
||||
it('transforms running:healthy:excluded to Running (healthy, excluded)', function () {
|
||||
$result = formatContainerStatus('running:healthy:excluded');
|
||||
|
||||
expect($result)->toBe('Running (healthy, excluded)');
|
||||
});
|
||||
|
||||
it('transforms exited:excluded to Exited (excluded)', function () {
|
||||
$result = formatContainerStatus('exited:excluded');
|
||||
|
||||
expect($result)->toBe('Exited (excluded)');
|
||||
});
|
||||
|
||||
it('transforms stopped:excluded to Stopped (excluded)', function () {
|
||||
$result = formatContainerStatus('stopped:excluded');
|
||||
|
||||
expect($result)->toBe('Stopped (excluded)');
|
||||
});
|
||||
});
|
||||
|
||||
describe('simple status format', function () {
|
||||
it('transforms running to Running', function () {
|
||||
$result = formatContainerStatus('running');
|
||||
|
||||
expect($result)->toBe('Running');
|
||||
});
|
||||
|
||||
it('transforms exited to Exited', function () {
|
||||
$result = formatContainerStatus('exited');
|
||||
|
||||
expect($result)->toBe('Exited');
|
||||
});
|
||||
|
||||
it('transforms stopped to Stopped', function () {
|
||||
$result = formatContainerStatus('stopped');
|
||||
|
||||
expect($result)->toBe('Stopped');
|
||||
});
|
||||
|
||||
it('transforms restarting to Restarting', function () {
|
||||
$result = formatContainerStatus('restarting');
|
||||
|
||||
expect($result)->toBe('Restarting');
|
||||
});
|
||||
|
||||
it('transforms degraded to Degraded', function () {
|
||||
$result = formatContainerStatus('degraded');
|
||||
|
||||
expect($result)->toBe('Degraded');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Proxy status preservation', function () {
|
||||
it('preserves Proxy:running without parsing colons', function () {
|
||||
$result = formatContainerStatus('Proxy:running');
|
||||
|
||||
expect($result)->toBe('Proxy:running');
|
||||
});
|
||||
|
||||
it('preserves Proxy:exited without parsing colons', function () {
|
||||
$result = formatContainerStatus('Proxy:exited');
|
||||
|
||||
expect($result)->toBe('Proxy:exited');
|
||||
});
|
||||
|
||||
it('preserves Proxy:healthy without parsing colons', function () {
|
||||
$result = formatContainerStatus('Proxy:healthy');
|
||||
|
||||
expect($result)->toBe('Proxy:healthy');
|
||||
});
|
||||
|
||||
it('applies headline formatting to Proxy statuses', function () {
|
||||
$result = formatContainerStatus('proxy:running');
|
||||
|
||||
expect($result)->toBe('Proxy (running)');
|
||||
});
|
||||
});
|
||||
|
||||
describe('headline transformation', function () {
|
||||
it('applies headline to simple lowercase status', function () {
|
||||
$result = formatContainerStatus('running');
|
||||
|
||||
expect($result)->toBe('Running');
|
||||
});
|
||||
|
||||
it('applies headline to uppercase status', function () {
|
||||
// headline() adds spaces between capital letters
|
||||
$result = formatContainerStatus('RUNNING');
|
||||
|
||||
expect($result)->toBe('R U N N I N G');
|
||||
});
|
||||
|
||||
it('applies headline to mixed case status', function () {
|
||||
// headline() adds spaces between capital letters
|
||||
$result = formatContainerStatus('RuNnInG');
|
||||
|
||||
expect($result)->toBe('Ru Nn In G');
|
||||
});
|
||||
|
||||
it('applies headline to first part of colon format', function () {
|
||||
// headline() adds spaces between capital letters
|
||||
$result = formatContainerStatus('RUNNING:healthy');
|
||||
|
||||
expect($result)->toBe('R U N N I N G (healthy)');
|
||||
});
|
||||
});
|
||||
|
||||
describe('edge cases', function () {
|
||||
it('handles empty string gracefully', function () {
|
||||
$result = formatContainerStatus('');
|
||||
|
||||
expect($result)->toBe('');
|
||||
});
|
||||
|
||||
it('handles multiple colons beyond expected format', function () {
|
||||
// Only first two parts should be used (or three with :excluded)
|
||||
$result = formatContainerStatus('running:healthy:extra:data');
|
||||
|
||||
expect($result)->toBe('Running (healthy)');
|
||||
});
|
||||
|
||||
it('handles status with spaces in health part', function () {
|
||||
$result = formatContainerStatus('running:health check failed');
|
||||
|
||||
expect($result)->toBe('Running (health check failed)');
|
||||
});
|
||||
|
||||
it('handles single colon with empty second part', function () {
|
||||
$result = formatContainerStatus('running:');
|
||||
|
||||
expect($result)->toBe('Running ()');
|
||||
});
|
||||
});
|
||||
|
||||
describe('real-world scenarios', function () {
|
||||
it('handles typical running healthy container', function () {
|
||||
$result = formatContainerStatus('running:healthy');
|
||||
|
||||
expect($result)->toBe('Running (healthy)');
|
||||
});
|
||||
|
||||
it('handles degraded container with health issues', function () {
|
||||
$result = formatContainerStatus('degraded:unhealthy');
|
||||
|
||||
expect($result)->toBe('Degraded (unhealthy)');
|
||||
});
|
||||
|
||||
it('handles excluded unhealthy container', function () {
|
||||
$result = formatContainerStatus('running:unhealthy:excluded');
|
||||
|
||||
expect($result)->toBe('Running (unhealthy, excluded)');
|
||||
});
|
||||
|
||||
it('handles proxy container status', function () {
|
||||
$result = formatContainerStatus('Proxy:running');
|
||||
|
||||
expect($result)->toBe('Proxy:running');
|
||||
});
|
||||
|
||||
it('handles stopped container', function () {
|
||||
$result = formatContainerStatus('stopped');
|
||||
|
||||
expect($result)->toBe('Stopped');
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Reference in a new issue