Skip to content

Commit f68443f

Browse files
committed
small unit test cleaning
1 parent b3f7ca6 commit f68443f

4 files changed

Lines changed: 102 additions & 108 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ yarn test:component
124124

125125
Component suite includes:
126126

127-
- focused behavior tests for `ThemeSwitch` and `TheFooter`
128-
- an all-components smoke suite in `tests/components/AllComponentsSmoke.test.ts` that mounts every `.vue` file under `src/components/**`
127+
- focused behavior tests for `ThemeSwitch` and `TheFooter` inside `tests/components/AllComponentsSmoke.test.ts`
128+
- an all-components smoke suite in the same file that mounts every `.vue` file under `src/components/**`
129129

130130
### Coverage tracker
131131

tests/components/AllComponentsSmoke.test.ts

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
import { RouterLinkStub, shallowMount } from "@vue/test-utils";
1+
import { RouterLinkStub, mount, shallowMount } from "@vue/test-utils";
22
import { createPinia } from "pinia";
3+
import { nextTick } from "vue";
34
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
5+
import TheFooter from "../../src/components/Styling/TheFooter.vue";
6+
import ThemeSwitch from "../../src/components/Styling/ThemeSwitch.vue";
47

58
vi.mock("../../src/components/login.ts", () => ({
69
session: {
@@ -152,6 +155,11 @@ const componentEntries = Object.entries(componentModules).sort(([a], [b]) =>
152155
a.localeCompare(b)
153156
);
154157

158+
const flushPromises = async () => {
159+
await Promise.resolve();
160+
await Promise.resolve();
161+
};
162+
155163
function makeProps(path: string): Record<string, unknown> {
156164
if (path.endsWith("/Styling/SharedWith.vue")) {
157165
return {
@@ -176,6 +184,97 @@ function makeProps(path: string): Record<string, unknown> {
176184
return {};
177185
}
178186

187+
describe("Focused Styling Component Tests", () => {
188+
it("ThemeSwitch initializes from saved localStorage theme", async () => {
189+
localStorage.setItem("app-theme", "light");
190+
191+
const wrapper = mount(ThemeSwitch);
192+
await nextTick();
193+
194+
const button = wrapper.get("button.theme-switch");
195+
expect(button.attributes("data-mode")).toBe("light");
196+
expect(button.attributes("aria-checked")).toBe("false");
197+
expect(document.documentElement.getAttribute("data-theme")).toBe("light");
198+
});
199+
200+
it("ThemeSwitch defaults to dark and toggles theme on click", async () => {
201+
const wrapper = mount(ThemeSwitch);
202+
await nextTick();
203+
204+
const button = wrapper.get("button.theme-switch");
205+
expect(button.attributes("data-mode")).toBe("dark");
206+
expect(localStorage.getItem("app-theme")).toBe("dark");
207+
expect(document.documentElement.getAttribute("data-theme")).toBe("dark");
208+
209+
await button.trigger("click");
210+
expect(button.attributes("data-mode")).toBe("light");
211+
expect(button.attributes("aria-checked")).toBe("false");
212+
expect(localStorage.getItem("app-theme")).toBe("light");
213+
expect(document.documentElement.getAttribute("data-theme")).toBe("light");
214+
});
215+
216+
it("ThemeSwitch toggles theme on keyboard handlers", async () => {
217+
const wrapper = mount(ThemeSwitch);
218+
await nextTick();
219+
220+
const button = wrapper.get("button.theme-switch");
221+
expect(button.attributes("data-mode")).toBe("dark");
222+
223+
await button.trigger("keydown.enter");
224+
expect(button.attributes("data-mode")).toBe("light");
225+
226+
await button.trigger("keydown.space");
227+
expect(button.attributes("data-mode")).toBe("dark");
228+
});
229+
230+
it("TheFooter renders version metadata and shows last modified date after fetch", async () => {
231+
const fetchMock = vi.fn(async () => ({
232+
json: async () => [
233+
{
234+
commit: { committer: { date: "2026-02-20T10:20:30.000Z" } },
235+
},
236+
],
237+
}));
238+
vi.stubGlobal("fetch", fetchMock as unknown as typeof fetch);
239+
240+
const wrapper = mount(TheFooter);
241+
await vi.waitFor(() => {
242+
expect(wrapper.text()).toContain("Last Modified: 2026-02-20");
243+
});
244+
245+
expect(wrapper.text()).toContain("Version: v1.0.0");
246+
expect(wrapper.text()).toContain("web-app-v1.0.0");
247+
expect(fetchMock).toHaveBeenCalledOnce();
248+
});
249+
250+
it("TheFooter keeps last-modified hidden when commit API returns no entries", async () => {
251+
const fetchMock = vi.fn(async () => ({
252+
json: async () => [],
253+
}));
254+
vi.stubGlobal("fetch", fetchMock as unknown as typeof fetch);
255+
256+
const wrapper = mount(TheFooter);
257+
await flushPromises();
258+
259+
expect(wrapper.text()).not.toContain("Last Modified:");
260+
});
261+
262+
it("TheFooter handles fetch failures without crashing", async () => {
263+
const fetchMock = vi.fn(async () => {
264+
throw new Error("network failure");
265+
});
266+
const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
267+
vi.stubGlobal("fetch", fetchMock as unknown as typeof fetch);
268+
269+
const wrapper = mount(TheFooter);
270+
await flushPromises();
271+
272+
expect(wrapper.exists()).toBe(true);
273+
expect(wrapper.text()).not.toContain("Last Modified:");
274+
expect(errorSpy).toHaveBeenCalled();
275+
});
276+
});
277+
179278
describe("All Vue Components Smoke Tests", () => {
180279
beforeEach(() => {
181280
vi.useFakeTimers();

tests/components/TheFooter.test.ts

Lines changed: 0 additions & 57 deletions
This file was deleted.

tests/components/ThemeSwitch.test.ts

Lines changed: 0 additions & 48 deletions
This file was deleted.

0 commit comments

Comments
 (0)