import { describe, it, expect, beforeEach, vi } from 'vitest'; import { setActivePinia, createPinia } from 'pinia'; vi.mock('@/module/apiError.js', () => ({ default: vi.fn(), })); const { mockGet, mockPost, mockPut, mockDelete } = vi.hoisted(() => ({ mockGet: vi.fn(), mockPost: vi.fn(), mockPut: vi.fn(), mockDelete: vi.fn(), })); vi.mock('@/api/client.js', () => ({ default: { get: mockGet, post: mockPost, put: mockPut, delete: mockDelete }, })); // Mock login store to avoid its side effects vi.mock('@/stores/login.ts', () => { const { defineStore } = require('pinia'); return { default: defineStore('loginStore', { state: () => ({ userData: { username: 'currentUser', name: 'Current' }, }), actions: { getUserData: vi.fn(), }, }), }; }); import useAcctMgmtStore from '@/stores/acctMgmt.ts'; describe('acctMgmtStore', () => { let store; beforeEach(() => { setActivePinia(createPinia()); store = useAcctMgmtStore(); vi.clearAllMocks(); }); it('has correct default state', () => { expect(store.allUserAccoutList).toEqual([]); expect(store.isAcctMenuOpen).toBe(false); }); describe('menu actions', () => { it('openAcctMenu sets true', () => { store.openAcctMenu(); expect(store.isAcctMenuOpen).toBe(true); }); it('closeAcctMenu sets false', () => { store.openAcctMenu(); store.closeAcctMenu(); expect(store.isAcctMenuOpen).toBe(false); }); it('toggleIsAcctMenuOpen toggles', () => { store.toggleIsAcctMenuOpen(); expect(store.isAcctMenuOpen).toBe(true); store.toggleIsAcctMenuOpen(); expect(store.isAcctMenuOpen).toBe(false); }); }); describe('setCurrentViewingUser', () => { it('finds user by username', () => { store.allUserAccoutList = [ { username: 'alice', name: 'Alice', detail: {} }, { username: 'bob', name: 'Bob', detail: {} }, ]; store.setCurrentViewingUser('bob'); expect(store.currentViewingUser.name).toBe('Bob'); }); }); describe('clearCurrentViewingUser', () => { it('resets to empty user', () => { store.currentViewingUser = { username: 'test', detail: {} }; store.clearCurrentViewingUser(); expect(store.currentViewingUser.username).toBe(''); }); }); describe('createNewAccount', () => { it('posts to /api/users and sets flag on success', async () => { mockPost.mockResolvedValue({ status: 200 }); const user = { username: 'newuser', password: 'pass' }; await store.createNewAccount(user); expect(mockPost).toHaveBeenCalledWith( '/api/users', user, ); expect(store.isOneAccountJustCreate).toBe(true); expect(store.justCreateUsername).toBe('newuser'); }); }); describe('deleteAccount', () => { it('returns true on success', async () => { mockDelete.mockResolvedValue({ status: 200 }); const result = await store.deleteAccount('alice'); expect(mockDelete).toHaveBeenCalledWith( '/api/users/alice', ); expect(result).toBe(true); }); it('returns false on error', async () => { mockDelete.mockRejectedValue(new Error('fail')); const result = await store.deleteAccount('alice'); expect(result).toBe(false); }); }); describe('editAccount', () => { it('puts edited data', async () => { mockPut.mockResolvedValue({ status: 200 }); const detail = { username: 'alice', password: 'newpw', name: 'Alice', is_active: true, }; const result = await store.editAccount('alice', detail); expect(mockPut).toHaveBeenCalledWith( '/api/users/alice', expect.objectContaining({ password: 'newpw' }), ); expect(result).toBe(true); }); }); describe('addRoleToUser', () => { it('puts role assignment', async () => { mockPut.mockResolvedValue({ status: 200 }); const result = await store.addRoleToUser('alice', 'admin'); expect(mockPut).toHaveBeenCalledWith( '/api/users/alice/roles/admin', ); expect(result).toBe(true); }); }); describe('deleteRoleToUser', () => { it('deletes role', async () => { mockDelete.mockResolvedValue({ status: 200 }); const result = await store.deleteRoleToUser('alice', 'admin'); expect(mockDelete).toHaveBeenCalledWith( '/api/users/alice/roles/admin', ); expect(result).toBe(true); }); }); describe('getUserDetail', () => { it('fetches user and sets admin flag', async () => { mockGet.mockResolvedValue({ status: 200, data: { username: 'alice', roles: [{ code: 'admin' }], }, }); const result = await store.getUserDetail('alice'); expect(result).toBe(true); expect(store.currentViewingUser.is_admin).toBe(true); }); it('returns false on error', async () => { mockGet.mockRejectedValue(new Error('not found')); const result = await store.getUserDetail('ghost'); expect(result).toBe(false); }); }); describe('hover state actions', () => { beforeEach(() => { store.allUserAccoutList = [ { username: 'alice', isDeleteHovered: false, isRowHovered: false, isEditHovered: false, isDetailHovered: false, }, ]; }); it('changeIsDeleteHoveredByUser', () => { store.changeIsDeleteHoveredByUser('alice', true); expect(store.allUserAccoutList[0].isDeleteHovered).toBe(true); }); it('changeIsRowHoveredByUser', () => { store.changeIsRowHoveredByUser('alice', true); expect(store.allUserAccoutList[0].isRowHovered).toBe(true); }); it('changeIsEditHoveredByUser', () => { store.changeIsEditHoveredByUser('alice', true); expect(store.allUserAccoutList[0].isEditHovered).toBe(true); }); it('changeIsDetailHoveredByUser', () => { store.changeIsDetailHoveredByUser('alice', true); expect(store.allUserAccoutList[0].isDetailHovered).toBe(true); }); }); it('resetJustCreateFlag resets flag', () => { store.isOneAccountJustCreate = true; store.resetJustCreateFlag(); expect(store.isOneAccountJustCreate).toBe(false); }); it('setShouldUpdateList sets boolean', () => { store.setShouldUpdateList(true); expect(store.shouldUpdateList).toBe(true); }); it('updateSingleAccountPiniaState updates user', () => { store.allUserAccoutList = [ { username: 'alice', name: 'Old' }, ]; store.updateSingleAccountPiniaState({ username: 'alice', name: 'New', }); expect(store.allUserAccoutList[0].name).toBe('New'); }); });