split-routing.test.tsx4.8 KBView on GitHub import React from 'react';
import { render } from '@testing-library/react';
import { MemoryRouter } from 'react-router';
import { SplitInboxTabs } from '@/modules/threads/components/SplitInboxTabs';
jest.mock('@tanstack/react-query', () => ({
useMutation: () => ({ mutateAsync: jest.fn() }),
useQueryClient: () => ({ invalidateQueries: jest.fn() }),
}));
const slugify = (name: string) =>
name.toLowerCase().trim().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
const getInboxSlug = (inbox: { id: string; name: string }) => {
if (inbox.id === 'default') return 'inbox';
if (inbox.id === 'important') return 'important';
if (inbox.id === 'other') return 'other';
return slugify(inbox.name);
};
const getRowInboxOrder = (inboxes: Array<{ id: string }>) => {
const important = inboxes.find((i) => i.id === 'important');
const other = inboxes.find((i) => i.id === 'other');
const middle = inboxes.filter((i) => i.id !== 'important' && i.id !== 'other');
if (important && other) return [important, ...middle, other];
if (important) return [important, ...middle];
if (other) return [...middle, other];
return middle;
};
const mockInboxesByLayout: Record<string, Array<{ id: string; name: string; position: number; system?: boolean; rule: { kind: 'all' } }>> = {
important_other: [
{ id: 'default', name: 'Inbox', position: 0, system: true, rule: { kind: 'all' } },
{ id: 'important', name: 'Important', position: 1, system: true, rule: { kind: 'all' } },
],
stacked: [
{ id: 'important', name: 'Important', position: 0, system: true, rule: { kind: 'all' } },
{ id: 'other', name: 'Other', position: 1, system: true, rule: { kind: 'all' } },
],
};
let mockCurrentLayout: 'important_other' | 'stacked' = 'important_other';
jest.mock('@/modules/threads/hooks/use-inboxes', () => ({
getInboxSlug,
findInboxBySlug: (
inboxes: Array<{ id: string; name: string }>,
slug: string,
) => inboxes.find((i) => getInboxSlug(i) === slug),
getRowInboxOrder,
useInboxes: () => ({
inboxes: mockInboxesByLayout[mockCurrentLayout],
activeInbox: mockInboxesByLayout[mockCurrentLayout][0],
activeInboxId: mockInboxesByLayout[mockCurrentLayout][0].id,
inboxLayout: mockCurrentLayout,
setActiveInboxId: jest.fn(),
setInboxLayout: jest.fn(),
addInbox: jest.fn(),
updateInbox: jest.fn(),
renameInbox: jest.fn(),
removeInbox: jest.fn(),
reorderInboxes: jest.fn(),
isLoading: false,
inboxesLoading: false,
}),
}));
jest.mock('@/modules/labels/hooks/use-labels-search', () => ({
__esModule: true,
default: () => ({ setLabels: jest.fn() }),
}));
jest.mock('@/hooks/use-inbox-counts', () => ({
useInboxCounts: () => ({
byId: {
default: { count: 0, isExact: true },
important: { count: 0, isExact: true },
other: { count: 0, isExact: true },
},
done: { count: 0, isExact: true },
}),
}));
jest.mock('@/modules/aop/hooks/use-aops', () => ({
useAOPs: () => ({ data: { aops: [] } }),
}));
jest.mock('@/modules/labels/hooks/use-labels', () => ({
useLabels: () => ({ allUserLabels: [], systemLabels: [] }),
}));
jest.mock('@/providers/query-provider', () => ({
useTRPC: () => ({
labels: {
list: {
queryKey: () => ['labels.list'],
},
create: {
mutationOptions: () => ({}),
},
delete: {
mutationOptions: () => ({}),
},
},
mail: {
createAiLabel: {
mutationOptions: () => ({}),
},
backfillAiLabels: {
mutationOptions: () => ({}),
},
deleteAiLabel: {
mutationOptions: () => ({}),
},
},
}),
}));
describe('split routing tabs', () => {
beforeEach(() => {
mockCurrentLayout = 'important_other';
});
it('renders split tabs on inbox route', () => {
const view = render(
<MemoryRouter initialEntries={['/mail/inbox']}>
<SplitInboxTabs />
</MemoryRouter>,
);
expect(view.getByText('Inbox')).toBeInTheDocument();
expect(view.getByText('Important')).toBeInTheDocument();
});
it('keeps split tabs and folder label visible on system-folder routes like done', () => {
const view = render(
<MemoryRouter initialEntries={['/mail/done']}>
<SplitInboxTabs />
</MemoryRouter>,
);
expect(view.getByText('Inbox')).toBeInTheDocument();
expect(view.getByText('Important')).toBeInTheDocument();
expect(view.getByText(/^Done$/)).toBeInTheDocument();
});
it('renders only a single Inbox tab in stacked layout', () => {
mockCurrentLayout = 'stacked';
const view = render(
<MemoryRouter initialEntries={['/mail/inbox']}>
<SplitInboxTabs />
</MemoryRouter>,
);
expect(view.getByText('Inbox')).toBeInTheDocument();
expect(view.queryByText('Important')).not.toBeInTheDocument();
expect(view.queryByText('Other')).not.toBeInTheDocument();
});
});