ui_migration feature(unitesting) modifying vitest config and spec, add test id flags to component
This commit is contained in:
parent
c7d16fa43f
commit
9968978a7b
3 changed files with 90 additions and 28 deletions
|
|
@ -17,6 +17,7 @@
|
|||
class="uk-button uk-button-default uk-width-1-1"
|
||||
type="button"
|
||||
@click="updateLogs()"
|
||||
data-test-id="update-btn"
|
||||
>
|
||||
Refresh Logs
|
||||
</button>
|
||||
|
|
@ -27,6 +28,7 @@
|
|||
:url="logFileURI"
|
||||
button-label="Download Log File"
|
||||
:button-primary="false"
|
||||
data-test-id="download-btn"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,24 +2,40 @@ import { shallowMount, flushPromises } from "@vue/test-utils";
|
|||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { createTestingPinia } from "@pinia/testing";
|
||||
import axios from "axios";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import LoggingContent from "../../components/tabContentComponents/loggingContent.vue";
|
||||
|
||||
// Mock Axios
|
||||
vi.mock("axios");
|
||||
vi.mock("axios", () => {
|
||||
return {
|
||||
default: {
|
||||
get: vi.fn(),
|
||||
post: vi.fn(),
|
||||
put: vi.fn(),
|
||||
delete: vi.fn(),
|
||||
patch: vi.fn(),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
// Mock VueUse to prevent IntersectionObserver crashes in JSDOM
|
||||
// This will be removed once vue-route is implemented
|
||||
vi.mock("@vueuse/core", () => ({
|
||||
useIntersectionObserver: vi.fn(() => ({
|
||||
stop: vi.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
describe("LoggingContent.vue", () => {
|
||||
// Test Description
|
||||
describe("Test LoggingContent.vue", () => {
|
||||
let wrapper;
|
||||
|
||||
// A sample log string matching backend's format
|
||||
const mockLogData = `[2026-05-14 08:46:12,808] [INFO] OFM server root logger has been set up at INFO level`;
|
||||
// Define path to a real log file and read it
|
||||
const logFilePath = path.resolve(__dirname, "../fixtures/realLog.txt");
|
||||
const mockLogData = fs.readFileSync(logFilePath, "utf-8");
|
||||
|
||||
// Things to do before each test
|
||||
beforeEach(async () => {
|
||||
// Reset mocks before each test
|
||||
vi.clearAllMocks();
|
||||
|
|
@ -41,22 +57,32 @@ describe("LoggingContent.vue", () => {
|
|||
],
|
||||
// Simplify child components
|
||||
stubs: {
|
||||
PaginateLinks: true,
|
||||
EndpointButton: true,
|
||||
transition: false,
|
||||
teleport: true,
|
||||
},
|
||||
PaginateLinks: true,
|
||||
EndpointButton: true,
|
||||
transition: true,
|
||||
teleport: true,
|
||||
settings: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
await flushPromises();
|
||||
// flush so we avoid leaving uncompleted processes running on background
|
||||
await flushPromises();
|
||||
});
|
||||
|
||||
// Render check
|
||||
it("renders the component correctly", () => {
|
||||
// Tear down wrapper, unmount testing component
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
// Test 1: Render check, if things do exist in the page as intended
|
||||
it("renders the component correctly", async () => {
|
||||
// Check if component is been loaded and it is rendered
|
||||
expect(wrapper.exists()).toBe(true);
|
||||
// Check if navbar exists
|
||||
expect(wrapper.find(".logging-navbar").exists()).toBe(true);
|
||||
});
|
||||
|
||||
// Test 2: Check log parsing to see if specific INFO exists
|
||||
it("fetches logs and parses them correctly when updateLogs is called", async () => {
|
||||
// Trigger the method
|
||||
await wrapper.vm.updateLogs();
|
||||
|
|
@ -65,28 +91,60 @@ describe("LoggingContent.vue", () => {
|
|||
// Verify Axios was called with the correct URI from the Pinia store
|
||||
expect(axios.get).toHaveBeenCalledWith("http://microscope.local:5000/api/v3/log/");
|
||||
|
||||
// Verify the logs array was populated and reversed (newest first)
|
||||
expect(wrapper.vm.logs.length).toBe(1);
|
||||
// Verify the logs have correct file length
|
||||
// Helps validate formatting, etc
|
||||
expect(wrapper.vm.logs.length).toBe(5491);
|
||||
|
||||
// Check if the most recent log (ERROR) is first due to .reverse()
|
||||
// Check the most recent log
|
||||
expect(wrapper.vm.logs[0].level).toBe("INFO");
|
||||
|
||||
// Check if the multi-line traceback was appended correctly to the ERROR log
|
||||
expect(wrapper.vm.logs[0].message).toContain("OFM");
|
||||
expect(wrapper.vm.logs[0].summary).toContain("server");
|
||||
// Check if the multi-line file has real first connection information
|
||||
expect(wrapper.vm.logs[0].message).toContain("uvicorn");
|
||||
expect(wrapper.vm.logs[0].summary).toContain("http://0.0.0.0:5000");
|
||||
});
|
||||
|
||||
// Test 3: Filter logging file information
|
||||
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 = "INFO";
|
||||
|
||||
// wait for Vue reactivity to update computed properties
|
||||
// Set filter to WARNING wait and compare expected length
|
||||
wrapper.vm.filterLevel = "WARNING";
|
||||
await wrapper.vm.$nextTick();
|
||||
expect(wrapper.vm.filteredItems.length).toBe(1449);
|
||||
expect(wrapper.vm.filteredItems[0].level).toBe("WARNING");
|
||||
|
||||
// Only the 1 ERROR log should remain in filteredItems
|
||||
expect(wrapper.vm.filteredItems.length).toBe(1);
|
||||
// Set filter to INFO wait and compare expected length
|
||||
wrapper.vm.filterLevel = "INFO";
|
||||
await wrapper.vm.$nextTick();
|
||||
expect(wrapper.vm.filteredItems.length).toBe(5491);
|
||||
expect(wrapper.vm.filteredItems[0].level).toBe("INFO");
|
||||
|
||||
// Set filter to ERROR wait and compare expected length
|
||||
wrapper.vm.filterLevel = "ERROR";
|
||||
await wrapper.vm.$nextTick();
|
||||
expect(wrapper.vm.filteredItems.length).toBe(7);
|
||||
expect(wrapper.vm.filteredItems[0].level).toBe("ERROR");
|
||||
});
|
||||
|
||||
// Test 4: Click buttons
|
||||
// This required the component file to be modified by adding data-test-id flags.
|
||||
// flags are needed as classes and text content may change by translation or style change.
|
||||
it("click buttons", async () => {
|
||||
// Click download button
|
||||
const downloadButton = wrapper.find('[data-test-id="download-btn"]');
|
||||
expect(downloadButton.exists()).toBe(true);
|
||||
await downloadButton.trigger("click");
|
||||
|
||||
// Click update button
|
||||
const updateButton = wrapper.find('[data-test-id="update-btn"]');
|
||||
expect(updateButton.exists()).toBe(true);
|
||||
await updateButton.trigger("click");
|
||||
});
|
||||
|
||||
// Test 5: Compare downloaded file to fixture file.
|
||||
// Test 6: WIP
|
||||
|
||||
afterAll(async () => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 15));
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,16 +5,18 @@ import { defineConfig } from "vitest/config";
|
|||
import vue from "@vitejs/plugin-vue";
|
||||
import path from "path";
|
||||
|
||||
console.log("\n\n::: Reading vitest config.")
|
||||
console.log("\n\n::: Reading vitest config.");
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [vue({
|
||||
plugins: [
|
||||
vue({
|
||||
template: {
|
||||
compilerOptions: {
|
||||
hoistStatic: false,
|
||||
},
|
||||
},
|
||||
})],
|
||||
}),
|
||||
],
|
||||
|
||||
test: {
|
||||
environment: "jsdom",
|
||||
|
|
@ -31,7 +33,7 @@ export default defineConfig({
|
|||
resolve: {
|
||||
alias: {
|
||||
"@": path.resolve(__dirname, "./src"),
|
||||
"vue": path.resolve(__dirname, "./node_modules/vue"),
|
||||
vue: path.resolve(__dirname, "./node_modules/vue"),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue