mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 00:12:39 +00:00
fix: name the rail's Mail entry Mail for screen readers instead of its unread count
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import React from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
// The Mail entry shows the Inbox's unread count as a badge. On the collapsed
|
||||
// rail the entry has no visible text, so the badge digits used to become the
|
||||
// link's whole accessible name ("2" instead of "Mail").
|
||||
|
||||
vi.mock('../account-switcher', () => ({ AccountSwitcher: () => null }));
|
||||
vi.mock('@/components/plugins/plugin-slot', () => ({ PluginSlot: () => null }));
|
||||
vi.mock('@/components/keyboard-shortcuts-modal', () => ({ KeyboardShortcutsModal: () => null }));
|
||||
vi.mock('@/components/search/search-box', () => ({ SearchBox: () => null }));
|
||||
vi.mock('@/hooks/use-config', () => ({ useConfig: () => ({ appName: 'Mail' }) }));
|
||||
vi.mock('@/hooks/use-stalwart-admin', () => ({ useStalwartAdmin: () => false }));
|
||||
vi.mock('@/i18n/navigation', () => ({
|
||||
useRouter: () => ({ push: vi.fn(), back: vi.fn(), replace: vi.fn() }),
|
||||
usePathname: () => '/files',
|
||||
Link: ({ children, href, ...rest }: { children: React.ReactNode; href: string }) => <a href={href} {...rest}>{children}</a>,
|
||||
}));
|
||||
|
||||
const { NavigationRail } = await import('../navigation-rail');
|
||||
const { useUpdateStore } = await import('@/stores/update-store');
|
||||
const { useEmailStore } = await import('@/stores/email-store');
|
||||
|
||||
beforeEach(() => {
|
||||
useUpdateStore.setState({ startPolling: vi.fn() } as never);
|
||||
useEmailStore.setState({ mailboxes: [{ id: 'a', role: 'inbox', unreadEmails: 2 }] } as never);
|
||||
});
|
||||
|
||||
describe.each([
|
||||
['collapsed rail', { orientation: 'vertical', collapsed: true }],
|
||||
['expanded rail', { orientation: 'vertical', collapsed: false }],
|
||||
['bottom bar', { orientation: 'horizontal', collapsed: false }],
|
||||
] as const)('%s', (_name, props) => {
|
||||
it('names the Mail entry by its label, not by its unread count', () => {
|
||||
render(<NavigationRail {...props} />);
|
||||
expect(screen.getAllByRole('link', { name: 'mail' }).length).toBeGreaterThan(0);
|
||||
expect(screen.queryByRole('link', { name: '2' })).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -382,7 +382,7 @@ export function NavigationRail({
|
||||
)}>
|
||||
<Icon className="w-5 h-5" />
|
||||
{item.badge != null && item.badge > 0 && (
|
||||
<span className="absolute -top-1.5 -right-2.5 flex items-center justify-center min-w-[16px] h-4 text-[10px] font-bold rounded-full bg-red-500 text-white px-1">
|
||||
<span aria-hidden="true" className="absolute -top-1.5 -right-2.5 flex items-center justify-center min-w-[16px] h-4 text-[10px] font-bold rounded-full bg-red-500 text-white px-1">
|
||||
{item.badge > 99 ? "99+" : item.badge}
|
||||
</span>
|
||||
)}
|
||||
@@ -588,13 +588,14 @@ export function NavigationRail({
|
||||
: "text-muted-foreground hover:bg-muted hover:text-foreground"
|
||||
)}
|
||||
aria-current={isActive ? "page" : undefined}
|
||||
aria-label={t(item.labelKey)}
|
||||
title={collapsed ? t(item.labelKey) : undefined}
|
||||
style={collapsed ? undefined : { paddingBlock: 'var(--density-sidebar-py)' }}
|
||||
>
|
||||
<Icon className={cn("w-[18px] h-[18px] flex-shrink-0", isActive && "text-primary")} />
|
||||
{!collapsed && <span className="truncate">{t(item.labelKey)}</span>}
|
||||
{item.badge != null && item.badge > 0 && (
|
||||
<span className={cn(
|
||||
<span aria-hidden="true" className={cn(
|
||||
"absolute flex items-center justify-center min-w-[16px] h-4 text-[10px] font-bold rounded-full bg-red-500 text-white px-1",
|
||||
collapsed ? "-top-0.5 -right-0.5" : "right-1.5"
|
||||
)}>
|
||||
|
||||
Reference in New Issue
Block a user