| import { describe, it, expect, beforeEach, vi } from 'vitest' |
| import { flushPromises, mount } from '@vue/test-utils' |
| import { setActivePinia, createPinia } from 'pinia' |
| import BlogList from './BlogList.vue' |
| import { useBlogStore } from '../stores/blog' |
|
|
| vi.mock('../api', () => ({ default: { get: vi.fn() } })) |
| import api from '../api' |
|
|
| function mountBlogList() { |
| setActivePinia(createPinia()) |
| return mount(BlogList, { |
| global: { stubs: { Navbar: true, Footer: true, PostCard: true } }, |
| }) |
| } |
|
|
| describe('BlogList', () => { |
| beforeEach(() => vi.clearAllMocks()) |
|
|
| it('loads categories and page-1 posts on mount', async () => { |
| api.get |
| .mockResolvedValueOnce({ data: [] }) |
| .mockResolvedValueOnce({ data: { posts: [{ id: 1 }], total: 1, page: 1, pages: 1 } }) |
| mountBlogList() |
| await flushPromises() |
| expect(api.get).toHaveBeenCalledWith(expect.stringContaining('/posts?')) |
| }) |
|
|
| it('shows a loading skeleton while fetching', async () => { |
| api.get.mockResolvedValueOnce({ data: [] }).mockReturnValueOnce(new Promise(() => {})) |
| const wrapper = mountBlogList() |
| await flushPromises() |
| const blog = useBlogStore() |
| blog.loading = true |
| await wrapper.vm.$nextTick() |
| expect(wrapper.findAll('.animate-pulse').length).toBe(6) |
| }) |
|
|
| it('renders pagination and reloads posts on page change', async () => { |
| api.get |
| .mockResolvedValueOnce({ data: [] }) |
| .mockResolvedValueOnce({ data: { posts: [{ id: 1 }], total: 30, page: 1, pages: 3 } }) |
| const wrapper = mountBlogList() |
| await flushPromises() |
| const pageBtns = wrapper.findAll('button') |
| expect(pageBtns.length).toBe(3) |
| api.get.mockResolvedValueOnce({ data: { posts: [], total: 30, page: 2, pages: 3 } }) |
| await pageBtns[1].trigger('click') |
| await flushPromises() |
| expect(api.get).toHaveBeenLastCalledWith(expect.stringContaining('page=2')) |
| }) |
| }) |
|
|