- App.tsx 탭 button 의 aria-pressed → role="tab" + aria-selected (canonical pattern, a11y audit 정정) - store.ts loadExpired action + test 제거 (App.tsx 호출 0건, loadInitial/refreshMeta 가 inline fetch — dead code)
This commit is contained in:
@@ -106,8 +106,10 @@ export function App(): React.ReactElement {
|
||||
).map((t) => (
|
||||
<button
|
||||
key={t.key}
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-selected={view === t.key}
|
||||
onClick={() => setView(t.key)}
|
||||
aria-pressed={view === t.key}
|
||||
style={tabBtnStyle(view === t.key)}
|
||||
>
|
||||
{t.label}({t.count})
|
||||
|
||||
@@ -58,7 +58,6 @@ interface InboxState {
|
||||
restoreNote: (id: string) => Promise<void>;
|
||||
permanentDeleteNote: (id: string) => Promise<void>;
|
||||
emptyTrash: () => Promise<void>;
|
||||
loadExpired: () => Promise<void>;
|
||||
trashExpiredBatch: (ids: string[]) => Promise<void>;
|
||||
snoozeExpired: () => void;
|
||||
recheckOllama: () => Promise<void>;
|
||||
@@ -235,10 +234,6 @@ export const useInbox = create<InboxState>((set, get) => ({
|
||||
set({ trashNotes: [], trashCount: 0 });
|
||||
}
|
||||
},
|
||||
async loadExpired() {
|
||||
const expiredCandidates = await inboxApi.listExpired();
|
||||
set({ expiredCandidates });
|
||||
},
|
||||
async trashExpiredBatch(ids: string[]) {
|
||||
const r = await inboxApi.trashExpiredBatch(ids);
|
||||
if (!r.confirmed) return;
|
||||
|
||||
@@ -130,25 +130,31 @@ describe('App header — 4 tabs', () => {
|
||||
|
||||
it('renders 4 tabs with counts', async () => {
|
||||
render(<App />);
|
||||
expect(await screen.findByRole('button', { name: /Inbox\(5\)/ })).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: /완료\(3\)/ })).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: /보관\(2\)/ })).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: /휴지통\(1\)/ })).toBeInTheDocument();
|
||||
expect(await screen.findByRole('tab', { name: /Inbox\(5\)/ })).toBeInTheDocument();
|
||||
expect(screen.getByRole('tab', { name: /완료\(3\)/ })).toBeInTheDocument();
|
||||
expect(screen.getByRole('tab', { name: /보관\(2\)/ })).toBeInTheDocument();
|
||||
expect(screen.getByRole('tab', { name: /휴지통\(1\)/ })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('clicking 완료 tab sets view=completed', async () => {
|
||||
render(<App />);
|
||||
fireEvent.click(await screen.findByRole('button', { name: /완료/ }));
|
||||
fireEvent.click(await screen.findByRole('tab', { name: /완료/ }));
|
||||
expect(useInbox.getState().view).toBe('completed');
|
||||
});
|
||||
|
||||
it('aria-pressed reflects current view', async () => {
|
||||
it('aria-selected reflects current view', async () => {
|
||||
useInbox.setState({ view: 'archived' });
|
||||
render(<App />);
|
||||
const archivedBtn = await screen.findByRole('button', { name: /보관/ });
|
||||
expect(archivedBtn.getAttribute('aria-pressed')).toBe('true');
|
||||
const inboxBtn = screen.getByRole('button', { name: /Inbox/ });
|
||||
expect(inboxBtn.getAttribute('aria-pressed')).toBe('false');
|
||||
const archivedBtn = await screen.findByRole('tab', { name: /보관/ });
|
||||
expect(archivedBtn.getAttribute('aria-selected')).toBe('true');
|
||||
const inboxBtn = screen.getByRole('tab', { name: /Inbox/ });
|
||||
expect(inboxBtn.getAttribute('aria-selected')).toBe('false');
|
||||
});
|
||||
|
||||
it('inbox tab has aria-selected="true" when active', async () => {
|
||||
render(<App />);
|
||||
const inboxTab = await screen.findByRole('tab', { name: /Inbox/ });
|
||||
expect(inboxTab).toHaveAttribute('aria-selected', 'true');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -175,7 +181,7 @@ describe('App — onboarding wizard', () => {
|
||||
it('does not render OnboardingWizard when onboarding_completed=true', async () => {
|
||||
vi.mocked(inboxApi.getSettings).mockResolvedValue({ onboarding_completed: true });
|
||||
render(<App />);
|
||||
await screen.findByRole('button', { name: /Inbox/ });
|
||||
await screen.findByRole('tab', { name: /Inbox/ });
|
||||
expect(screen.queryByText(/Inkling 사용 시작/)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -52,15 +52,6 @@ describe('useInbox — expired state (v0.2.3 #5)', () => {
|
||||
|
||||
afterEach(() => { vi.restoreAllMocks(); });
|
||||
|
||||
it('loadExpired sets expiredCandidates from inboxApi', async () => {
|
||||
mockApi.listExpired.mockResolvedValueOnce([noteStub('n1')]);
|
||||
const { useInbox } = await import('../../src/renderer/inbox/store.js');
|
||||
await useInbox.getState().loadExpired();
|
||||
const s = useInbox.getState();
|
||||
expect(s.expiredCandidates).toHaveLength(1);
|
||||
expect(s.expiredCandidates[0]!.id).toBe('n1');
|
||||
});
|
||||
|
||||
it('trashExpiredBatch removes ids and increments trashCount when confirmed', async () => {
|
||||
mockApi.trashExpiredBatch.mockResolvedValueOnce({ trashedCount: 2, confirmed: true });
|
||||
const { useInbox } = await import('../../src/renderer/inbox/store.js');
|
||||
|
||||
Reference in New Issue
Block a user