- 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
191 lines
6.3 KiB
JavaScript
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);
|
|
});
|
|
});
|
|
});
|