Files
textbee/web/components/shared/route-tabs.test.tsx
isra el 18e7d1b3d8 perf(web): make dashboard navigation fast and cut session fetches
- prefetch route-tab links so tab clicks reuse a cached payload instead
  of paying an uncached server round trip each time
- add loading.tsx boundaries (dashboard root and each section) so clicks
  paint within a frame; section-level files keep the header and tabs
  mounted while only the content area swaps
- link the sidebar Account item and the checkout page straight to
  /dashboard/account/billing. The /dashboard/account redirect stub stays
  for old links, but no internal link pays the extra hop anymore. The
  stub also dropped query params, which silently ate the plan-change
  success toast.
- set QueryClient defaults (staleTime 60s, no focus refetch, retry 1);
  mutations already invalidate their keys, so the user's own changes
  stay instant. Device messages and webhook deliveries get a 15s
  staleTime since they change from outside the tab.
- replace the axios getCachedSession TTL cache with a token seeded from
  the server session in Providers and kept in sync by a session bridge.
  Requests attach the token synchronously; /api/auth/session is only a
  deduped fallback, instead of a refetch every 2 minutes with a
  thundering herd on expiry.
- swap the billing card's 16px loading spinner for a card-shaped
  skeleton so the tab no longer looks blank while loading

Tests: interceptor seeding/dedupe/signed-out behavior, provider
defaults and token seeding, nav active-state matching, tab prefetch,
billing loading state, plus e2e coverage for direct-to-billing
navigation and an at-most-one-session-call budget guard.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 13:49:14 +03:00

46 lines
1.5 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest'
import { render, screen } from '@testing-library/react'
import RouteTabs from './route-tabs'
// Capture Link props: prefetch is router behavior, invisible in the DOM.
vi.mock('next/link', () => ({
default: ({ children, href, prefetch, ...rest }: any) => (
<a href={href} data-prefetch={String(prefetch)} {...rest}>
{children}
</a>
),
}))
vi.mock('next/navigation', () => ({
usePathname: () => '/dashboard/messaging',
}))
const tabs = [
{ href: '/dashboard/messaging', label: 'Send', exact: true },
{ href: '/dashboard/messaging/bulk', label: 'Bulk Send' },
{ href: '/dashboard/messaging/history', label: 'History' },
]
describe('RouteTabs', () => {
it('opts every tab link into full prefetch', () => {
render(<RouteTabs tabs={tabs} />)
// These routes are dynamic (session cookie in the app layout); without an
// explicit prefetch every tab click pays a full server round trip.
for (const link of screen.getAllByRole('link')) {
expect(link).toHaveAttribute('data-prefetch', 'true')
}
expect(screen.getAllByRole('link')).toHaveLength(tabs.length)
})
it('marks only the active tab with aria-current', () => {
render(<RouteTabs tabs={tabs} />)
expect(screen.getByRole('link', { name: 'Send' })).toHaveAttribute(
'aria-current',
'page'
)
expect(
screen.getByRole('link', { name: 'Bulk Send' })
).not.toHaveAttribute('aria-current')
})
})