import { describe, it, expect, vi, beforeEach } from 'vitest' import { mount, flushPromises } from '@vue/test-utils' import { createRouter, createMemoryHistory } from 'vue-router' import ElementPlus from 'element-plus' import SessionSidebar from '../src/components/SessionSidebar.vue' import LoginView from '../src/views/LoginView.vue' import axios from 'axios' vi.mock('axios', () => ({ default: { get: vi.fn(), }, })) const mockedAxios = axios const makeRouter = () => createRouter({ history: createMemoryHistory(), routes: [ { path: '/', name: 'login', component: LoginView }, { path: '/welcome', name: 'welcome', component: LoginView }, { path: '/chat/:id', name: 'chat', component: LoginView }, ], }) describe('SessionSidebar', () => { beforeEach(() => { localStorage.clear() vi.clearAllMocks() }) it('redirects to login without token', async () => { const router = makeRouter() router.push('/welcome') await router.isReady() mount(SessionSidebar, { global: { plugins: [router, ElementPlus], }, }) await flushPromises() expect(router.currentRoute.value.name).toBe('login') }) it('renders sessions and selects one', async () => { localStorage.setItem('ars-token', 'jwt-token') mockedAxios.get.mockResolvedValue({ data: { data: [ { session_id: 's1', session_name: 'Demo', status: 'OPEN', last_message_preview: 'Hi there', last_seq: 3, updated_at: '2025-02-14T10:00:00Z', }, ], total: 1, current_page: 1, per_page: 20, last_page: 1, }, }) const router = makeRouter() router.push('/welcome') await router.isReady() const wrapper = mount(SessionSidebar, { global: { plugins: [router, ElementPlus], }, }) await flushPromises() expect(mockedAxios.get).toHaveBeenCalledWith( 'http://localhost:8000/api/sessions', expect.any(Object) ) expect(wrapper.text()).toContain('Demo') await wrapper.find('.session-item').trigger('click') await flushPromises() expect(localStorage.getItem('ars-current-session')).toBe('s1') expect(router.currentRoute.value.name).toBe('chat') }) it('resets page when refreshing after loading more', async () => { localStorage.setItem('ars-token', 'jwt-token') mockedAxios.get .mockResolvedValueOnce({ data: { data: [{ session_id: 's1', session_name: 'P1', status: 'OPEN' }], meta: { total: 2, current_page: 1, per_page: 10, last_page: 2 }, }, }) .mockResolvedValueOnce({ data: { data: [{ session_id: 's2', session_name: 'P2', status: 'OPEN' }], meta: { total: 2, current_page: 2, per_page: 10, last_page: 2 }, }, }) .mockResolvedValueOnce({ data: { data: [{ session_id: 's1', session_name: 'Refreshed', status: 'OPEN' }], meta: { total: 1, current_page: 1, per_page: 10, last_page: 1 }, }, }) const router = makeRouter() router.push('/welcome') await router.isReady() const wrapper = mount(SessionSidebar, { global: { plugins: [router, ElementPlus], }, }) await flushPromises() expect(wrapper.findAll('.session-item')).toHaveLength(1) await wrapper.find('.load-more').trigger('click') await flushPromises() expect(mockedAxios.get.mock.calls[1][1].params.page).toBe(2) expect(wrapper.findAll('.session-item')).toHaveLength(2) await wrapper.find('[data-testid="refresh-btn"]').trigger('click') await flushPromises() expect(mockedAxios.get.mock.calls[2][1].params.page).toBe(1) expect(wrapper.findAll('.session-item')).toHaveLength(1) expect(wrapper.text()).toContain('Refreshed') }) })