Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,15 @@ describe('DetailsHealth', () => {
},
});

expect(await screen.findByLabelText('db')).toBeInTheDocument();
expect(await screen.findByLabelText('diskSpace')).toBeInTheDocument();
expect(await screen.findByLabelText('ping')).toBeInTheDocument();
expect(
await screen.findByRole('group', { name: 'db' }),
).toBeInTheDocument();
expect(
await screen.findByRole('group', { name: 'diskSpace' }),
).toBeInTheDocument();
expect(
await screen.findByRole('group', { name: 'ping' }),
).toBeInTheDocument();
});

it('should update when instance prop changes', async () => {
Expand Down Expand Up @@ -180,7 +186,10 @@ describe('DetailsHealth', () => {

statusBadges = await screen.findAllByRole('status');
expect(statusBadges[0]).toHaveTextContent('DOWN');
expect(await screen.findByLabelText('db')).toBeInTheDocument();

expect(
await screen.findByRole('group', { name: 'db' }),
).toBeInTheDocument();
});
});

Expand Down Expand Up @@ -250,9 +259,11 @@ describe('DetailsHealth', () => {
});

// custom-group has service component
expect(await screen.findByLabelText('customDetails')).toBeInTheDocument();
expect(
await screen.findByLabelText('evenMoreDiskSpace'),
await screen.findByRole('group', { name: 'customDetails' }),
).toBeInTheDocument();
expect(
await screen.findByRole('group', { name: 'evenMoreDiskSpace' }),
).toBeInTheDocument();
});

Expand All @@ -277,15 +288,19 @@ describe('DetailsHealth', () => {

// First click — fetch & show
await userEvent.click(button);
await screen.findByLabelText('service');
expect(
await screen.findByRole('group', { name: 'service' }),
).toBeInTheDocument();

// Second click — hide
await userEvent.click(button);
expect(screen.queryByLabelText('service')).not.toBeInTheDocument();

// Third click — show again
await userEvent.click(button);
expect(await screen.findByLabelText('service')).toBeInTheDocument();
expect(
await screen.findByRole('group', { name: 'service' }),
).toBeInTheDocument();

// fetchHealthGroup should only be called once (first click)
expect(fetchGroupSpy).toHaveBeenCalledTimes(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,10 +385,8 @@ describe('HealthDetails', () => {
await user.click(toggleButton);

// Details should now be hidden
expect(
screen.queryByText('HSQL Database Engine'),
).not.toBeInTheDocument();
expect(screen.queryByText('isValid()')).not.toBeInTheDocument();
expect(screen.queryByText('HSQL Database Engine')).not.toBeVisible();
expect(screen.queryByText('isValid()')).not.toBeVisible();
});

it('should expand details when toggle button is clicked twice', async () => {
Expand All @@ -412,9 +410,7 @@ describe('HealthDetails', () => {

// First click - expand
await user.click(toggleButton);
expect(
screen.queryByText('HSQL Database Engine'),
).not.toBeInTheDocument();
expect(screen.queryByText('HSQL Database Engine')).not.toBeVisible();

// Second click - collapse
await user.click(toggleButton);
Expand Down Expand Up @@ -465,9 +461,7 @@ describe('HealthDetails', () => {
});

// Details should be visible because we set collapsed to false in localStorage
expect(
await screen.findByText('HSQL Database Engine'),
).toBeInTheDocument();
expect(await screen.findByText('HSQL Database Engine')).toBeVisible();
});

it('should handle child health components correctly', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,44 +16,49 @@

<template>
<dl
class="px-4 py-3 even:bg-white odd:bg-gray-50"
class="px-4 py-3 even:bg-white odd:bg-gray-50 grid grid-cols-3"
role="group"
:aria-label="name"
>
<dt
:id="`health-${id}__${safeNameId}`"
class="flex text-sm font-medium text-gray-500 items-center"
class="w-48 text-sm font-medium text-gray-500 items-center"
>
<div class="w-48">
<div class="break-all">
{{ name }}
</div>
<div class="flex-1">
<sba-status-badge v-if="health.status" :status="health.status" />
</div>
<div v-if="details && details.length > 0" class="w-12 text-right">
<sba-button
class="p-0! border-none"
:title="t('instances.details.health.toggle_details', { name })"
:aria-label="t('instances.details.health.toggle_details', { name })"
:aria-expanded="String(!isCollapsed)"
:aria-controls="`health-details-${id}__${safeNameId}`"
@click="() => toggleCollapsed()"
>
<font-awesome-icon
:icon="faChevronRight"
class="transition-transform"
:class="{ 'rotate-90': !isCollapsed }"
/>
<font-awesome-icon :icon="faCircleInfo" />
</sba-button>
</div>
</dt>
<dd
:id="`health-details-${id}__${safeNameId}`"
class="mt-1 text-sm text-gray-900 sm:mt-0"
class="mt-1 text-sm text-gray-900 sm:mt-0 col-span-2"
:aria-labelledby="`health-${id}__${safeNameId}`"
>
<dl v-if="!isCollapsed" class="grid grid-cols-6 mt-2">
<div class="flex gap-1 items-center">
<div class="flex-1">
<sba-status-badge v-if="health.status" :status="health.status" />
</div>
<div v-if="details && details.length > 0" class="w-12 text-right">
<sba-button
class="p-0! border-none"
:title="t('instances.details.health.toggle_details', { name })"
:aria-label="t('instances.details.health.toggle_details', { name })"
:aria-expanded="String(!isCollapsed)"
:aria-controls="`health-details-${id}__${safeNameId}`"
@click="() => toggleCollapsed()"
>
<font-awesome-icon
:icon="faChevronRight"
class="transition-transform"
:class="{ 'rotate-90': !isCollapsed }"
/>
</sba-button>
</div>
</div>
<dl
v-if="details && details.length > 0"
v-show="!isCollapsed"
class="grid grid-cols-6 mt-2"
>
<template
v-for="(detail, idx) in details"
:key="`${detail.name}_${idx}`"
Expand Down Expand Up @@ -110,10 +115,7 @@
</template>

<script lang="ts" setup>
import {
faChevronRight,
faCircleInfo,
} from '@fortawesome/free-solid-svg-icons';
import { faChevronRight } from '@fortawesome/free-solid-svg-icons';
import prettyBytes from 'pretty-bytes';
import { computed, ref, useId, watch } from 'vue';
import { useI18n } from 'vue-i18n';
Expand Down