mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-31 04:38:11 +00:00
feat(sidebar): surface partial status for multi-container stacks (#1426)
Bulk stack-status aggregation collapsed a stack to "running" as soon as any container was up, so a multi-container stack with crashed containers showed a green UP pill and the degradation was invisible from the sidebar. Add a crash-aware "partial" state: a stack is partial when at least one container is running and at least one has genuinely failed (exited with a non-zero code, dead, or crash-looping). Cleanly finished one-shot containers (exit 0) and clean restart-policy cycling do not count, so an app with a completed init job stays UP. The exit code is read from the container Status string, so no extra inspect calls are needed. Render partial as an amber PT pill with a hover tooltip showing the running/total count, fold it into the Down filter (needs-attention), and treat it as running for context-menu lifecycle actions so operators keep stop/restart/update. The dashboard stack-health table, cross-node search rows, and the command palette all pick up the new state through the shared status surfaces.
This commit is contained in:
@@ -36,6 +36,26 @@ describe('StackRow', () => {
|
||||
expect(screen.getByText('--')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders PT with the amber class for partial', () => {
|
||||
const { container } = render(<StackRow {...base({ status: 'partial', running: 3, total: 5 })} />);
|
||||
expect(screen.getByText('PT')).toBeInTheDocument();
|
||||
expect(container.querySelector('.text-warning')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('wraps the partial pill in a hover tooltip', () => {
|
||||
// jsdom does not mount the cursor-follow label, so assert the PT trigger is
|
||||
// wrapped in the RowTooltip cursor-container; the visible "3/5 running"
|
||||
// tooltip text is verified in the Playwright drive.
|
||||
const { container } = render(<StackRow {...base({ status: 'partial', running: 3, total: 5 })} />);
|
||||
expect(screen.getByText('PT').closest('[data-slot="cursor-container"]')).not.toBeNull();
|
||||
expect(container.querySelector('[data-slot="cursor-container"]')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('does not wrap a non-partial pill in a tooltip', () => {
|
||||
render(<StackRow {...base({ status: 'running' })} />);
|
||||
expect(screen.getByText('UP').closest('[data-slot="cursor-container"]')).toBeNull();
|
||||
});
|
||||
|
||||
it('renders cyan rail only when active', () => {
|
||||
const { rerender } = render(<StackRow {...base({ isActive: false })} />);
|
||||
expect(screen.getByTestId('stack-row')).not.toHaveClass('bg-accent/[0.07]');
|
||||
|
||||
Reference in New Issue
Block a user