- Add double-click handler to make file names editable in UI - Remove duplicate IPC handler for rename-file in renderer.js - Fix checkEpisodeCountMatch to properly validate sequential episodes - Fix begin-mapping to handle both season folder and show folder cases - Improve open-file-in-player handler to properly log results
319 lines
10 KiB
JavaScript
319 lines
10 KiB
JavaScript
// Test renderer business logic and state management
|
|
const { test } = require('node:test');
|
|
const assert = require('node:assert');
|
|
|
|
// Test AppState class
|
|
test('AppState - should initialize with default values', () => {
|
|
const AppState = require('./utils/renderer/AppState');
|
|
const state = new AppState();
|
|
|
|
assert.strictEqual(state.getCurrentDirectory(), null);
|
|
assert.deepStrictEqual(state.getCurrentFiles(), []);
|
|
assert.strictEqual(state.getCurrentShow(), null);
|
|
assert.deepStrictEqual(state.getCurrentSeasons(), []);
|
|
assert.deepStrictEqual(state.getCurrentEpisodes(), []);
|
|
assert.strictEqual(state.getSelectedSeasonEpisodeCount(), 0);
|
|
assert.strictEqual(state.isUpdatingEpisodeNumbers, false); // property, not method
|
|
});
|
|
|
|
test('AppState - should set and get directory', () => {
|
|
const AppState = require('./utils/renderer/AppState');
|
|
const state = new AppState();
|
|
|
|
state.setCurrentDirectory('/test/path');
|
|
assert.strictEqual(state.getCurrentDirectory(), '/test/path');
|
|
});
|
|
|
|
test('AppState - should set and get files', () => {
|
|
const AppState = require('./utils/renderer/AppState');
|
|
const state = new AppState();
|
|
|
|
const files = [{ path: '/test/file.mp4', name: 'file.mp4' }];
|
|
state.setCurrentFiles(files);
|
|
assert.deepStrictEqual(state.getCurrentFiles(), files);
|
|
});
|
|
|
|
test('AppState - should set and get show', () => {
|
|
const AppState = require('./utils/renderer/AppState');
|
|
const state = new AppState();
|
|
|
|
const show = { id: 'series-123', name: 'Test Show' };
|
|
state.setCurrentShow(show);
|
|
assert.deepStrictEqual(state.getCurrentShow(), show);
|
|
});
|
|
|
|
test('AppState - should reset state', () => {
|
|
const AppState = require('./utils/renderer/AppState');
|
|
const state = new AppState();
|
|
|
|
state.setCurrentDirectory('/test/path');
|
|
state.setCurrentFiles([{ path: '/test/file.mp4' }]);
|
|
state.setCurrentShow({ id: 'series-123' });
|
|
state.reset();
|
|
|
|
assert.strictEqual(state.getCurrentDirectory(), null);
|
|
assert.deepStrictEqual(state.getCurrentFiles(), []);
|
|
assert.strictEqual(state.getCurrentShow(), null);
|
|
});
|
|
|
|
// Test EpisodeManager business logic
|
|
test('EpisodeManager - should get episode range from element', () => {
|
|
const EpisodeManager = require('./utils/renderer/EpisodeManager');
|
|
const manager = new EpisodeManager();
|
|
|
|
const mockElement = {
|
|
dataset: {
|
|
episodeStart: '5',
|
|
episodeEnd: '7'
|
|
}
|
|
};
|
|
|
|
const range = manager.getEpisodeRange(mockElement);
|
|
assert.strictEqual(range.start, 5);
|
|
assert.strictEqual(range.end, 7);
|
|
});
|
|
|
|
test('EpisodeManager - should default to single episode', () => {
|
|
const EpisodeManager = require('./utils/renderer/EpisodeManager');
|
|
const manager = new EpisodeManager();
|
|
|
|
const mockElement = {
|
|
dataset: {}
|
|
};
|
|
|
|
const range = manager.getEpisodeRange(mockElement);
|
|
assert.strictEqual(range.start, 1);
|
|
assert.strictEqual(range.end, 1);
|
|
});
|
|
|
|
test('EpisodeManager - should calculate total episode count', () => {
|
|
const EpisodeManager = require('./utils/renderer/EpisodeManager');
|
|
const manager = new EpisodeManager();
|
|
|
|
// Create mock episode element that querySelector can find
|
|
const mockEpisodeEl1 = {
|
|
dataset: {
|
|
episodeStart: '1',
|
|
episodeEnd: '3'
|
|
}
|
|
};
|
|
const mockEpisodeEl2 = {
|
|
dataset: {
|
|
episodeStart: '4',
|
|
episodeEnd: '5'
|
|
}
|
|
};
|
|
|
|
// Mock file items with querySelector method
|
|
const mockFile1 = {
|
|
querySelector: (selector) => {
|
|
if (selector === '.episode-number') return mockEpisodeEl1;
|
|
return null;
|
|
}
|
|
};
|
|
const mockFile2 = {
|
|
querySelector: (selector) => {
|
|
if (selector === '.episode-number') return mockEpisodeEl2;
|
|
return null;
|
|
}
|
|
};
|
|
|
|
const mockFileList = {
|
|
querySelectorAll: () => [mockFile1, mockFile2]
|
|
};
|
|
|
|
const total = manager.calculateTotalEpisodeCount(mockFileList);
|
|
assert.strictEqual(total, 5); // 3 + 2
|
|
});
|
|
|
|
test('EpisodeManager - should get last episode end', () => {
|
|
const AppState = require('./utils/renderer/AppState');
|
|
const state = new AppState();
|
|
|
|
// Test the property exists
|
|
assert.strictEqual(typeof state.isUpdatingEpisodeNumbers, 'boolean');
|
|
});
|
|
|
|
// Test TagManager business logic
|
|
test('TagManager - should have tag colors', () => {
|
|
const TagManager = require('./utils/renderer/TagManager');
|
|
const manager = new TagManager();
|
|
|
|
assert.strictEqual(manager.tagColors.extra, '#28a745');
|
|
assert.strictEqual(manager.tagColors['behind-the-scenes'], '#17a2b8');
|
|
assert.strictEqual(manager.tagColors.delete, '#dc3545');
|
|
});
|
|
|
|
test('TagManager - should identify tag types', () => {
|
|
const TagManager = require('./utils/renderer/TagManager');
|
|
const manager = new TagManager();
|
|
|
|
assert.ok(manager.tagColors['extra'], 'Should have extra tag color');
|
|
assert.ok(manager.tagColors['behind-the-scenes'], 'Should have behind-the-scenes tag color');
|
|
assert.ok(manager.tagColors['delete'], 'Should have delete tag color');
|
|
});
|
|
|
|
// Test FileManager business logic
|
|
test('FileManager - should have all required methods', () => {
|
|
const FileManager = require('./utils/renderer/FileManager');
|
|
const manager = new FileManager();
|
|
|
|
assert.strictEqual(typeof manager.selectDirectory, 'function');
|
|
assert.strictEqual(typeof manager.scanDirectory, 'function');
|
|
assert.strictEqual(typeof manager.renameFile, 'function');
|
|
assert.strictEqual(typeof manager.beginMapping, 'function');
|
|
assert.strictEqual(typeof manager.logAuditEvent, 'function');
|
|
assert.strictEqual(typeof manager.moveFileToFolder, 'function');
|
|
assert.strictEqual(typeof manager.logFileInfo, 'function');
|
|
});
|
|
|
|
test('FileManager - should collect file data with episode ranges', () => {
|
|
const FileManager = require('./utils/renderer/FileManager');
|
|
const manager = new FileManager();
|
|
|
|
// Test the method exists
|
|
assert.strictEqual(typeof manager.collectFileData, 'function');
|
|
});
|
|
|
|
// Test SearchManager business logic
|
|
test('SearchManager - should initialize with default values', () => {
|
|
const SearchManager = require('./utils/renderer/SearchManager');
|
|
|
|
// Create mock elements
|
|
const mockInput = { value: '' };
|
|
const mockResults = { innerHTML: '' };
|
|
|
|
const manager = new SearchManager(mockInput, mockResults);
|
|
|
|
assert.strictEqual(manager.currentShow, null);
|
|
});
|
|
|
|
test('SearchManager - should clear search results', () => {
|
|
const SearchManager = require('./utils/renderer/SearchManager');
|
|
|
|
const mockInput = { value: '' };
|
|
const mockResults = { innerHTML: '' };
|
|
|
|
const manager = new SearchManager(mockInput, mockResults);
|
|
|
|
assert.strictEqual(typeof manager.clearSearchResults, 'function');
|
|
});
|
|
|
|
// Test ProgressManager business logic
|
|
test('ProgressManager - should show progress', () => {
|
|
const ProgressManager = require('./utils/renderer/ProgressManager');
|
|
|
|
const mockContainer = { style: { display: '' } };
|
|
const mockText = { textContent: '' };
|
|
const mockCount = { textContent: '' };
|
|
|
|
const manager = new ProgressManager(mockContainer, mockText, mockCount);
|
|
|
|
assert.strictEqual(typeof manager.showProgress, 'function');
|
|
});
|
|
|
|
test('ProgressManager - should hide progress', () => {
|
|
const ProgressManager = require('./utils/renderer/ProgressManager');
|
|
|
|
const mockContainer = { style: { display: '' } };
|
|
const mockText = { textContent: '' };
|
|
const mockCount = { textContent: '' };
|
|
|
|
const manager = new ProgressManager(mockContainer, mockText, mockCount);
|
|
|
|
assert.strictEqual(typeof manager.hideProgress, 'function');
|
|
});
|
|
|
|
// Test UIManager business logic
|
|
test('UIManager - should initialize all managers', () => {
|
|
const UIManager = require('./utils/renderer/UIManager');
|
|
|
|
// Verify UIManager exists and is a class
|
|
assert.strictEqual(typeof UIManager, 'function');
|
|
assert.strictEqual(UIManager.name, 'UIManager');
|
|
});
|
|
|
|
// Skip UIManager constructor test in Node.js environment (requires DOM)
|
|
test('UIManager - should have all required methods', () => {
|
|
// Mock Electron ipcRenderer
|
|
const mockIpcRenderer = {
|
|
on: () => {},
|
|
invoke: () => ({ success: true })
|
|
};
|
|
|
|
// Mock window object
|
|
const mockWindow = {
|
|
addEventListener: () => {}
|
|
};
|
|
|
|
// Mock document with required elements
|
|
const mockDocument = {
|
|
getElementById: (id) => {
|
|
// Return mock elements for required IDs
|
|
const mockElement = {
|
|
addEventListener: () => {},
|
|
style: {},
|
|
textContent: '',
|
|
innerHTML: '',
|
|
querySelector: () => null,
|
|
querySelectorAll: () => [],
|
|
classList: { add: () => {}, remove: () => {} },
|
|
dataset: {},
|
|
hasAttribute: () => false,
|
|
setAttribute: () => {},
|
|
removeAttribute: () => {}
|
|
};
|
|
return mockElement;
|
|
},
|
|
querySelectorAll: (selector) => [],
|
|
addEventListener: () => {},
|
|
body: {
|
|
appendChild: () => {}
|
|
}
|
|
};
|
|
|
|
// Store original require cache entries
|
|
const originalRequireCache = { ...require.cache };
|
|
|
|
// Create mock electron module
|
|
const mockElectronModule = {
|
|
ipcRenderer: mockIpcRenderer
|
|
};
|
|
|
|
// Create mock window module (empty, just for completeness)
|
|
const mockWindowModule = {};
|
|
|
|
// Temporarily replace require cache for electron and window
|
|
const electronRequirePath = require.resolve('electron');
|
|
require.cache[electronRequirePath] = {
|
|
exports: mockElectronModule
|
|
};
|
|
|
|
// Temporarily replace document and window globals
|
|
const originalDocument = global.document;
|
|
const originalWindow = global.window;
|
|
global.document = mockDocument;
|
|
global.window = mockWindow;
|
|
|
|
try {
|
|
// Clear the UIManager module cache to force re-require with mocked dependencies
|
|
delete require.cache[require.resolve('./utils/renderer/UIManager')];
|
|
|
|
const UIManager = require('./utils/renderer/UIManager');
|
|
const uiManager = new UIManager();
|
|
|
|
// Check that key methods exist
|
|
assert.strictEqual(typeof uiManager.selectDirectory, 'function');
|
|
assert.strictEqual(typeof uiManager.scanDirectory, 'function');
|
|
assert.strictEqual(typeof uiManager.searchShows, 'function');
|
|
assert.strictEqual(typeof uiManager.beginMapping, 'function');
|
|
} finally {
|
|
// Restore original require cache
|
|
require.cache = originalRequireCache;
|
|
// Restore original globals
|
|
global.document = originalDocument;
|
|
global.window = originalWindow;
|
|
}
|
|
});
|
|
|
|
console.log('\n✅ All renderer business logic tests passed!'); |