diff --git a/webapp/src/components/tabContentComponents/loggingContent.vue b/webapp/src/components/tabContentComponents/loggingContent.vue index c66eb3f2..1802aa8d 100644 --- a/webapp/src/components/tabContentComponents/loggingContent.vue +++ b/webapp/src/components/tabContentComponents/loggingContent.vue @@ -225,7 +225,7 @@ export default { }, escapeText: function (unsafeText) { let div = document.createElement("div"); - div.innerText = unsafeText; + div.textContent = unsafeText; return div.innerHTML; }, }, diff --git a/webapp/src/tests/unit/LoggingContent.spec.js b/webapp/src/tests/unit/LoggingContent.spec.js index 55ac5027..9faa434d 100644 --- a/webapp/src/tests/unit/LoggingContent.spec.js +++ b/webapp/src/tests/unit/LoggingContent.spec.js @@ -1,22 +1,18 @@ -// File: LoggingContent.spec.js -// Component: loggingContent.vue -// This file mocks AXIOS for simulated requests and VUEUSE as its not standard JSDOM. - -import { mount } from '@vue/test-utils'; -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import { createTestingPinia } from '@pinia/testing'; -import axios from 'axios'; -import LoggingContent from '../../components/tabContentComponents/loggingContent.vue'; +import { mount } from "@vue/test-utils"; +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { createTestingPinia } from "@pinia/testing"; +import axios from "axios"; +import LoggingContent from "../../components/tabContentComponents/loggingContent.vue"; // Mock Axios -vi.mock('axios'); +vi.mock("axios"); // Mock VueUse to prevent IntersectionObserver crashes in JSDOM -vi.mock('@vueuse/core', () => ({ +vi.mock("@vueuse/core", () => ({ useIntersectionObserver: vi.fn(), })); -describe('LoggingContent.vue', () => { +describe("LoggingContent.vue", () => { let wrapper; // A sample log string matching backend's format @@ -29,7 +25,7 @@ describe('LoggingContent.vue', () => { beforeEach(() => { // Reset mocks before each test vi.clearAllMocks(); - + // Set axios to return our fake logs axios.get.mockResolvedValue({ data: mockLogData }); @@ -40,51 +36,51 @@ describe('LoggingContent.vue', () => { createTestingPinia({ createSpy: vi.fn, initialState: { - settings: { baseUri: 'http://localhost:3000/api/v3' } + settings: { baseUri: "http://localhost:3000/api/v3" }, }, }), ], // Simplify child components - stubs: ['PaginateLinks', 'EndpointButton'] + stubs: ["PaginateLinks", "EndpointButton"], }, }); }); // Render check - it('renders the component correctly', () => { + it("renders the component correctly", () => { expect(wrapper.exists()).toBe(true); - expect(wrapper.find('.logging-navbar').exists()).toBe(true); + expect(wrapper.find(".logging-navbar").exists()).toBe(true); }); - it('fetches logs and parses them correctly when updateLogs is called', async () => { + it("fetches logs and parses them correctly when updateLogs is called", async () => { // Trigger the method await wrapper.vm.updateLogs(); // Verify Axios was called with the correct URI from the Pinia store - expect(axios.get).toHaveBeenCalledWith('http://localhost:3000/api/v3/log/'); + expect(axios.get).toHaveBeenCalledWith("http://localhost:3000/api/v3/log/"); // Verify the logs array was populated and reversed (newest first) expect(wrapper.vm.logs.length).toBe(3); - + // Check if the most recent log (ERROR) is first due to .reverse() - expect(wrapper.vm.logs[0].level).toBe('ERROR'); - + expect(wrapper.vm.logs[0].level).toBe("ERROR"); + // Check if the multi-line traceback was appended correctly to the ERROR log - expect(wrapper.vm.logs[0].message).toContain('Traceback'); - expect(wrapper.vm.logs[0].summary).toContain('connect()'); + expect(wrapper.vm.logs[0].message).toContain("Traceback"); + expect(wrapper.vm.logs[0].summary).toContain("connect()"); }); - it('filters logs based on the selected level', async () => { + it("filters logs based on the selected level", async () => { await wrapper.vm.updateLogs(); - + // Set filter to ERROR (should only show ERROR and CRITICAL) - wrapper.vm.filterLevel = 'ERROR'; - + wrapper.vm.filterLevel = "ERROR"; + // wait for Vue reactivity to update computed properties - await wrapper.vm.$nextTick(); - + await wrapper.vm.$nextTick(); + // Only the 1 ERROR log should remain in filteredItems expect(wrapper.vm.filteredItems.length).toBe(1); - expect(wrapper.vm.filteredItems[0].level).toBe('ERROR'); + expect(wrapper.vm.filteredItems[0].level).toBe("ERROR"); }); -}); \ No newline at end of file +}); diff --git a/webapp/vitest.config.js b/webapp/vitest.config.js index 99b2e94e..255ea48f 100644 --- a/webapp/vitest.config.js +++ b/webapp/vitest.config.js @@ -1,23 +1,22 @@ - // File: vitest.config.js // Generic configuration for vitest -import { defineConfig } from 'vitest/config'; -import vue from '@vitejs/plugin-vue'; -import path from 'path'; +import { defineConfig } from "vitest/config"; +import vue from "@vitejs/plugin-vue"; +import path from "path"; export default defineConfig({ plugins: [vue()], test: { - environment: 'jsdom', + environment: "jsdom", globals: true, }, resolve: { alias: { - '@': path.resolve(__dirname, './src'), + "@": path.resolve(__dirname, "./src"), }, }, -}); \ No newline at end of file +});