🧪 Add unit tests for JsonViewer component in gamemaster
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* JsonViewer Component Tests
|
||||
* Verifies JSON display and line selection UI
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||
import { mount } from '@vue/test-utils';
|
||||
import { ref } from 'vue';
|
||||
import JsonViewer from '../../../../src/components/gamemaster/JsonViewer.vue';
|
||||
import { useLineSelection } from '../../../../src/composables/useLineSelection.js';
|
||||
|
||||
vi.mock('../../../../src/composables/useLineSelection.js', () => ({
|
||||
useLineSelection: vi.fn()
|
||||
}));
|
||||
|
||||
const createSelectionMock = overrides => ({
|
||||
selectedLines: ref(new Set()),
|
||||
toggleLineSelection: vi.fn(),
|
||||
...overrides
|
||||
});
|
||||
|
||||
describe('JsonViewer Component', () => {
|
||||
let selectionMock;
|
||||
|
||||
beforeEach(() => {
|
||||
selectionMock = createSelectionMock();
|
||||
useLineSelection.mockReturnValue(selectionMock);
|
||||
});
|
||||
|
||||
const baseProps = {
|
||||
displayLines: [
|
||||
{ lineNumber: 1, content: '{', hasMatch: false },
|
||||
{ lineNumber: 2, content: ' "name": "Pikachu"', hasMatch: true }
|
||||
],
|
||||
fileContent: '{\n "name": "Pikachu"\n}',
|
||||
selectedFile: 'pokemon',
|
||||
preferences: { showLineNumbers: true, darkMode: false, lineWrap: false },
|
||||
searchResults: [1],
|
||||
currentResultIndex: 0,
|
||||
highlightConfig: { theme: 'github', language: 'json' },
|
||||
lineHeight: 20
|
||||
};
|
||||
|
||||
it('does not render when fileContent is empty', () => {
|
||||
const wrapper = mount(JsonViewer, {
|
||||
props: { ...baseProps, fileContent: '' }
|
||||
});
|
||||
|
||||
expect(wrapper.find('.content-viewer').exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('renders lines with line numbers', () => {
|
||||
selectionMock.selectedLines.value.add(2);
|
||||
|
||||
const wrapper = mount(JsonViewer, {
|
||||
props: baseProps
|
||||
});
|
||||
|
||||
const lines = wrapper.findAll('.line');
|
||||
expect(lines.length).toBe(2);
|
||||
expect(lines[1].classes()).toContain('selected');
|
||||
expect(wrapper.findAll('.line-number').length).toBe(2);
|
||||
});
|
||||
|
||||
it('calls toggleLineSelection on line click', async () => {
|
||||
const wrapper = mount(JsonViewer, {
|
||||
props: baseProps
|
||||
});
|
||||
|
||||
const lines = wrapper.findAll('.line');
|
||||
await lines[0].trigger('click');
|
||||
|
||||
expect(selectionMock.toggleLineSelection).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('marks the current search result line', () => {
|
||||
const wrapper = mount(JsonViewer, {
|
||||
props: baseProps
|
||||
});
|
||||
|
||||
const current = wrapper.findAll('.line')[1];
|
||||
expect(current.classes()).toContain('current-result');
|
||||
});
|
||||
|
||||
it('shows warning banner when file is too large', () => {
|
||||
const wrapper = mount(JsonViewer, {
|
||||
props: { ...baseProps, fileTooLarge: true }
|
||||
});
|
||||
|
||||
expect(wrapper.find('.warning-banner').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('uses RecycleScroller for large line counts', () => {
|
||||
const largeLines = Array.from({ length: 1001 }, (_, index) => ({
|
||||
lineNumber: index + 1,
|
||||
content: `line ${index + 1}`,
|
||||
hasMatch: false
|
||||
}));
|
||||
|
||||
const wrapper = mount(JsonViewer, {
|
||||
props: {
|
||||
...baseProps,
|
||||
displayLines: largeLines
|
||||
},
|
||||
global: {
|
||||
stubs: {
|
||||
RecycleScroller: {
|
||||
template: '<div class="scroller"><slot :item="items[0]" /></div>',
|
||||
props: ['items']
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper.find('.scroller').exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user