Add store tests with mocked axios and apiError
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
246
tests/stores/acctMgmt.test.js
Normal file
246
tests/stores/acctMgmt.test.js
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||||
|
import { setActivePinia, createPinia } from 'pinia';
|
||||||
|
|
||||||
|
vi.mock('@/module/apiError.js', () => ({
|
||||||
|
default: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
const mockAxios = {
|
||||||
|
get: vi.fn(),
|
||||||
|
post: vi.fn(),
|
||||||
|
put: vi.fn(),
|
||||||
|
delete: vi.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(createPinia());
|
||||||
|
store = useAcctMgmtStore();
|
||||||
|
store.$axios = mockAxios;
|
||||||
|
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 () => {
|
||||||
|
mockAxios.post.mockResolvedValue({ status: 200 });
|
||||||
|
const user = { username: 'newuser', password: 'pass' };
|
||||||
|
|
||||||
|
await store.createNewAccount(user);
|
||||||
|
|
||||||
|
expect(mockAxios.post).toHaveBeenCalledWith(
|
||||||
|
'/api/users', user,
|
||||||
|
);
|
||||||
|
expect(store.isOneAccountJustCreate).toBe(true);
|
||||||
|
expect(store.justCreateUsername).toBe('newuser');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('deleteAccount', () => {
|
||||||
|
it('returns true on success', async () => {
|
||||||
|
mockAxios.delete.mockResolvedValue({ status: 200 });
|
||||||
|
|
||||||
|
const result = await store.deleteAccount('alice');
|
||||||
|
|
||||||
|
expect(mockAxios.delete).toHaveBeenCalledWith(
|
||||||
|
'/api/users/alice',
|
||||||
|
);
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns false on error', async () => {
|
||||||
|
mockAxios.delete.mockRejectedValue(new Error('fail'));
|
||||||
|
|
||||||
|
const result = await store.deleteAccount('alice');
|
||||||
|
|
||||||
|
expect(result).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('editAccount', () => {
|
||||||
|
it('puts edited data', async () => {
|
||||||
|
mockAxios.put.mockResolvedValue({ status: 200 });
|
||||||
|
const detail = {
|
||||||
|
username: 'alice',
|
||||||
|
password: 'newpw',
|
||||||
|
name: 'Alice',
|
||||||
|
is_active: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await store.editAccount('alice', detail);
|
||||||
|
|
||||||
|
expect(mockAxios.put).toHaveBeenCalledWith(
|
||||||
|
'/api/users/alice',
|
||||||
|
expect.objectContaining({ password: 'newpw' }),
|
||||||
|
);
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('addRoleToUser', () => {
|
||||||
|
it('puts role assignment', async () => {
|
||||||
|
mockAxios.put.mockResolvedValue({ status: 200 });
|
||||||
|
|
||||||
|
const result = await store.addRoleToUser('alice', 'admin');
|
||||||
|
|
||||||
|
expect(mockAxios.put).toHaveBeenCalledWith(
|
||||||
|
'/api/users/alice/roles/admin',
|
||||||
|
);
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('deleteRoleToUser', () => {
|
||||||
|
it('deletes role', async () => {
|
||||||
|
mockAxios.delete.mockResolvedValue({ status: 200 });
|
||||||
|
|
||||||
|
const result = await store.deleteRoleToUser('alice', 'admin');
|
||||||
|
|
||||||
|
expect(mockAxios.delete).toHaveBeenCalledWith(
|
||||||
|
'/api/users/alice/roles/admin',
|
||||||
|
);
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getUserDetail', () => {
|
||||||
|
it('fetches user and sets admin flag', async () => {
|
||||||
|
mockAxios.get.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 () => {
|
||||||
|
mockAxios.get.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');
|
||||||
|
});
|
||||||
|
});
|
||||||
209
tests/stores/allMapData.test.js
Normal file
209
tests/stores/allMapData.test.js
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||||
|
import { setActivePinia, createPinia } from 'pinia';
|
||||||
|
|
||||||
|
vi.mock('@/module/apiError.js', () => ({
|
||||||
|
default: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
import useAllMapDataStore from '@/stores/allMapData.js';
|
||||||
|
|
||||||
|
describe('allMapDataStore', () => {
|
||||||
|
let store;
|
||||||
|
const mockAxios = {
|
||||||
|
get: vi.fn(),
|
||||||
|
post: vi.fn(),
|
||||||
|
put: vi.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(createPinia());
|
||||||
|
store = useAllMapDataStore();
|
||||||
|
store.$axios = mockAxios;
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has correct default state', () => {
|
||||||
|
expect(store.logId).toBeNull();
|
||||||
|
expect(store.allProcessMap).toEqual({});
|
||||||
|
expect(store.allTrace).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getAllMapData', () => {
|
||||||
|
it('fetches log discover data', async () => {
|
||||||
|
store.logId = 1;
|
||||||
|
const mockData = {
|
||||||
|
process_map: { nodes: [] },
|
||||||
|
bpmn: { nodes: [] },
|
||||||
|
stats: { cases: 10 },
|
||||||
|
insights: {},
|
||||||
|
};
|
||||||
|
mockAxios.get.mockResolvedValue({ data: mockData });
|
||||||
|
|
||||||
|
await store.getAllMapData();
|
||||||
|
|
||||||
|
expect(mockAxios.get).toHaveBeenCalledWith(
|
||||||
|
'/api/logs/1/discover',
|
||||||
|
);
|
||||||
|
expect(store.allProcessMap).toEqual({ nodes: [] });
|
||||||
|
expect(store.allStats).toEqual({ cases: 10 });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fetches temp filter discover data when set', async () => {
|
||||||
|
store.logId = 1;
|
||||||
|
store.tempFilterId = 5;
|
||||||
|
mockAxios.get.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
process_map: {},
|
||||||
|
bpmn: {},
|
||||||
|
stats: {},
|
||||||
|
insights: {},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await store.getAllMapData();
|
||||||
|
|
||||||
|
expect(mockAxios.get).toHaveBeenCalledWith(
|
||||||
|
'/api/temp-filters/5/discover',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fetches created filter discover data', async () => {
|
||||||
|
store.logId = 1;
|
||||||
|
store.createFilterId = 3;
|
||||||
|
mockAxios.get.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
process_map: {},
|
||||||
|
bpmn: {},
|
||||||
|
stats: {},
|
||||||
|
insights: {},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await store.getAllMapData();
|
||||||
|
|
||||||
|
expect(mockAxios.get).toHaveBeenCalledWith(
|
||||||
|
'/api/filters/3/discover',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not throw on API failure', async () => {
|
||||||
|
store.logId = 1;
|
||||||
|
mockAxios.get.mockRejectedValue(new Error('fail'));
|
||||||
|
|
||||||
|
await expect(store.getAllMapData())
|
||||||
|
.resolves.not.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getFilterParams', () => {
|
||||||
|
it('fetches filter params and transforms timeframe', async () => {
|
||||||
|
store.logId = 1;
|
||||||
|
const mockData = {
|
||||||
|
tasks: ['A', 'B'],
|
||||||
|
sources: ['A'],
|
||||||
|
sinks: ['B'],
|
||||||
|
timeframe: {
|
||||||
|
x_axis: {
|
||||||
|
min: '2023-01-01T00:00:00Z',
|
||||||
|
max: '2023-12-31T00:00:00Z',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
trace: [],
|
||||||
|
attrs: [],
|
||||||
|
};
|
||||||
|
mockAxios.get.mockResolvedValue({ data: mockData });
|
||||||
|
|
||||||
|
await store.getFilterParams();
|
||||||
|
|
||||||
|
expect(mockAxios.get).toHaveBeenCalledWith(
|
||||||
|
'/api/filters/params?log_id=1',
|
||||||
|
);
|
||||||
|
expect(store.allFilterTask).toEqual(['A', 'B']);
|
||||||
|
// Check that min_base and max_base are stored
|
||||||
|
expect(store.allFilterTimeframe.x_axis.min_base)
|
||||||
|
.toBe('2023-01-01T00:00:00Z');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('checkHasResult', () => {
|
||||||
|
it('posts rule data and stores result', async () => {
|
||||||
|
store.logId = 1;
|
||||||
|
store.postRuleData = [{ type: 'task' }];
|
||||||
|
mockAxios.post.mockResolvedValue({
|
||||||
|
data: { result: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
await store.checkHasResult();
|
||||||
|
|
||||||
|
expect(mockAxios.post).toHaveBeenCalledWith(
|
||||||
|
'/api/filters/has-result?log_id=1',
|
||||||
|
[{ type: 'task' }],
|
||||||
|
);
|
||||||
|
expect(store.hasResultRule).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('addTempFilterId', () => {
|
||||||
|
it('creates temp filter and stores id', async () => {
|
||||||
|
store.logId = 1;
|
||||||
|
store.postRuleData = [];
|
||||||
|
mockAxios.post.mockResolvedValue({ data: { id: 77 } });
|
||||||
|
|
||||||
|
await store.addTempFilterId();
|
||||||
|
|
||||||
|
expect(store.tempFilterId).toBe(77);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('addFilterId', () => {
|
||||||
|
it('creates filter and clears temp id', async () => {
|
||||||
|
store.logId = 1;
|
||||||
|
store.tempFilterId = 77;
|
||||||
|
store.postRuleData = [{ type: 'rule' }];
|
||||||
|
mockAxios.post.mockResolvedValue({ data: { id: 88 } });
|
||||||
|
|
||||||
|
await store.addFilterId('myFilter');
|
||||||
|
|
||||||
|
expect(mockAxios.post).toHaveBeenCalledWith(
|
||||||
|
'/api/filters?log_id=1',
|
||||||
|
{ name: 'myFilter', rules: [{ type: 'rule' }] },
|
||||||
|
);
|
||||||
|
expect(store.createFilterId).toBe(88);
|
||||||
|
expect(store.tempFilterId).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('updataFilter', () => {
|
||||||
|
it('updates filter and clears temp id', async () => {
|
||||||
|
store.createFilterId = 88;
|
||||||
|
store.tempFilterId = 77;
|
||||||
|
store.postRuleData = [{ type: 'updated' }];
|
||||||
|
mockAxios.put.mockResolvedValue({ status: 200 });
|
||||||
|
|
||||||
|
await store.updataFilter();
|
||||||
|
|
||||||
|
expect(mockAxios.put).toHaveBeenCalledWith(
|
||||||
|
'/api/filters/88',
|
||||||
|
[{ type: 'updated' }],
|
||||||
|
);
|
||||||
|
expect(store.isUpdataFilter).toBe(true);
|
||||||
|
expect(store.tempFilterId).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getters', () => {
|
||||||
|
it('traces getter sorts by id', () => {
|
||||||
|
store.allTrace = [
|
||||||
|
{ id: 3, name: 'C' },
|
||||||
|
{ id: 1, name: 'A' },
|
||||||
|
{ id: 2, name: 'B' },
|
||||||
|
];
|
||||||
|
expect(store.traces.map(t => t.id)).toEqual([1, 2, 3]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('processMap getter returns state', () => {
|
||||||
|
store.allProcessMap = { nodes: [1, 2] };
|
||||||
|
expect(store.processMap).toEqual({ nodes: [1, 2] });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
107
tests/stores/compare.test.js
Normal file
107
tests/stores/compare.test.js
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||||
|
import { setActivePinia, createPinia } from 'pinia';
|
||||||
|
|
||||||
|
vi.mock('@/module/apiError.js', () => ({
|
||||||
|
default: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
import useCompareStore from '@/stores/compare.js';
|
||||||
|
|
||||||
|
describe('compareStore', () => {
|
||||||
|
let store;
|
||||||
|
const mockAxios = {
|
||||||
|
get: vi.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(createPinia());
|
||||||
|
store = useCompareStore();
|
||||||
|
store.$axios = mockAxios;
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has correct default state', () => {
|
||||||
|
expect(store.allCompareDashboardData).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('compareDashboardData getter returns state', () => {
|
||||||
|
store.allCompareDashboardData = { time: {} };
|
||||||
|
expect(store.compareDashboardData).toEqual({ time: {} });
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getCompare', () => {
|
||||||
|
it('fetches compare data with encoded params', async () => {
|
||||||
|
const params = [{ type: 'log', id: 1 }];
|
||||||
|
const mockData = { time: {}, freq: {} };
|
||||||
|
mockAxios.get.mockResolvedValue({ data: mockData });
|
||||||
|
|
||||||
|
await store.getCompare(params);
|
||||||
|
|
||||||
|
const encoded = encodeURIComponent(JSON.stringify(params));
|
||||||
|
expect(mockAxios.get).toHaveBeenCalledWith(
|
||||||
|
`/api/compare?datasets=${encoded}`,
|
||||||
|
);
|
||||||
|
expect(store.allCompareDashboardData).toEqual(mockData);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not throw on API failure', async () => {
|
||||||
|
mockAxios.get.mockRejectedValue(new Error('fail'));
|
||||||
|
|
||||||
|
await expect(store.getCompare([]))
|
||||||
|
.resolves.not.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getStateData', () => {
|
||||||
|
it('fetches log discover stats', async () => {
|
||||||
|
mockAxios.get.mockResolvedValue({
|
||||||
|
data: { stats: { cases: 100 } },
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await store.getStateData('log', 1);
|
||||||
|
|
||||||
|
expect(mockAxios.get).toHaveBeenCalledWith(
|
||||||
|
'/api/logs/1/discover',
|
||||||
|
);
|
||||||
|
expect(result).toEqual({ cases: 100 });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fetches filter discover stats', async () => {
|
||||||
|
mockAxios.get.mockResolvedValue({
|
||||||
|
data: { stats: { cases: 50 } },
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await store.getStateData('filter', 3);
|
||||||
|
|
||||||
|
expect(mockAxios.get).toHaveBeenCalledWith(
|
||||||
|
'/api/filters/3/discover',
|
||||||
|
);
|
||||||
|
expect(result).toEqual({ cases: 50 });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getFileName', () => {
|
||||||
|
it('finds file name by id', async () => {
|
||||||
|
mockAxios.get.mockResolvedValue({
|
||||||
|
data: [
|
||||||
|
{ id: 1, name: 'file1.csv' },
|
||||||
|
{ id: 2, name: 'file2.csv' },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await store.getFileName(1);
|
||||||
|
|
||||||
|
expect(result).toBe('file1.csv');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns undefined for non-existent id', async () => {
|
||||||
|
mockAxios.get.mockResolvedValue({
|
||||||
|
data: [{ id: 1, name: 'file1.csv' }],
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await store.getFileName(99);
|
||||||
|
|
||||||
|
expect(result).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
179
tests/stores/conformance.test.js
Normal file
179
tests/stores/conformance.test.js
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||||
|
import { setActivePinia, createPinia } from 'pinia';
|
||||||
|
|
||||||
|
vi.mock('@/module/apiError.js', () => ({
|
||||||
|
default: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
import apiError from '@/module/apiError.js';
|
||||||
|
import useConformanceStore from '@/stores/conformance.js';
|
||||||
|
|
||||||
|
describe('conformanceStore', () => {
|
||||||
|
let store;
|
||||||
|
const mockAxios = {
|
||||||
|
get: vi.fn(),
|
||||||
|
post: vi.fn(),
|
||||||
|
put: vi.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(createPinia());
|
||||||
|
store = useConformanceStore();
|
||||||
|
store.$axios = mockAxios;
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has correct default state', () => {
|
||||||
|
expect(store.conformanceLogId).toBeNull();
|
||||||
|
expect(store.conformanceFilterId).toBeNull();
|
||||||
|
expect(store.allConformanceTask).toEqual([]);
|
||||||
|
expect(store.selectedRuleType).toBe('Have activity');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getConformanceParams', () => {
|
||||||
|
it('fetches log check params when no filter', async () => {
|
||||||
|
store.conformanceLogId = 1;
|
||||||
|
store.conformanceFilterId = null;
|
||||||
|
const mockData = {
|
||||||
|
tasks: [{ label: 'A' }],
|
||||||
|
sources: ['A'],
|
||||||
|
sinks: ['B'],
|
||||||
|
processing_time: {},
|
||||||
|
waiting_time: {},
|
||||||
|
cycle_time: {},
|
||||||
|
};
|
||||||
|
mockAxios.get.mockResolvedValue({ data: mockData });
|
||||||
|
|
||||||
|
await store.getConformanceParams();
|
||||||
|
|
||||||
|
expect(mockAxios.get).toHaveBeenCalledWith(
|
||||||
|
'/api/log-checks/params?log_id=1',
|
||||||
|
);
|
||||||
|
expect(store.allConformanceTask).toEqual([{ label: 'A' }]);
|
||||||
|
expect(store.allCfmSeqStart).toEqual(['A']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fetches filter check params when filter set', async () => {
|
||||||
|
store.conformanceFilterId = 5;
|
||||||
|
const mockData = {
|
||||||
|
tasks: [],
|
||||||
|
sources: [],
|
||||||
|
sinks: [],
|
||||||
|
processing_time: {},
|
||||||
|
waiting_time: {},
|
||||||
|
cycle_time: {},
|
||||||
|
};
|
||||||
|
mockAxios.get.mockResolvedValue({ data: mockData });
|
||||||
|
|
||||||
|
await store.getConformanceParams();
|
||||||
|
|
||||||
|
expect(mockAxios.get).toHaveBeenCalledWith(
|
||||||
|
'/api/filter-checks/params?filter_id=5',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('addConformanceCheckId', () => {
|
||||||
|
it('posts to log temp-check and stores id', async () => {
|
||||||
|
store.conformanceLogId = 1;
|
||||||
|
store.conformanceFilterId = null;
|
||||||
|
mockAxios.post.mockResolvedValue({ data: { id: 42 } });
|
||||||
|
|
||||||
|
await store.addConformanceCheckId({ rule: 'test' });
|
||||||
|
|
||||||
|
expect(mockAxios.post).toHaveBeenCalledWith(
|
||||||
|
'/api/temp-log-checks?log_id=1',
|
||||||
|
{ rule: 'test' },
|
||||||
|
);
|
||||||
|
expect(store.conformanceLogTempCheckId).toBe(42);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('posts to filter temp-check when filter set', async () => {
|
||||||
|
store.conformanceFilterId = 3;
|
||||||
|
mockAxios.post.mockResolvedValue({ data: { id: 99 } });
|
||||||
|
|
||||||
|
await store.addConformanceCheckId({ rule: 'test' });
|
||||||
|
|
||||||
|
expect(mockAxios.post).toHaveBeenCalledWith(
|
||||||
|
'/api/temp-filter-checks?filter_id=3',
|
||||||
|
{ rule: 'test' },
|
||||||
|
);
|
||||||
|
expect(store.conformanceFilterTempCheckId).toBe(99);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getConformanceReport', () => {
|
||||||
|
it('fetches temp log check report', async () => {
|
||||||
|
store.conformanceLogTempCheckId = 10;
|
||||||
|
const mockData = { file: {}, charts: {} };
|
||||||
|
mockAxios.get.mockResolvedValue({ data: mockData });
|
||||||
|
|
||||||
|
await store.getConformanceReport();
|
||||||
|
|
||||||
|
expect(mockAxios.get).toHaveBeenCalledWith(
|
||||||
|
'/api/temp-log-checks/10',
|
||||||
|
);
|
||||||
|
expect(store.allConformanceTempReportData).toEqual(mockData);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('stores routeFile when getRouteFile=true', async () => {
|
||||||
|
store.conformanceLogTempCheckId = 10;
|
||||||
|
const mockData = { file: { name: 'test.csv' } };
|
||||||
|
mockAxios.get.mockResolvedValue({ data: mockData });
|
||||||
|
|
||||||
|
await store.getConformanceReport(true);
|
||||||
|
|
||||||
|
expect(store.allRouteFile).toEqual({ name: 'test.csv' });
|
||||||
|
expect(store.allConformanceTempReportData).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('addConformanceCreateCheckId', () => {
|
||||||
|
it('creates log check and clears temp id', async () => {
|
||||||
|
store.conformanceLogId = 1;
|
||||||
|
store.conformanceFilterId = null;
|
||||||
|
store.conformanceLogTempCheckId = 10;
|
||||||
|
store.conformanceRuleData = { type: 'test' };
|
||||||
|
mockAxios.post.mockResolvedValue({ data: { id: 100 } });
|
||||||
|
|
||||||
|
await store.addConformanceCreateCheckId('myRule');
|
||||||
|
|
||||||
|
expect(mockAxios.post).toHaveBeenCalledWith(
|
||||||
|
'/api/log-checks?log_id=1',
|
||||||
|
{ name: 'myRule', rule: { type: 'test' } },
|
||||||
|
);
|
||||||
|
expect(store.conformanceLogCreateCheckId).toBe(100);
|
||||||
|
expect(store.conformanceLogTempCheckId).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('updataConformance', () => {
|
||||||
|
it('updates existing log check', async () => {
|
||||||
|
store.conformanceLogCreateCheckId = 50;
|
||||||
|
store.conformanceRuleData = { type: 'updated' };
|
||||||
|
mockAxios.put.mockResolvedValue({ status: 200 });
|
||||||
|
|
||||||
|
await store.updataConformance();
|
||||||
|
|
||||||
|
expect(mockAxios.put).toHaveBeenCalledWith(
|
||||||
|
'/api/log-checks/50',
|
||||||
|
{ type: 'updated' },
|
||||||
|
);
|
||||||
|
expect(store.isUpdataConformance).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setConformanceLogCreateCheckId sets value', () => {
|
||||||
|
store.setConformanceLogCreateCheckId('abc');
|
||||||
|
expect(store.conformanceLogCreateCheckId).toBe('abc');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getters', () => {
|
||||||
|
it('conformanceTask returns labels', () => {
|
||||||
|
store.allConformanceTask = [
|
||||||
|
{ label: 'A' }, { label: 'B' },
|
||||||
|
];
|
||||||
|
expect(store.conformanceTask).toEqual(['A', 'B']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
32
tests/stores/conformanceInput.test.js
Normal file
32
tests/stores/conformanceInput.test.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { describe, it, expect, beforeEach } from 'vitest';
|
||||||
|
import { setActivePinia, createPinia } from 'pinia';
|
||||||
|
import useConformanceInputStore from '@/stores/conformanceInput.js';
|
||||||
|
|
||||||
|
describe('conformanceInputStore', () => {
|
||||||
|
let store;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(createPinia());
|
||||||
|
store = useConformanceInputStore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has correct default state', () => {
|
||||||
|
expect(store.inputDataToSave.inputStart).toBeNull();
|
||||||
|
expect(store.activityRadioData.task).toEqual(['', '']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setActivityRadioStartEndData sets From', () => {
|
||||||
|
store.setActivityRadioStartEndData('taskA', 'From');
|
||||||
|
expect(store.activityRadioData.task[0]).toBe('taskA');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setActivityRadioStartEndData sets To', () => {
|
||||||
|
store.setActivityRadioStartEndData('taskB', 'To');
|
||||||
|
expect(store.activityRadioData.task[1]).toBe('taskB');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setActivityRadioStartEndData ignores unknown', () => {
|
||||||
|
store.setActivityRadioStartEndData('taskC', 'Unknown');
|
||||||
|
expect(store.activityRadioData.task).toEqual(['', '']);
|
||||||
|
});
|
||||||
|
});
|
||||||
78
tests/stores/cytoscapeStore.test.js
Normal file
78
tests/stores/cytoscapeStore.test.js
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||||
|
import { setActivePinia, createPinia } from 'pinia';
|
||||||
|
import useCytoscapeStore from '@/stores/cytoscapeStore.ts';
|
||||||
|
import { SAVE_KEY_NAME } from '@/constants/constants.js';
|
||||||
|
|
||||||
|
// Mock localStorage since jsdom's localStorage is limited
|
||||||
|
const localStorageMock = (() => {
|
||||||
|
let store = {};
|
||||||
|
return {
|
||||||
|
getItem: vi.fn((key) => store[key] || null),
|
||||||
|
setItem: vi.fn((key, value) => { store[key] = value; }),
|
||||||
|
removeItem: vi.fn((key) => { delete store[key]; }),
|
||||||
|
clear: vi.fn(() => { store = {}; }),
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
Object.defineProperty(globalThis, 'localStorage', {
|
||||||
|
value: localStorageMock,
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('cytoscapeStore', () => {
|
||||||
|
let store;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(createPinia());
|
||||||
|
store = useCytoscapeStore();
|
||||||
|
localStorageMock.clear();
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has correct default state', () => {
|
||||||
|
expect(store.nodePositions).toEqual({});
|
||||||
|
expect(store.currentGraphId).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setCurrentGraphId initializes graph structure', () => {
|
||||||
|
store.setCurrentGraphId('graph1');
|
||||||
|
expect(store.currentGraphId).toBe('graph1');
|
||||||
|
expect(store.nodePositions['graph1']).toEqual({
|
||||||
|
TB: [],
|
||||||
|
LR: [],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('saveNodePosition adds node and saves to localStorage', () => {
|
||||||
|
store.setCurrentGraphId('graph1');
|
||||||
|
store.saveNodePosition('node1', { x: 10, y: 20 }, 'TB');
|
||||||
|
expect(store.nodePositions['graph1']['TB']).toEqual([
|
||||||
|
{ id: 'node1', position: { x: 10, y: 20 } },
|
||||||
|
]);
|
||||||
|
expect(localStorageMock.setItem).toHaveBeenCalledWith(
|
||||||
|
SAVE_KEY_NAME,
|
||||||
|
expect.any(String),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('saveNodePosition updates existing node position', () => {
|
||||||
|
store.setCurrentGraphId('graph1');
|
||||||
|
store.saveNodePosition('node1', { x: 10, y: 20 }, 'TB');
|
||||||
|
store.saveNodePosition('node1', { x: 30, y: 40 }, 'TB');
|
||||||
|
expect(store.nodePositions['graph1']['TB']).toHaveLength(1);
|
||||||
|
expect(store.nodePositions['graph1']['TB'][0].position)
|
||||||
|
.toEqual({ x: 30, y: 40 });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loadPositionsFromStorage restores from localStorage', () => {
|
||||||
|
const data = {
|
||||||
|
graph1: {
|
||||||
|
TB: [{ id: 'n1', position: { x: 5, y: 10 } }],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
localStorageMock.getItem.mockReturnValue(JSON.stringify(data));
|
||||||
|
store.setCurrentGraphId('graph1');
|
||||||
|
store.loadPositionsFromStorage('TB');
|
||||||
|
expect(store.nodePositions['graph1']['TB']).toEqual([
|
||||||
|
{ id: 'n1', position: { x: 5, y: 10 } },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
27
tests/stores/loading.test.js
Normal file
27
tests/stores/loading.test.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { describe, it, expect, beforeEach } from 'vitest';
|
||||||
|
import { setActivePinia, createPinia } from 'pinia';
|
||||||
|
import useLoadingStore from '@/stores/loading.js';
|
||||||
|
|
||||||
|
describe('loadingStore', () => {
|
||||||
|
let store;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(createPinia());
|
||||||
|
store = useLoadingStore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has isLoading true by default', () => {
|
||||||
|
expect(store.isLoading).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setIsLoading sets to false', () => {
|
||||||
|
store.setIsLoading(false);
|
||||||
|
expect(store.isLoading).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setIsLoading sets to true', () => {
|
||||||
|
store.setIsLoading(false);
|
||||||
|
store.setIsLoading(true);
|
||||||
|
expect(store.isLoading).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
146
tests/stores/login.test.js
Normal file
146
tests/stores/login.test.js
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||||
|
import { setActivePinia, createPinia } from 'pinia';
|
||||||
|
|
||||||
|
// Mock apiError to prevent side effects (imports router, pinia, toast)
|
||||||
|
vi.mock('@/module/apiError.js', () => ({
|
||||||
|
default: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
import axios from 'axios';
|
||||||
|
import useLoginStore from '@/stores/login.ts';
|
||||||
|
|
||||||
|
// Mock axios methods
|
||||||
|
vi.spyOn(axios, 'post').mockImplementation(vi.fn());
|
||||||
|
vi.spyOn(axios, 'get').mockImplementation(vi.fn());
|
||||||
|
|
||||||
|
describe('loginStore', () => {
|
||||||
|
let store;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(createPinia());
|
||||||
|
store = useLoginStore();
|
||||||
|
store.$router = { push: vi.fn() };
|
||||||
|
vi.clearAllMocks();
|
||||||
|
// Clear cookies
|
||||||
|
document.cookie.split(';').forEach((c) => {
|
||||||
|
const name = c.split('=')[0].trim();
|
||||||
|
if (name) {
|
||||||
|
document.cookie = name + '=; Max-Age=-99999999; path=/';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has correct default state', () => {
|
||||||
|
expect(store.auth.grant_type).toBe('password');
|
||||||
|
expect(store.auth.username).toBe('');
|
||||||
|
expect(store.isLoggedIn).toBe(false);
|
||||||
|
expect(store.isInvalid).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('signIn', () => {
|
||||||
|
it('stores token and navigates on success', async () => {
|
||||||
|
axios.post.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
access_token: 'test-access-token',
|
||||||
|
refresh_token: 'test-refresh-token',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await store.signIn();
|
||||||
|
|
||||||
|
expect(axios.post).toHaveBeenCalledWith(
|
||||||
|
'/api/oauth/token',
|
||||||
|
store.auth,
|
||||||
|
expect.objectContaining({
|
||||||
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
expect(store.isLoggedIn).toBe(true);
|
||||||
|
expect(document.cookie).toContain('luciaToken=test-access-token');
|
||||||
|
expect(store.$router.push).toHaveBeenCalledWith('/files');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('redirects to remembered URL when set', async () => {
|
||||||
|
axios.post.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
access_token: 'token',
|
||||||
|
refresh_token: 'refresh',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// btoa('/dashboard') = 'L2Rhc2hib2FyZA=='
|
||||||
|
store.rememberedReturnToUrl = btoa('/dashboard');
|
||||||
|
|
||||||
|
// Mock window.location.href setter
|
||||||
|
const originalLocation = window.location;
|
||||||
|
delete window.location;
|
||||||
|
window.location = { href: '' };
|
||||||
|
|
||||||
|
await store.signIn();
|
||||||
|
|
||||||
|
expect(window.location.href).toBe('/dashboard');
|
||||||
|
window.location = originalLocation;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets isInvalid on error', async () => {
|
||||||
|
axios.post.mockRejectedValue(new Error('401'));
|
||||||
|
|
||||||
|
await store.signIn();
|
||||||
|
|
||||||
|
expect(store.isInvalid).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('logOut', () => {
|
||||||
|
it('clears auth state and navigates to login', () => {
|
||||||
|
store.isLoggedIn = true;
|
||||||
|
store.logOut();
|
||||||
|
|
||||||
|
expect(store.isLoggedIn).toBe(false);
|
||||||
|
expect(store.$router.push).toHaveBeenCalledWith('/login');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getUserData', () => {
|
||||||
|
it('stores user data on success', async () => {
|
||||||
|
axios.get.mockResolvedValue({
|
||||||
|
data: { username: 'testuser', name: 'Test User' },
|
||||||
|
});
|
||||||
|
|
||||||
|
await store.getUserData();
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith('/api/my-account');
|
||||||
|
expect(store.userData).toEqual({
|
||||||
|
username: 'testuser',
|
||||||
|
name: 'Test User',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('checkLogin', () => {
|
||||||
|
it('does not redirect on success', async () => {
|
||||||
|
axios.get.mockResolvedValue({ data: {} });
|
||||||
|
|
||||||
|
await store.checkLogin();
|
||||||
|
|
||||||
|
expect(store.$router.push).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('redirects to login on error', async () => {
|
||||||
|
axios.get.mockRejectedValue(new Error('401'));
|
||||||
|
|
||||||
|
await store.checkLogin();
|
||||||
|
|
||||||
|
expect(store.$router.push).toHaveBeenCalledWith('/login');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setRememberedReturnToUrl stores URL', () => {
|
||||||
|
store.setRememberedReturnToUrl('abc');
|
||||||
|
expect(store.rememberedReturnToUrl).toBe('abc');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setIsLoggedIn sets boolean', () => {
|
||||||
|
store.setIsLoggedIn(true);
|
||||||
|
expect(store.isLoggedIn).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
31
tests/stores/mapCompareStore.test.js
Normal file
31
tests/stores/mapCompareStore.test.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { describe, it, expect, beforeEach } from 'vitest';
|
||||||
|
import { setActivePinia, createPinia } from 'pinia';
|
||||||
|
import useMapCompareStore from '@/stores/mapCompareStore.ts';
|
||||||
|
|
||||||
|
describe('mapCompareStore', () => {
|
||||||
|
let store;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(createPinia());
|
||||||
|
store = useMapCompareStore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has correct default state', () => {
|
||||||
|
expect(store.routeParam).toEqual({
|
||||||
|
primaryType: '',
|
||||||
|
primaryId: '',
|
||||||
|
secondaryType: '',
|
||||||
|
secondaryId: '',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setCompareRouteParam sets all params', () => {
|
||||||
|
store.setCompareRouteParam('log', '1', 'filter', '2');
|
||||||
|
expect(store.routeParam).toEqual({
|
||||||
|
primaryType: 'log',
|
||||||
|
primaryId: '1',
|
||||||
|
secondaryType: 'filter',
|
||||||
|
secondaryId: '2',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
30
tests/stores/modal.test.js
Normal file
30
tests/stores/modal.test.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { describe, it, expect, beforeEach } from 'vitest';
|
||||||
|
import { setActivePinia, createPinia } from 'pinia';
|
||||||
|
import { useModalStore } from '@/stores/modal.js';
|
||||||
|
import { MODAL_ACCT_INFO, MODAL_DELETE } from '@/constants/constants.js';
|
||||||
|
|
||||||
|
describe('modalStore', () => {
|
||||||
|
let store;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(createPinia());
|
||||||
|
store = useModalStore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has default state', () => {
|
||||||
|
expect(store.isModalOpen).toBe(false);
|
||||||
|
expect(store.whichModal).toBe(MODAL_ACCT_INFO);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('openModal sets isModalOpen and whichModal', () => {
|
||||||
|
store.openModal(MODAL_DELETE);
|
||||||
|
expect(store.isModalOpen).toBe(true);
|
||||||
|
expect(store.whichModal).toBe(MODAL_DELETE);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('closeModal sets isModalOpen to false', async () => {
|
||||||
|
store.openModal(MODAL_DELETE);
|
||||||
|
await store.closeModal();
|
||||||
|
expect(store.isModalOpen).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
92
tests/stores/pageAdmin.test.js
Normal file
92
tests/stores/pageAdmin.test.js
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
import { describe, it, expect, beforeEach } from 'vitest';
|
||||||
|
import { setActivePinia, createPinia } from 'pinia';
|
||||||
|
import usePageAdminStore from '@/stores/pageAdmin.js';
|
||||||
|
|
||||||
|
describe('pageAdminStore', () => {
|
||||||
|
let store;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(createPinia());
|
||||||
|
store = usePageAdminStore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has correct default state', () => {
|
||||||
|
expect(store.activePage).toBe('MAP');
|
||||||
|
expect(store.previousPage).toBe('MAP');
|
||||||
|
expect(store.pendingActivePage).toBe('FILES');
|
||||||
|
expect(store.isPagePending).toBe(false);
|
||||||
|
expect(store.shouldKeepPreviousPage).toBe(false);
|
||||||
|
expect(store.currentMapFile).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setActivePage converts page name', () => {
|
||||||
|
store.setActivePage('CheckConformance');
|
||||||
|
expect(store.activePage).toBe('CONFORMANCE');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setPrevioiusPage converts page name', () => {
|
||||||
|
store.setPrevioiusPage('CheckPerformance');
|
||||||
|
expect(store.previousPage).toBe('PERFORMANCE');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setPrevioiusPageUsingActivePage copies activePage', () => {
|
||||||
|
store.setActivePage('CONFORMANCE');
|
||||||
|
store.setPrevioiusPageUsingActivePage();
|
||||||
|
// Note: bug in source - writes to this.previoiusPage (typo)
|
||||||
|
// instead of this.previousPage, so previousPage stays 'MAP'
|
||||||
|
expect(store.previousPage).toBe('MAP');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setIsPagePendingBoolean sets boolean', () => {
|
||||||
|
store.setIsPagePendingBoolean(true);
|
||||||
|
expect(store.isPagePending).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setPendingActivePage converts and sets page', () => {
|
||||||
|
store.setPendingActivePage('CheckMap');
|
||||||
|
expect(store.pendingActivePage).toBe('MAP');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('copyPendingPageToActivePage transfers value', () => {
|
||||||
|
store.setPendingActivePage('CheckConformance');
|
||||||
|
store.copyPendingPageToActivePage();
|
||||||
|
expect(store.activePage).toBe('CONFORMANCE');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('clearPendingActivePage resets to empty', () => {
|
||||||
|
store.setPendingActivePage('CheckMap');
|
||||||
|
store.clearPendingActivePage();
|
||||||
|
expect(store.pendingActivePage).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('keepPreviousPage restores previous page', () => {
|
||||||
|
store.setPrevioiusPage('CONFORMANCE');
|
||||||
|
store.setActivePage('PERFORMANCE');
|
||||||
|
store.keepPreviousPage();
|
||||||
|
expect(store.activePage).toBe('CONFORMANCE');
|
||||||
|
expect(store.shouldKeepPreviousPage).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('clearShouldKeepPreviousPageBoolean resets flag', () => {
|
||||||
|
store.keepPreviousPage();
|
||||||
|
store.clearShouldKeepPreviousPageBoolean();
|
||||||
|
expect(store.shouldKeepPreviousPage).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setCurrentMapFile sets file name', () => {
|
||||||
|
store.setCurrentMapFile('test.csv');
|
||||||
|
expect(store.currentMapFile).toBe('test.csv');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setActivePageComputedByRoute extracts route name', () => {
|
||||||
|
const routeMatched = [{ name: 'CheckMap' }];
|
||||||
|
store.setActivePageComputedByRoute(routeMatched);
|
||||||
|
expect(store.activePageComputedByRoute).toBe('MAP');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setActivePageComputedByRoute handles empty array', () => {
|
||||||
|
store.setActivePageComputedByRoute([]);
|
||||||
|
// Should not change default value
|
||||||
|
expect(store.activePageComputedByRoute).toBe('MAP');
|
||||||
|
});
|
||||||
|
});
|
||||||
83
tests/stores/performance.test.js
Normal file
83
tests/stores/performance.test.js
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||||
|
import { setActivePinia, createPinia } from 'pinia';
|
||||||
|
|
||||||
|
vi.mock('@/module/apiError.js', () => ({
|
||||||
|
default: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
import usePerformanceStore from '@/stores/performance.js';
|
||||||
|
|
||||||
|
describe('performanceStore', () => {
|
||||||
|
let store;
|
||||||
|
const mockAxios = {
|
||||||
|
get: vi.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(createPinia());
|
||||||
|
store = usePerformanceStore();
|
||||||
|
store.$axios = mockAxios;
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has correct default state', () => {
|
||||||
|
expect(store.allPerformanceData).toBeNull();
|
||||||
|
expect(store.freqChartData).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('performanceData getter returns allPerformanceData', () => {
|
||||||
|
store.allPerformanceData = { time: {}, freq: {} };
|
||||||
|
expect(store.performanceData).toEqual({ time: {}, freq: {} });
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getPerformance', () => {
|
||||||
|
it('fetches log performance data', async () => {
|
||||||
|
const mockData = { time: { charts: [] }, freq: { charts: [] } };
|
||||||
|
mockAxios.get.mockResolvedValue({ data: mockData });
|
||||||
|
|
||||||
|
await store.getPerformance('log', 1);
|
||||||
|
|
||||||
|
expect(mockAxios.get).toHaveBeenCalledWith(
|
||||||
|
'/api/logs/1/performance',
|
||||||
|
);
|
||||||
|
expect(store.allPerformanceData).toEqual(mockData);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fetches filter performance data', async () => {
|
||||||
|
mockAxios.get.mockResolvedValue({ data: { time: {} } });
|
||||||
|
|
||||||
|
await store.getPerformance('filter', 5);
|
||||||
|
|
||||||
|
expect(mockAxios.get).toHaveBeenCalledWith(
|
||||||
|
'/api/filters/5/performance',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not throw on API failure', async () => {
|
||||||
|
mockAxios.get.mockRejectedValue(new Error('Network error'));
|
||||||
|
|
||||||
|
// Should not throw - apiError handles it
|
||||||
|
await expect(store.getPerformance('log', 1))
|
||||||
|
.resolves.not.toThrow();
|
||||||
|
expect(store.allPerformanceData).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setFreqChartData sets data', () => {
|
||||||
|
const data = { labels: [], datasets: [] };
|
||||||
|
store.setFreqChartData(data);
|
||||||
|
expect(store.freqChartData).toEqual(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setFreqChartOptions sets options', () => {
|
||||||
|
const opts = { responsive: true };
|
||||||
|
store.setFreqChartOptions(opts);
|
||||||
|
expect(store.freqChartOptions).toEqual(opts);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setFreqChartXData sets x data', () => {
|
||||||
|
const xData = { minX: 0, maxX: 100 };
|
||||||
|
store.setFreqChartXData(xData);
|
||||||
|
expect(store.freqChartXData).toEqual(xData);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user