280 lines
8.2 KiB
JavaScript
280 lines
8.2 KiB
JavaScript
/**
|
|
* GamemasterExplorer View Tests
|
|
* Integration tests verifying the refactored component works correctly
|
|
*/
|
|
|
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
import { mount } from '@vue/test-utils';
|
|
import { ref } from 'vue';
|
|
import GamemasterExplorer from '../../../src/views/GamemasterExplorer.vue';
|
|
|
|
// Mock composables
|
|
vi.mock('../../../src/composables/useGamemasterFiles.js', () => ({
|
|
useGamemasterFiles: vi.fn(() => ({
|
|
selectedFile: ref('pokemon.json'),
|
|
fileContent: ref('{"test": "data"}'),
|
|
fileLines: ref(['{', ' "test": "data"', '}']),
|
|
displayLines: ref(['{', ' "test": "data"', '}']),
|
|
isLoading: ref(false),
|
|
fileError: ref(null),
|
|
preferences: ref({
|
|
lineWrap: false,
|
|
darkMode: false,
|
|
showLineNumbers: true,
|
|
performanceMode: 'auto'
|
|
}),
|
|
hasFiles: ref(true),
|
|
fileTooLarge: ref(false),
|
|
loadStatus: vi.fn(),
|
|
formatSize: vi.fn(size => `${size} B`),
|
|
formatFileName: vi.fn(name => name),
|
|
getFileType: vi.fn(name => name.replace('.json', ''))
|
|
}))
|
|
}));
|
|
|
|
vi.mock('../../../src/composables/useGamemasterSearch.js', () => ({
|
|
useGamemasterSearch: vi.fn(() => ({
|
|
searchQuery: ref(''),
|
|
searchResults: ref([]),
|
|
currentResultIndex: ref(-1),
|
|
isSearching: ref(false),
|
|
searchError: ref(null),
|
|
executeSearch: vi.fn(),
|
|
clearSearch: vi.fn(),
|
|
goToNextResult: vi.fn(),
|
|
goToPrevResult: vi.fn()
|
|
}))
|
|
}));
|
|
|
|
vi.mock('../../../src/composables/useLineSelection.js', () => ({
|
|
useLineSelection: vi.fn(() => ({
|
|
selectedLines: ref(new Set()),
|
|
hasSelection: ref(false),
|
|
selectionCount: ref(0),
|
|
toggleLineSelection: vi.fn(),
|
|
clearSelection: vi.fn(),
|
|
selectAll: vi.fn(),
|
|
copySelected: vi.fn(),
|
|
exportSelected: vi.fn()
|
|
}))
|
|
}));
|
|
|
|
vi.mock('../../../src/composables/useJsonFilter.js', () => ({
|
|
default: vi.fn(() => ({
|
|
filterProperty: ref(''),
|
|
filterValue: ref(''),
|
|
filterMode: ref('equals'),
|
|
filteredData: ref([]),
|
|
setFilter: vi.fn(),
|
|
clearFilters: vi.fn(),
|
|
getUniqueValues: vi.fn(() => [])
|
|
}))
|
|
}));
|
|
|
|
vi.mock('../../../src/composables/useKeyboardShortcuts.js', () => ({
|
|
useKeyboardShortcuts: vi.fn()
|
|
}));
|
|
|
|
vi.mock('../../../src/composables/useUrlState.js', () => ({
|
|
useUrlState: vi.fn()
|
|
}));
|
|
|
|
vi.mock('../../../src/composables/useClipboard.js', () => ({
|
|
useClipboard: vi.fn(() => ({
|
|
copied: ref(false),
|
|
error: ref(null),
|
|
copy: vi.fn()
|
|
}))
|
|
}));
|
|
|
|
vi.mock('../../../src/utilities/gamemaster-client.js', () => ({
|
|
GamemasterClient: vi.fn(() => ({
|
|
getStatus: vi.fn(),
|
|
getFile: vi.fn()
|
|
}))
|
|
}));
|
|
|
|
describe('GamemasterExplorer', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
it('renders successfully', () => {
|
|
const wrapper = mount(GamemasterExplorer);
|
|
expect(wrapper.exists()).toBe(true);
|
|
});
|
|
|
|
it('shows loading state when isLoading is true', () => {
|
|
const { useGamemasterFiles } = await import(
|
|
'../../../src/composables/useGamemasterFiles.js'
|
|
);
|
|
useGamemasterFiles.mockReturnValueOnce({
|
|
selectedFile: ref(''),
|
|
fileContent: ref(''),
|
|
fileLines: ref([]),
|
|
displayLines: ref([]),
|
|
isLoading: ref(true),
|
|
fileError: ref(null),
|
|
preferences: ref({}),
|
|
hasFiles: ref(false),
|
|
fileTooLarge: ref(false),
|
|
loadStatus: vi.fn()
|
|
});
|
|
|
|
const wrapper = mount(GamemasterExplorer);
|
|
expect(wrapper.find('.loading-state').exists()).toBe(true);
|
|
expect(wrapper.text()).toContain('Loading Gamemaster Explorer');
|
|
});
|
|
|
|
it('shows error state when fileError exists', () => {
|
|
const { useGamemasterFiles } = await import(
|
|
'../../../src/composables/useGamemasterFiles.js'
|
|
);
|
|
useGamemasterFiles.mockReturnValueOnce({
|
|
selectedFile: ref(''),
|
|
fileContent: ref(''),
|
|
fileLines: ref([]),
|
|
displayLines: ref([]),
|
|
isLoading: ref(false),
|
|
fileError: ref('Failed to load files'),
|
|
preferences: ref({}),
|
|
hasFiles: ref(false),
|
|
fileTooLarge: ref(false),
|
|
loadStatus: vi.fn()
|
|
});
|
|
|
|
const wrapper = mount(GamemasterExplorer);
|
|
expect(wrapper.find('.error-state').exists()).toBe(true);
|
|
expect(wrapper.text()).toContain('Failed to load files');
|
|
});
|
|
|
|
it('shows no files state when hasFiles is false', () => {
|
|
const { useGamemasterFiles } = await import(
|
|
'../../../src/composables/useGamemasterFiles.js'
|
|
);
|
|
useGamemasterFiles.mockReturnValueOnce({
|
|
selectedFile: ref(''),
|
|
fileContent: ref(''),
|
|
fileLines: ref([]),
|
|
displayLines: ref([]),
|
|
isLoading: ref(false),
|
|
fileError: ref(null),
|
|
preferences: ref({}),
|
|
hasFiles: ref(false),
|
|
fileTooLarge: ref(false),
|
|
loadStatus: vi.fn()
|
|
});
|
|
|
|
const wrapper = mount(GamemasterExplorer);
|
|
expect(wrapper.find('.no-files-state').exists()).toBe(true);
|
|
expect(wrapper.text()).toContain('No Gamemaster Files Available');
|
|
});
|
|
|
|
it('renders main explorer interface when files are loaded', () => {
|
|
const wrapper = mount(GamemasterExplorer);
|
|
expect(wrapper.find('.explorer-container').exists()).toBe(true);
|
|
expect(wrapper.find('.explorer-header').exists()).toBe(true);
|
|
expect(wrapper.text()).toContain('Gamemaster Explorer');
|
|
});
|
|
|
|
it('includes all child components', () => {
|
|
const wrapper = mount(GamemasterExplorer);
|
|
|
|
// Check for FileSelector component
|
|
expect(wrapper.findComponent({ name: 'FileSelector' }).exists()).toBe(true);
|
|
|
|
// Check for SearchBar component
|
|
expect(wrapper.findComponent({ name: 'SearchBar' }).exists()).toBe(true);
|
|
|
|
// Check for FilterPanel component
|
|
expect(wrapper.findComponent({ name: 'FilterPanel' }).exists()).toBe(true);
|
|
|
|
// Check for JsonViewer component
|
|
expect(wrapper.findComponent({ name: 'JsonViewer' }).exists()).toBe(true);
|
|
|
|
// Check for ActionToolbar component
|
|
expect(wrapper.findComponent({ name: 'ActionToolbar' }).exists()).toBe(true);
|
|
});
|
|
|
|
it('toggles help panel', async () => {
|
|
const wrapper = mount(GamemasterExplorer);
|
|
|
|
expect(wrapper.find('.help-panel').exists()).toBe(false);
|
|
|
|
// Click help button
|
|
const helpButton = wrapper.findAll('.btn-icon')[0];
|
|
await helpButton.trigger('click');
|
|
|
|
expect(wrapper.find('.help-panel').exists()).toBe(true);
|
|
expect(wrapper.text()).toContain('Keyboard Shortcuts');
|
|
});
|
|
|
|
it('toggles settings panel', async () => {
|
|
const wrapper = mount(GamemasterExplorer);
|
|
|
|
expect(wrapper.find('.settings-panel').exists()).toBe(false);
|
|
|
|
// Click settings button
|
|
const settingsButton = wrapper.findAll('.btn-icon')[1];
|
|
await settingsButton.trigger('click');
|
|
|
|
expect(wrapper.find('.settings-panel').exists()).toBe(true);
|
|
expect(wrapper.text()).toContain('Settings');
|
|
});
|
|
|
|
it('has back to home link', () => {
|
|
const wrapper = mount(GamemasterExplorer);
|
|
const backLink = wrapper.find('.back-button');
|
|
|
|
expect(backLink.exists()).toBe(true);
|
|
expect(backLink.attributes('to')).toBe('/');
|
|
});
|
|
|
|
it('calls loadStatus on mount', () => {
|
|
const { useGamemasterFiles } = await import(
|
|
'../../../src/composables/useGamemasterFiles.js'
|
|
);
|
|
const mockLoadStatus = vi.fn();
|
|
useGamemasterFiles.mockReturnValueOnce({
|
|
selectedFile: ref(''),
|
|
fileContent: ref(''),
|
|
fileLines: ref([]),
|
|
displayLines: ref([]),
|
|
isLoading: ref(false),
|
|
fileError: ref(null),
|
|
preferences: ref({}),
|
|
hasFiles: ref(true),
|
|
fileTooLarge: ref(false),
|
|
loadStatus: mockLoadStatus
|
|
});
|
|
|
|
mount(GamemasterExplorer);
|
|
|
|
// loadStatus should be called on mount
|
|
expect(mockLoadStatus).toHaveBeenCalled();
|
|
});
|
|
|
|
it('computes filterData from fileContent', () => {
|
|
const wrapper = mount(GamemasterExplorer);
|
|
|
|
// Component should parse JSON content for filtering
|
|
const filterData = wrapper.vm.filterData;
|
|
expect(filterData).toBeDefined();
|
|
});
|
|
|
|
it('displays toast messages for clipboard operations', async () => {
|
|
const { useClipboard } = await import(
|
|
'../../../src/composables/useClipboard.js'
|
|
);
|
|
useClipboard.mockReturnValueOnce({
|
|
copied: ref(true),
|
|
error: ref(null),
|
|
copy: vi.fn()
|
|
});
|
|
|
|
const wrapper = mount(GamemasterExplorer);
|
|
expect(wrapper.find('.toast.success').exists()).toBe(true);
|
|
expect(wrapper.text()).toContain('Copied to clipboard');
|
|
});
|
|
});
|