From b07c74d3c1b9a9da9dca79a94c50393f41438284 Mon Sep 17 00:00:00 2001 From: FragginWagon Date: Thu, 29 Jan 2026 03:55:21 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=AA=20Add=20unit=20tests=20for=20JsonV?= =?UTF-8?q?iewer=20component=20in=20gamemaster?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/gamemaster/JsonViewer.test.js | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 code/websites/pokedex.online/tests/unit/components/gamemaster/JsonViewer.test.js diff --git a/code/websites/pokedex.online/tests/unit/components/gamemaster/JsonViewer.test.js b/code/websites/pokedex.online/tests/unit/components/gamemaster/JsonViewer.test.js new file mode 100644 index 0000000..b64182d --- /dev/null +++ b/code/websites/pokedex.online/tests/unit/components/gamemaster/JsonViewer.test.js @@ -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: '
', + props: ['items'] + } + } + } + }); + + expect(wrapper.find('.scroller').exists()).toBe(true); + }); +});