Usamos cookies para mejorar tu experiencia en el sitio
CodeWorlds

Testing Composables & Stores

Testowanie logiki biznesowej - composables i Pinia stores.

Testing Composables

1// composables/useCounter.js
2import { ref, computed } from 'vue'
3
4export function useCounter(initialValue = 0) {
5  const count = ref(initialValue)
6  const doubled = computed(() => count.value * 2)
7
8  function increment() {
9    count.value++
10  }
11
12  function decrement() {
13    count.value--
14  }
15
16  return { count, doubled, increment, decrement }
17}
18
19// composables/useCounter.spec.js
20import { describe, it, expect } from 'vitest'
21import { useCounter } from './useCounter'
22
23describe('useCounter', () => {
24  it('initializes with default value', () => {
25    const { count } = useCounter()
26    expect(count.value).toBe(0)
27  })
28
29  it('initializes with custom value', () => {
30    const { count } = useCounter(10)
31    expect(count.value).toBe(10)
32  })
33
34  it('increments count', () => {
35    const { count, increment } = useCounter()
36
37    increment()
38
39    expect(count.value).toBe(1)
40  })
41
42  it('computes doubled value', () => {
43    const { count, doubled, increment } = useCounter()
44
45    expect(doubled.value).toBe(0)
46
47    increment()
48
49    expect(doubled.value).toBe(2)
50  })
51})

Testing Async Composables

1// composables/useFetch.js
2import { ref } from 'vue'
3
4export function useFetch(url) {
5  const data = ref(null)
6  const loading = ref(false)
7  const error = ref(null)
8
9  async function fetchData() {
10    loading.value = true
11    error.value = null
12
13    try {
14      const response = await fetch(url)
15      data.value = await response.json()
16    } catch (e) {
17      error.value = e
18    } finally {
19      loading.value = false
20    }
21  }
22
23  return { data, loading, error, fetchData }
24}
25
26// composables/useFetch.spec.js
27import { describe, it, expect, vi, beforeEach } from 'vitest'
28import { useFetch } from './useFetch'
29
30describe('useFetch', () => {
31  beforeEach(() => {
32    global.fetch = vi.fn()
33  })
34
35  it('fetches data successfully', async () => {
36    const mockData = { id: 1, title: 'Test' }
37
38    global.fetch.mockResolvedValue({
39      json: async () => mockData
40    })
41
42    const { data, loading, error, fetchData } = useFetch('/api/test')
43
44    expect(loading.value).toBe(false)
45    expect(data.value).toBe(null)
46
47    await fetchData()
48
49    expect(loading.value).toBe(false)
50    expect(data.value).toEqual(mockData)
51    expect(error.value).toBe(null)
52  })
53
54  it('handles errors', async () => {
55    global.fetch.mockRejectedValue(new Error('Network error'))
56
57    const { data, error, fetchData } = useFetch('/api/test')
58
59    await fetchData()
60
61    expect(data.value).toBe(null)
62    expect(error.value).toBeInstanceOf(Error)
63  })
64})

Testing Pinia Stores

1// stores/gallery.spec.js
2import { describe, it, expect, beforeEach, vi } from 'vitest'
3import { setActivePinia, createPinia } from 'pinia'
4import { useGalleryStore } from './gallery'
5
6describe('Gallery Store', () => {
7  beforeEach(() => {
8    setActivePinia(createPinia())
9  })
10
11  it('initializes with empty artworks', () => {
12    const store = useGalleryStore()
13    expect(store.artworks).toEqual([])
14  })
15
16  it('fetches artworks', async () => {
17    const mockArtworks = [
18      { id: 1, title: 'Mona Lisa' },
19      { id: 2, title: 'Last Supper' }
20    ]
21
22    global.fetch = vi.fn().mockResolvedValue({
23      ok: true,
24      json: async () => mockArtworks
25    })
26
27    const store = useGalleryStore()
28
29    await store.fetchArtworks()
30
31    expect(store.artworks).toEqual(mockArtworks)
32    expect(store.isLoading).toBe(false)
33  })
34
35  it('handles fetch errors', async () => {
36    global.fetch = vi.fn().mockResolvedValue({
37      ok: false
38    })
39
40    const store = useGalleryStore()
41
42    await expect(store.fetchArtworks()).rejects.toThrow()
43    expect(store.error).toBeTruthy()
44  })
45
46  it('filters artworks by search', () => {
47    const store = useGalleryStore()
48
49    store.artworks = [
50      { id: 1, title: 'Mona Lisa', artist: 'Leonardo' },
51      { id: 2, title: 'Last Supper', artist: 'Leonardo' },
52      { id: 3, title: 'David', artist: 'Michelangelo' }
53    ]
54
55    store.filters.search = 'mona'
56
57    expect(store.filteredArtworks).toHaveLength(1)
58    expect(store.filteredArtworks[0].title).toBe('Mona Lisa')
59  })
60
61  it('adds artwork', async () => {
62    const newArtwork = { title: 'New Artwork', artist: 'Test' }
63    const savedArtwork = { id: 1, ...newArtwork }
64
65    global.fetch = vi.fn().mockResolvedValue({
66      ok: true,
67      json: async () => savedArtwork
68    })
69
70    const store = useGalleryStore()
71
72    const result = await store.addArtwork(newArtwork)
73
74    expect(store.artworks).toContainEqual(savedArtwork)
75    expect(result).toEqual(savedArtwork)
76  })
77})

Mocking Dependencies

1// stores/gallery.js uses useAuthStore
2import { vi } from 'vitest'
3
4vi.mock('./auth', () => ({
5  useAuthStore: () => ({
6    token: 'fake-token',
7    isAuthenticated: true
8  })
9}))
Ir a CodeWorlds