| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- import { clearCookies } from '@/test-utils/cookies'
- import { beforeEach, describe, expect, it, vi } from 'vitest'
- import { render, type RenderResult } from 'vitest-browser-react'
- import { userEvent } from 'vitest/browser'
- import { getCookie, setCookie } from '@/lib/cookies'
- import { DirectionProvider } from '@/context/direction-provider'
- import { LayoutProvider } from '@/context/layout-provider'
- import { ThemeProvider } from '@/context/theme-provider'
- import { SidebarProvider } from '@/components/ui/sidebar'
- import { ConfigDrawer } from './config-drawer'
- async function renderConfigDrawer({
- sidebarDefaultOpen = true,
- }: {
- sidebarDefaultOpen?: boolean
- } = {}) {
- return await render(
- <DirectionProvider>
- <ThemeProvider>
- <LayoutProvider>
- <SidebarProvider defaultOpen={sidebarDefaultOpen}>
- <ConfigDrawer />
- </SidebarProvider>
- </LayoutProvider>
- </ThemeProvider>
- </DirectionProvider>
- )
- }
- async function openDrawer(screen: RenderResult) {
- await userEvent.click(
- screen.getByRole('button', { name: /^Open theme settings$/i })
- )
- await vi.waitFor(() =>
- expect(screen.getByText(/^Theme Settings$/i)).toBeInTheDocument()
- )
- }
- describe('ConfigDrawer (integration)', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- clearCookies()
- document.documentElement.classList.remove('light', 'dark')
- document.documentElement.removeAttribute('dir')
- })
- it('opens the drawer and renders the sections', async () => {
- const screen = await renderConfigDrawer()
- await openDrawer(screen)
- expect(screen.getByText(/^Theme$/i)).toBeInTheDocument()
- expect(screen.getByText(/^Layout$/i)).toBeInTheDocument()
- expect(screen.getByText(/^Direction$/i)).toBeInTheDocument()
- expect(
- screen.getByRole('button', {
- name: /reset all settings to default values/i,
- })
- ).toBeInTheDocument()
- })
- describe('theme preference', () => {
- it('applies light theme to <html> and cookie', async () => {
- const screen = await renderConfigDrawer()
- await openDrawer(screen)
- await userEvent.click(
- screen.getByRole('radio', { name: /select light/i })
- )
- await vi.waitFor(() =>
- expect(document.documentElement.classList.contains('light')).toBe(true)
- )
- expect(getCookie('vite-ui-theme')).toBe('light')
- })
- it('applies dark theme to <html> and cookie', async () => {
- const screen = await renderConfigDrawer()
- await openDrawer(screen)
- await userEvent.click(screen.getByRole('radio', { name: /select dark/i }))
- await vi.waitFor(() =>
- expect(document.documentElement.classList.contains('dark')).toBe(true)
- )
- expect(getCookie('vite-ui-theme')).toBe('dark')
- })
- it('applies system theme: stores cookie and applies a resolved light or dark class', async () => {
- // Pre-seed light so mounted theme is not system; re-selecting System alone would not fire setTheme.
- setCookie('vite-ui-theme', 'light')
- const screen = await renderConfigDrawer()
- await openDrawer(screen)
- await userEvent.click(
- screen.getByRole('radio', { name: /select system/i })
- )
- await vi.waitFor(() => expect(getCookie('vite-ui-theme')).toBe('system'))
- await vi.waitFor(() => {
- const root = document.documentElement
- const hasLight = root.classList.contains('light')
- const hasDark = root.classList.contains('dark')
- expect(hasLight !== hasDark).toBe(true)
- })
- })
- })
- describe('sidebar variant', () => {
- it('selecting floating updates layout_variant cookie', async () => {
- const screen = await renderConfigDrawer()
- await openDrawer(screen)
- await userEvent.click(
- screen.getByRole('radio', { name: /select floating/i })
- )
- await vi.waitFor(() =>
- expect(getCookie('layout_variant')).toBe('floating')
- )
- })
- it('selecting sidebar updates layout_variant cookie', async () => {
- const screen = await renderConfigDrawer()
- await openDrawer(screen)
- await userEvent.click(
- screen.getByRole('radio', { name: /^select sidebar$/i })
- )
- await vi.waitFor(() =>
- expect(getCookie('layout_variant')).toBe('sidebar')
- )
- })
- it('selecting inset updates layout_variant cookie after another variant', async () => {
- const screen = await renderConfigDrawer()
- await openDrawer(screen)
- await userEvent.click(
- screen.getByRole('radio', { name: /select floating/i })
- )
- await vi.waitFor(() =>
- expect(getCookie('layout_variant')).toBe('floating')
- )
- await userEvent.click(
- screen.getByRole('radio', { name: /select inset/i })
- )
- await vi.waitFor(() => expect(getCookie('layout_variant')).toBe('inset'))
- })
- })
- it('selecting full layout sets collapsible to offcanvas and closes sidebar', async () => {
- const screen = await renderConfigDrawer({ sidebarDefaultOpen: true })
- await openDrawer(screen)
- await userEvent.click(
- screen.getByRole('radio', { name: /select full layout/i })
- )
- await vi.waitFor(() =>
- expect(getCookie('layout_collapsible')).toBe('offcanvas')
- )
- await vi.waitFor(() => expect(getCookie('sidebar_state')).toBe('false'))
- })
- describe('section reset buttons', () => {
- it('resets theme via section control after choosing dark', async () => {
- const screen = await renderConfigDrawer()
- await openDrawer(screen)
- await userEvent.click(screen.getByRole('radio', { name: /select dark/i }))
- await vi.waitFor(() => expect(getCookie('vite-ui-theme')).toBe('dark'))
- await userEvent.click(
- screen.getByRole('button', {
- name: /reset theme preference to default/i,
- })
- )
- await vi.waitFor(() => expect(getCookie('vite-ui-theme')).toBe('system'))
- })
- it('resets direction via section control after choosing RTL', async () => {
- const screen = await renderConfigDrawer()
- await openDrawer(screen)
- await userEvent.click(
- screen.getByRole('radio', { name: /select right to left/i })
- )
- await vi.waitFor(() =>
- expect(document.documentElement.getAttribute('dir')).toBe('rtl')
- )
- await userEvent.click(
- screen.getByRole('button', {
- name: /reset text direction to default/i,
- })
- )
- await vi.waitFor(() =>
- expect(document.documentElement.getAttribute('dir')).toBe('ltr')
- )
- expect(getCookie('dir')).toBe('ltr')
- })
- it('resets sidebar style via section control after choosing floating', async () => {
- const screen = await renderConfigDrawer()
- await openDrawer(screen)
- await userEvent.click(
- screen.getByRole('radio', { name: /select floating/i })
- )
- await vi.waitFor(() =>
- expect(getCookie('layout_variant')).toBe('floating')
- )
- await userEvent.click(
- screen.getByRole('button', {
- name: /reset sidebar style to default/i,
- })
- )
- await vi.waitFor(() => expect(getCookie('layout_variant')).toBe('inset'))
- })
- it('resets layout via section control after choosing compact', async () => {
- const screen = await renderConfigDrawer({ sidebarDefaultOpen: true })
- await openDrawer(screen)
- await userEvent.click(
- screen.getByRole('radio', { name: /select compact/i })
- )
- await vi.waitFor(() => expect(getCookie('sidebar_state')).toBe('false'))
- await userEvent.click(
- screen.getByRole('button', {
- name: /reset layout options to default/i,
- })
- )
- await vi.waitFor(() => expect(getCookie('sidebar_state')).toBe('true'))
- await vi.waitFor(() =>
- expect(getCookie('layout_collapsible')).toBe('icon')
- )
- })
- })
- it('changes direction and applies it to <html dir>', async () => {
- const screen = await renderConfigDrawer()
- await openDrawer(screen)
- await userEvent.click(
- screen.getByRole('radio', { name: /select right to left/i })
- )
- await vi.waitFor(() =>
- expect(document.documentElement.getAttribute('dir')).toBe('rtl')
- )
- expect(getCookie('dir')).toBe('rtl')
- })
- it('updates layout: selecting non-default closes sidebar and changes layout cookie', async () => {
- const screen = await renderConfigDrawer({ sidebarDefaultOpen: true })
- await openDrawer(screen)
- expect(
- screen.getByRole('radio', { name: /select default/i })
- ).toHaveAttribute('data-state', 'checked')
- await userEvent.click(
- screen.getByRole('radio', { name: /select compact/i })
- )
- await vi.waitFor(() => expect(getCookie('sidebar_state')).toBe('false'))
- await vi.waitFor(() => expect(getCookie('layout_collapsible')).toBe('icon'))
- })
- it('reset restores defaults across sidebar/theme/layout/direction', async () => {
- const screen = await renderConfigDrawer({ sidebarDefaultOpen: true })
- await openDrawer(screen)
- await userEvent.click(screen.getByRole('radio', { name: /select dark/i }))
- await userEvent.click(
- screen.getByRole('radio', { name: /select right to left/i })
- )
- await userEvent.click(
- screen.getByRole('radio', { name: /select floating/i })
- )
- await userEvent.click(
- screen.getByRole('radio', { name: /select full layout/i })
- )
- await vi.waitFor(() => expect(getCookie('vite-ui-theme')).toBe('dark'))
- await vi.waitFor(() => expect(getCookie('dir')).toBe('rtl'))
- await vi.waitFor(() => expect(getCookie('layout_variant')).toBe('floating'))
- await vi.waitFor(() =>
- expect(getCookie('layout_collapsible')).toBe('offcanvas')
- )
- await userEvent.click(
- screen.getByRole('button', {
- name: /reset all settings to default values/i,
- })
- )
- await vi.waitFor(() => expect(getCookie('sidebar_state')).toBe('true'))
- await vi.waitFor(() => expect(getCookie('dir')).toBeUndefined())
- await vi.waitFor(() => expect(getCookie('vite-ui-theme')).toBeUndefined())
- await vi.waitFor(() => expect(getCookie('layout_variant')).toBe('inset'))
- await vi.waitFor(() => expect(getCookie('layout_collapsible')).toBe('icon'))
- await vi.waitFor(() =>
- expect(document.documentElement.getAttribute('dir')).toBe('ltr')
- )
- })
- })
|