Przeglądaj źródła

refactor(test): add clearCookies helper and refactor cookie tests

Extract clearCookies(filter?) to `src/test-utils/cookies` using removeCookie
from lib. Replace duplicated clearing and getCookieValue in auth-store,
config-drawer, and cookies tests; assert missing cookies with toBeUndefined.
satnaing 2 miesięcy temu
rodzic
commit
c212188bf7

+ 33 - 72
src/components/config-drawer.test.tsx

@@ -1,21 +1,14 @@
+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 } 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'
 
-function getCookieValue(name: string) {
-  const match = document.cookie.match(
-    new RegExp(
-      `(?:^|; )${name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}=([^;]*)`
-    )
-  )
-  return match ? decodeURIComponent(match[1]) : null
-}
-
 async function renderConfigDrawer({
   sidebarDefaultOpen = true,
 }: {
@@ -47,11 +40,7 @@ describe('ConfigDrawer (integration)', () => {
   beforeEach(() => {
     vi.clearAllMocks()
 
-    for (const cookie of document.cookie.split(';')) {
-      const name = cookie.split('=')[0]?.trim()
-      if (!name) continue
-      document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`
-    }
+    clearCookies()
 
     document.documentElement.classList.remove('light', 'dark')
     document.documentElement.removeAttribute('dir')
@@ -82,7 +71,7 @@ describe('ConfigDrawer (integration)', () => {
       await vi.waitFor(() =>
         expect(document.documentElement.classList.contains('light')).toBe(true)
       )
-      expect(getCookieValue('vite-ui-theme')).toBe('light')
+      expect(getCookie('vite-ui-theme')).toBe('light')
     })
 
     it('applies dark theme to <html> and cookie', async () => {
@@ -92,7 +81,7 @@ describe('ConfigDrawer (integration)', () => {
       await vi.waitFor(() =>
         expect(document.documentElement.classList.contains('dark')).toBe(true)
       )
-      expect(getCookieValue('vite-ui-theme')).toBe('dark')
+      expect(getCookie('vite-ui-theme')).toBe('dark')
     })
 
     it('applies system theme: stores cookie and applies a resolved light or dark class', async () => {
@@ -102,15 +91,11 @@ describe('ConfigDrawer (integration)', () => {
       await userEvent.click(
         screen.getByRole('radio', { name: /select light/i })
       )
-      await vi.waitFor(() =>
-        expect(getCookieValue('vite-ui-theme')).toBe('light')
-      )
+      await vi.waitFor(() => expect(getCookie('vite-ui-theme')).toBe('light'))
       await userEvent.click(
         screen.getByRole('radio', { name: /select system/i })
       )
-      await vi.waitFor(() =>
-        expect(getCookieValue('vite-ui-theme')).toBe('system')
-      )
+      await vi.waitFor(() => expect(getCookie('vite-ui-theme')).toBe('system'))
       await vi.waitFor(() => {
         const root = document.documentElement
         const hasLight = root.classList.contains('light')
@@ -129,7 +114,7 @@ describe('ConfigDrawer (integration)', () => {
         screen.getByRole('radio', { name: /select floating/i })
       )
       await vi.waitFor(() =>
-        expect(getCookieValue('layout_variant')).toBe('floating')
+        expect(getCookie('layout_variant')).toBe('floating')
       )
     })
 
@@ -141,7 +126,7 @@ describe('ConfigDrawer (integration)', () => {
         screen.getByRole('radio', { name: /^select sidebar$/i })
       )
       await vi.waitFor(() =>
-        expect(getCookieValue('layout_variant')).toBe('sidebar')
+        expect(getCookie('layout_variant')).toBe('sidebar')
       )
     })
 
@@ -153,15 +138,13 @@ describe('ConfigDrawer (integration)', () => {
         screen.getByRole('radio', { name: /select floating/i })
       )
       await vi.waitFor(() =>
-        expect(getCookieValue('layout_variant')).toBe('floating')
+        expect(getCookie('layout_variant')).toBe('floating')
       )
 
       await userEvent.click(
         screen.getByRole('radio', { name: /select inset/i })
       )
-      await vi.waitFor(() =>
-        expect(getCookieValue('layout_variant')).toBe('inset')
-      )
+      await vi.waitFor(() => expect(getCookie('layout_variant')).toBe('inset'))
     })
   })
 
@@ -173,11 +156,9 @@ describe('ConfigDrawer (integration)', () => {
       screen.getByRole('radio', { name: /select full layout/i })
     )
     await vi.waitFor(() =>
-      expect(getCookieValue('layout_collapsible')).toBe('offcanvas')
-    )
-    await vi.waitFor(() =>
-      expect(getCookieValue('sidebar_state')).toBe('false')
+      expect(getCookie('layout_collapsible')).toBe('offcanvas')
     )
+    await vi.waitFor(() => expect(getCookie('sidebar_state')).toBe('false'))
   })
 
   describe('section reset buttons', () => {
@@ -186,18 +167,14 @@ describe('ConfigDrawer (integration)', () => {
       await openDrawer(screen)
 
       await userEvent.click(screen.getByRole('radio', { name: /select dark/i }))
-      await vi.waitFor(() =>
-        expect(getCookieValue('vite-ui-theme')).toBe('dark')
-      )
+      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(getCookieValue('vite-ui-theme')).toBe('system')
-      )
+      await vi.waitFor(() => expect(getCookie('vite-ui-theme')).toBe('system'))
     })
 
     it('resets direction via section control after choosing RTL', async () => {
@@ -219,7 +196,7 @@ describe('ConfigDrawer (integration)', () => {
       await vi.waitFor(() =>
         expect(document.documentElement.getAttribute('dir')).toBe('ltr')
       )
-      expect(getCookieValue('dir')).toBe('ltr')
+      expect(getCookie('dir')).toBe('ltr')
     })
 
     it('resets sidebar style via section control after choosing floating', async () => {
@@ -230,7 +207,7 @@ describe('ConfigDrawer (integration)', () => {
         screen.getByRole('radio', { name: /select floating/i })
       )
       await vi.waitFor(() =>
-        expect(getCookieValue('layout_variant')).toBe('floating')
+        expect(getCookie('layout_variant')).toBe('floating')
       )
 
       await userEvent.click(
@@ -238,9 +215,7 @@ describe('ConfigDrawer (integration)', () => {
           name: /reset sidebar style to default/i,
         })
       )
-      await vi.waitFor(() =>
-        expect(getCookieValue('layout_variant')).toBe('inset')
-      )
+      await vi.waitFor(() => expect(getCookie('layout_variant')).toBe('inset'))
     })
 
     it('resets layout via section control after choosing compact', async () => {
@@ -250,20 +225,16 @@ describe('ConfigDrawer (integration)', () => {
       await userEvent.click(
         screen.getByRole('radio', { name: /select compact/i })
       )
-      await vi.waitFor(() =>
-        expect(getCookieValue('sidebar_state')).toBe('false')
-      )
+      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(getCookieValue('sidebar_state')).toBe('true')
-      )
-      await vi.waitFor(() =>
-        expect(getCookieValue('layout_collapsible')).toBe('icon')
+        expect(getCookie('layout_collapsible')).toBe('icon')
       )
     })
   })
@@ -279,7 +250,7 @@ describe('ConfigDrawer (integration)', () => {
     await vi.waitFor(() =>
       expect(document.documentElement.getAttribute('dir')).toBe('rtl')
     )
-    expect(getCookieValue('dir')).toBe('rtl')
+    expect(getCookie('dir')).toBe('rtl')
   })
 
   it('updates layout: selecting non-default closes sidebar and changes layout cookie', async () => {
@@ -295,12 +266,8 @@ describe('ConfigDrawer (integration)', () => {
       screen.getByRole('radio', { name: /select compact/i })
     )
 
-    await vi.waitFor(() =>
-      expect(getCookieValue('sidebar_state')).toBe('false')
-    )
-    await vi.waitFor(() =>
-      expect(getCookieValue('layout_collapsible')).toBe('icon')
-    )
+    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 () => {
@@ -319,13 +286,11 @@ describe('ConfigDrawer (integration)', () => {
       screen.getByRole('radio', { name: /select full layout/i })
     )
 
-    await vi.waitFor(() => expect(getCookieValue('vite-ui-theme')).toBe('dark'))
-    await vi.waitFor(() => expect(getCookieValue('dir')).toBe('rtl'))
-    await vi.waitFor(() =>
-      expect(getCookieValue('layout_variant')).toBe('floating')
-    )
+    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(getCookieValue('layout_collapsible')).toBe('offcanvas')
+      expect(getCookie('layout_collapsible')).toBe('offcanvas')
     )
 
     await userEvent.click(
@@ -334,15 +299,11 @@ describe('ConfigDrawer (integration)', () => {
       })
     )
 
-    await vi.waitFor(() => expect(getCookieValue('sidebar_state')).toBe('true'))
-    await vi.waitFor(() => expect(getCookieValue('dir')).toBe(null))
-    await vi.waitFor(() => expect(getCookieValue('vite-ui-theme')).toBe(null))
-    await vi.waitFor(() =>
-      expect(getCookieValue('layout_variant')).toBe('inset')
-    )
-    await vi.waitFor(() =>
-      expect(getCookieValue('layout_collapsible')).toBe('icon')
-    )
+    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')
     )

+ 6 - 7
src/lib/cookies.test.ts

@@ -1,16 +1,15 @@
+import { clearCookies } from '@/test-utils/cookies'
 import { beforeEach, describe, expect, it } from 'vitest'
 import { getCookie, removeCookie, setCookie } from './cookies'
 
+const COOKIE_PREFIX = 'test_cookie_'
+
 describe('cookies', () => {
-  const uniqueName = () => `test_cookie_${Math.random().toString(36).slice(2)}`
+  const uniqueName = () =>
+    `${COOKIE_PREFIX}${Math.random().toString(36).slice(2)}`
 
   beforeEach(() => {
-    for (const part of document.cookie.split(';')) {
-      const name = part.split('=')[0]?.trim()
-      if (name?.startsWith('test_cookie_')) {
-        removeCookie(name)
-      }
-    }
+    clearCookies(COOKIE_PREFIX)
   })
 
   it('stores a value that can be read back', () => {

+ 2 - 9
src/stores/auth-store.test.ts

@@ -1,13 +1,6 @@
+import { clearCookies } from '@/test-utils/cookies'
 import { beforeEach, describe, expect, it, vi } from 'vitest'
 
-function clearAllCookies() {
-  for (const part of document.cookie.split(';')) {
-    const name = part.split('=')[0]?.trim()
-    if (!name) continue
-    document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`
-  }
-}
-
 async function importAuthStore() {
   const { useAuthStore } = await import('./auth-store')
   return useAuthStore
@@ -22,7 +15,7 @@ const sampleUser = {
 
 describe('useAuthStore', () => {
   beforeEach(() => {
-    clearAllCookies()
+    clearCookies()
     vi.resetModules()
   })
 

+ 28 - 0
src/test-utils/cookies.ts

@@ -0,0 +1,28 @@
+import { removeCookie } from '@/lib/cookies'
+
+/**
+ * Remove cookies visible on `document.cookie` for test isolation.
+ *
+ * - No `filter`: remove every cookie.
+ * - `string`: remove only names that **start with** that string (prefix).
+ * - `RegExp`: remove only names where `filter.test(name)` is true.
+ */
+export function clearCookies(filter?: string | RegExp): void {
+  if (typeof document === 'undefined') return
+
+  for (const part of document.cookie.split(';')) {
+    const name = part.split('=')[0]?.trim()
+    if (!name) continue
+
+    const shouldRemove =
+      filter === undefined
+        ? true
+        : typeof filter === 'string'
+          ? name.startsWith(filter)
+          : filter.test(name)
+
+    if (shouldRemove) {
+      removeCookie(name)
+    }
+  }
+}