MovieMapper/tests/AppState.test.js
Jarian Cottingham 9b6e90ce0e test: add Vitest suite with 86% coverage threshold
- Add Vitest + jsdom test framework with V8 coverage
- 118 tests across 7 test files covering AppState, ProgressManager, EpisodeManager, FileListManager, fileUtils, main.js logic, renderer escapeHtml, preload module polyfill
- Fix async bug in extractFileDuration (await in non-async callback)
- CI enforces 85% coverage threshold on testable modules
- Exclude Electron IPC wrappers (FileManager, SearchManager, TagManager, ModalManager, UIManager) from coverage as they require Electron runtime
2026-07-06 04:54:40 +00:00

191 lines
6.3 KiB
JavaScript

import { describe, it, expect, vi, beforeEach } from 'vitest';
import AppState from '../utils/renderer/AppState';
describe('AppState', () => {
let state;
beforeEach(() => {
state = new AppState();
});
describe('constructor', () => {
it('initializes with default values', () => {
expect(state.getCurrentDirectory()).toBeNull();
expect(state.getCurrentFiles()).toEqual([]);
expect(state.getCurrentShow()).toBeNull();
expect(state.getCurrentSeasons()).toEqual([]);
expect(state.getCurrentEpisodes()).toEqual([]);
expect(state.getSelectedSeasonEpisodeCount()).toBe(0);
expect(state.isUpdatingEpisodeNumbers).toBe(false);
expect(state.getNavigationStack()).toEqual([]);
expect(state.getNavigationDepth()).toBe(0);
});
});
describe('currentDirectory', () => {
it('sets and gets directory', () => {
state.setCurrentDirectory('/path/to/dir');
expect(state.getCurrentDirectory()).toBe('/path/to/dir');
});
it('overwrites previous directory', () => {
state.setCurrentDirectory('/path/one');
state.setCurrentDirectory('/path/two');
expect(state.getCurrentDirectory()).toBe('/path/two');
});
});
describe('currentFiles', () => {
it('sets and gets files array', () => {
const files = [{ name: 'file1.mp4' }, { name: 'file2.mp4' }];
state.setCurrentFiles(files);
expect(state.getCurrentFiles()).toEqual(files);
});
it('handles empty array', () => {
state.setCurrentFiles([]);
expect(state.getCurrentFiles()).toEqual([]);
});
});
describe('currentShow', () => {
it('sets and gets show object', () => {
const show = { id: 'series-12345', name: 'Test Show' };
state.setCurrentShow(show);
expect(state.getCurrentShow()).toEqual(show);
});
});
describe('currentSeasons', () => {
it('sets and gets seasons array', () => {
const seasons = [{ number: 1 }, { number: 2 }];
state.setCurrentSeasons(seasons);
expect(state.getCurrentSeasons()).toEqual(seasons);
});
});
describe('currentEpisodes', () => {
it('sets and gets episodes array', () => {
const episodes = [{ number: 1 }, { number: 2 }];
state.setCurrentEpisodes(episodes);
expect(state.getCurrentEpisodes()).toEqual(episodes);
});
});
describe('selectedSeasonEpisodeCount', () => {
it('sets and gets episode count', () => {
state.setSelectedSeasonEpisodeCount(13);
expect(state.getSelectedSeasonEpisodeCount()).toBe(13);
});
});
describe('updatingEpisodeNumbers', () => {
it('sets and gets updating flag', () => {
state.setUpdatingEpisodeNumbers(true);
expect(state.isUpdatingEpisodeNumbers).toBe(true);
state.setUpdatingEpisodeNumbers(false);
expect(state.isUpdatingEpisodeNumbers).toBe(false);
});
});
describe('reset', () => {
it('resets all state to defaults', () => {
state.setCurrentDirectory('/path/to/dir');
state.setCurrentFiles([{ name: 'file.mp4' }]);
state.setCurrentShow({ name: 'Show' });
state.setCurrentSeasons([{ number: 1 }]);
state.setCurrentEpisodes([{ number: 1 }]);
state.setSelectedSeasonEpisodeCount(10);
state.setUpdatingEpisodeNumbers(true);
state.addToNavigationStack('/path/to/dir');
state.reset();
expect(state.getCurrentDirectory()).toBeNull();
expect(state.getCurrentFiles()).toEqual([]);
expect(state.getCurrentShow()).toBeNull();
expect(state.getCurrentSeasons()).toEqual([]);
expect(state.getCurrentEpisodes()).toEqual([]);
expect(state.getSelectedSeasonEpisodeCount()).toBe(0);
expect(state.isUpdatingEpisodeNumbers).toBe(false);
expect(state.getNavigationStack()).toEqual([]);
expect(state.getNavigationDepth()).toBe(0);
});
});
describe('navigationStack', () => {
it('adds directories to stack', () => {
state.addToNavigationStack('/home');
expect(state.getNavigationStack()).toEqual(['/home']);
expect(state.getNavigationDepth()).toBe(0);
});
it('supports multiple navigation levels', () => {
state.addToNavigationStack('/home');
state.addToNavigationStack('/home/movies');
state.addToNavigationStack('/home/movies/show');
expect(state.getNavigationStack().length).toBe(3);
expect(state.getNavigationDepth()).toBe(2);
});
it('returns current directory from stack', () => {
state.addToNavigationStack('/home');
state.addToNavigationStack('/home/movies');
expect(state.getCurrentDirectoryFromStack()).toBe('/home/movies');
});
it('returns null when stack is empty', () => {
expect(state.getCurrentDirectoryFromStack()).toBeNull();
});
it('truncates forward history on new navigation', () => {
state.addToNavigationStack('/home');
state.addToNavigationStack('/home/movies');
state.goBack();
state.addToNavigationStack('/home/photos');
expect(state.getNavigationStack()).toEqual(['/home', '/home/photos']);
});
it('goes back to previous directory', () => {
state.addToNavigationStack('/home');
state.addToNavigationStack('/home/movies');
const result = state.goBack();
expect(result).toBe('/home');
});
it('returns null when cannot go back', () => {
state.addToNavigationStack('/home');
const result = state.goBack();
expect(result).toBeNull();
});
it('returns null on empty stack goBack', () => {
const result = state.goBack();
expect(result).toBeNull();
});
it('canGoBack returns correct state', () => {
expect(state.canGoBack()).toBe(false);
state.addToNavigationStack('/home');
expect(state.canGoBack()).toBe(false);
state.addToNavigationStack('/home/movies');
expect(state.canGoBack()).toBe(true);
});
it('canGoBack becomes false after going back to root', () => {
state.addToNavigationStack('/home');
state.addToNavigationStack('/home/movies');
state.goBack();
expect(state.canGoBack()).toBe(false);
});
it('handles deep navigation', () => {
for (let i = 1; i <= 5; i++) {
state.addToNavigationStack(`/level${i}`);
}
expect(state.getNavigationDepth()).toBe(4);
expect(state.getNavigationStack().length).toBe(5);
});
});
});