You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
78 lines
3.1 KiB
78 lines
3.1 KiB
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
import { render, screen, fireEvent, waitFor } from '@testing-library/svelte'
|
|
import MyDecks from './MyDecks.svelte'
|
|
import { auth } from '../lib/stores/auth.js'
|
|
|
|
const mockPush = vi.fn()
|
|
vi.mock('svelte-spa-router', () => ({ push: (...args) => mockPush(...args) }))
|
|
|
|
vi.mock('../lib/stores/auth.js', () => {
|
|
const { writable } = require('svelte/store')
|
|
const store = writable({ user: { id: 'u1' }, loading: false, error: null })
|
|
return { auth: { subscribe: store.subscribe, set: store.set } }
|
|
})
|
|
|
|
const mockFetchMyDecks = vi.fn()
|
|
const mockTogglePublished = vi.fn()
|
|
const mockGetMyDeckRating = vi.fn()
|
|
const mockSubmitDeckRating = vi.fn()
|
|
const mockGetSourceUpdatePreview = vi.fn()
|
|
const mockApplySourceUpdate = vi.fn()
|
|
const mockDeleteDeck = vi.fn()
|
|
vi.mock('../lib/api/decks.js', () => ({
|
|
fetchMyDecks: (...args) => mockFetchMyDecks(...args),
|
|
togglePublished: (...args) => mockTogglePublished(...args),
|
|
getMyDeckRating: (...args) => mockGetMyDeckRating(...args),
|
|
submitDeckRating: (...args) => mockSubmitDeckRating(...args),
|
|
getSourceUpdatePreview: (...args) => mockGetSourceUpdatePreview(...args),
|
|
applySourceUpdate: (...args) => mockApplySourceUpdate(...args),
|
|
deleteDeck: (...args) => mockDeleteDeck(...args),
|
|
}))
|
|
|
|
describe('MyDecks', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
auth.set({ user: { id: 'u1' }, loading: false, error: null })
|
|
mockFetchMyDecks.mockResolvedValue([])
|
|
})
|
|
|
|
it('shows sign in message when no user', () => {
|
|
auth.set({ user: null, loading: false, error: null })
|
|
render(MyDecks)
|
|
expect(screen.getByText(/Sign in to create and manage your decks/)).toBeInTheDocument()
|
|
})
|
|
|
|
it('shows loading then empty message when no decks', async () => {
|
|
render(MyDecks)
|
|
expect(screen.getByText(/Loading/)).toBeInTheDocument()
|
|
await waitFor(() => expect(screen.getByText(/No decks yet/)).toBeInTheDocument())
|
|
expect(mockFetchMyDecks).toHaveBeenCalledWith('u1')
|
|
})
|
|
|
|
it('shows error when fetch fails', async () => {
|
|
mockFetchMyDecks.mockRejectedValue(new Error('Failed to load'))
|
|
render(MyDecks)
|
|
await waitFor(() => expect(screen.getByText('Failed to load')).toBeInTheDocument())
|
|
})
|
|
|
|
it('renders deck list and goEdit navigates to edit', async () => {
|
|
mockFetchMyDecks.mockResolvedValue([
|
|
{ id: 'd1', title: 'Deck One', description: '', question_count: 2, copied_from_deck_id: null },
|
|
])
|
|
render(MyDecks)
|
|
await waitFor(() => expect(screen.getByText('Deck One')).toBeInTheDocument())
|
|
await fireEvent.click(screen.getByTitle('Edit deck'))
|
|
expect(mockPush).toHaveBeenCalledWith('/decks/d1/edit')
|
|
})
|
|
|
|
it('clicking card goes to preview', async () => {
|
|
mockFetchMyDecks.mockResolvedValue([
|
|
{ id: 'd1', title: 'Deck One', description: '', question_count: 2, copied_from_deck_id: null },
|
|
])
|
|
render(MyDecks)
|
|
await waitFor(() => expect(screen.getByText('Deck One')).toBeInTheDocument())
|
|
await fireEvent.click(screen.getByRole('button', { name: /Deck One/ }))
|
|
expect(mockPush).toHaveBeenCalledWith('/decks/d1/preview')
|
|
})
|
|
})
|