Setting page

* Switched to eslint.config.ts and demoted @typescript-eslint/no-unused-vars to warning
* Created /settings route, associated component and modified tests for routes
* Added tests for SettingsView.vue
* Added jiti library needed for linting
* Refactored routes' tests.
* Refactoring to reduce code duplication
This commit is contained in:
Liviu Burcusel 2025-10-25 16:01:28 +02:00
parent 304d5188b8
commit 2a014e0733
Signed by: liviu
GPG key ID: 6CDB37A4AD2C610C
9 changed files with 234 additions and 206 deletions

View file

@ -1,116 +1,138 @@
import { describe, it, expect, beforeEach } from "vitest"
import { mount } from "@vue/test-utils"
import { createRouter, createWebHistory } from "vue-router"
import { createVuetify } from "vuetify"
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'
import HeaderNavBar from "../../src/components/HeaderNavBar.vue"
import { describe, it, expect, beforeEach } from "vitest";
import { mount } from "@vue/test-utils";
import { createRouter, createWebHistory } from "vue-router";
import { createVuetify } from "vuetify";
import * as components from "vuetify/components";
import * as directives from "vuetify/directives";
import HeaderNavBar from "../../src/components/HeaderNavBar.vue";
globalThis.ResizeObserver = require('resize-observer-polyfill');
globalThis.ResizeObserver = require("resize-observer-polyfill");
// Mock routes for testing
const routes = [
{ path: "/", component: { template: "<div>Home</div>" } },
{ path: "/about", component: { template: "<div>About</div>" } }
]
{ path: "/about", component: { template: "<div>About</div>" } },
{ path: "/settings", component: { template: "<div>Settings</div>" } },
];
const router = createRouter({
history: createWebHistory(),
routes
routes,
});
const vuetify = createVuetify({
components,
directives,
})
});
describe("HeaderNavBar", () => {
let wrapper: any
let wrapper: any;
beforeEach(() => {
wrapper = mount({
template: `
wrapper = mount(
{
template: `
<v-app>
<v-layout>
<HeaderNavBar />
</v-layout>
</v-app>
`,
}, {
global: {
components: {
HeaderNavBar,
},
plugins: [router, vuetify]
},
{
global: {
components: {
HeaderNavBar,
},
plugins: [router, vuetify],
},
}
})
})
);
});
it("renders the component", () => {
expect(wrapper.exists()).toBe(true)
expect(wrapper.findComponent({ name: "VAppBar" }).exists()).toBe(true)
})
expect(wrapper.exists()).toBe(true);
expect(wrapper.findComponent({ name: "VAppBar" }).exists()).toBe(true);
});
it("renders both navigation buttons", () => {
it("renders all navigation buttons", () => {
const homeButton = wrapper.find("[data-role='homeNavigation']");
const aboutButton = wrapper.find("[data-role='aboutNavigation']");
const settingsButton = wrapper.find("[data-role='settingsNavigation']");
expect(homeButton.exists()).toBe(true);
expect(aboutButton.exists()).toBe(true);
expect(settingsButton.exists()).toBe(true);
expect(homeButton.text()).toContain("Home");
expect(aboutButton.text()).toContain("About");
expect(settingsButton.text()).toContain("Settings");
});
it("has correct icons on buttons", () => {
const homeButton = wrapper.find("[data-role='homeNavigation']");
const aboutButton = wrapper.find("[data-role='aboutNavigation']");
const settingsButton = wrapper.find("[data-role='settingsNavigation']");
expect(homeButton.find("i").attributes("class")).toContain("mdi-home-outline");
expect(aboutButton.find("i").attributes("class")).toContain("mdi-chat-question-outline");
expect(homeButton.find("i").attributes("class")).toContain("mdi-home-outline");
expect(aboutButton.find("i").attributes("class")).toContain("mdi-chat-question-outline");
expect(settingsButton.find("i").attributes("class")).toContain("mdi-cog-outline");
});
it("has correct RouterLink paths", () => {
const routerLinks = wrapper.findAllComponents({ name: "RouterLink" });
expect(routerLinks).toHaveLength(2);
expect(routerLinks).toHaveLength(3);
expect(routerLinks[0].props("to")).toBe("/");
expect(routerLinks[1].props("to")).toBe("/about");
expect(routerLinks[2].props("to")).toBe("/settings");
});
it("applies correct button variants based on active route", async () => {
// Navigate to home route
await router.push("/")
await wrapper.vm.$nextTick()
await router.push("/");
await wrapper.vm.$nextTick();
// Check home button is elevated (active) and about is outlined (inactive)
// Check home button is elevated and the rest are outlined
const homeButton = wrapper.find("[data-role='homeNavigation']");
const aboutButton = wrapper.find("[data-role='aboutNavigation']");
const settingsButton = wrapper.find("[data-role='settingsNavigation']");
expect(homeButton.find("button").attributes("class")).toContain("elevated");
expect(aboutButton.find("button").attributes("class")).toContain("outlined");
expect(homeButton.find("button").attributes("class")).toContain("elevated");
expect(aboutButton.find("button").attributes("class")).toContain("outlined");
expect(settingsButton.find("button").attributes("class")).toContain("outlined");
// // Navigate to about route
// Navigate to about route
await router.push("/about");
await wrapper.vm.$nextTick();
// // Check about button is now elevated and home is outlined
// Check about button is now elevated and the rest are outlined
expect(homeButton.find("button").attributes("class")).toContain("outlined");
expect(aboutButton.find("button").attributes("class")).toContain("elevated");
expect(aboutButton.find("button").attributes("class")).toContain("elevated");
expect(settingsButton.find("button").attributes("class")).toContain("outlined");
// Navigate to settings route
await router.push("/settings");
await wrapper.vm.$nextTick();
// Check about button is now elevated and the rest are outlined
expect(homeButton.find("button").attributes("class")).toContain("outlined");
expect(aboutButton.find("button").attributes("class")).toContain("outlined");
expect(settingsButton.find("button").attributes("class")).toContain("elevated");
});
it("has correct button styling classes", () => {
const routerLinks = wrapper.findAllComponents({ name: "RouterLink" });
for (const link of routerLinks) {
expect(link.classes()).toContain("mx-2")
expect(link.classes()).toContain("text-decoration-none")
expect(link.classes()).toContain("mx-2");
expect(link.classes()).toContain("text-decoration-none");
}
const buttons = wrapper.findAllComponents({ name: "v-btn" });
const buttons = wrapper.findAllComponents({ name: "v-btn" });
for (const button of buttons) {
expect(button.attributes("class")).toContain("v-btn--size-large");
expect(button.attributes("class")).toContain("-primary");
}
expect(button.attributes("class")).toContain("v-btn--size-large");
expect(button.attributes("class")).toContain("-primary");
}
});
it("has proper app bar structure", () => {
@ -126,11 +148,11 @@ describe("HeaderNavBar", () => {
it("maintains accessibility attributes", () => {
const homeButton = wrapper.find("[data-role='homeNavigation']");
expect(homeButton.attributes("data-role")).toBe('homeNavigation');
expect(homeButton.attributes("data-role")).toBe("homeNavigation");
// Check that buttons are actual button elements for screen readers
const buttons = wrapper.findAll("button");
expect(buttons).toHaveLength(2);
expect(buttons).toHaveLength(3);
for (const button of buttons) {
expect(button.element.tagName).toBe("BUTTON");
}