mirror of
https://github.com/jacobtread/obsidian-timekeep.git
synced 2026-07-22 10:10:27 +00:00
test: tests files for needed tests, timesheetStatusBarItem tests
This commit is contained in:
parent
8b04d70bd2
commit
e8a7eb5cd7
24 changed files with 177 additions and 44 deletions
|
|
@ -17,5 +17,8 @@ vi.mock("obsidian", () => {
|
|||
Vault: MockVault,
|
||||
Component: MockComponent,
|
||||
Notice: MockNotice,
|
||||
setIcon: vi.fn((containerEl: HTMLElement, icon: string) => {
|
||||
containerEl.innerHTML += `<svg data-icon="${icon}"></svg>`;
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ describe("DomComponent", () => {
|
|||
comp.wrapperEl = wrapper;
|
||||
container.appendChild(wrapper);
|
||||
|
||||
comp.onunload();
|
||||
comp.unload();
|
||||
|
||||
expect(comp.unmounted).toBe(true); // only unload sets unmounted
|
||||
expect(wrapper.parentElement).toBeNull();
|
||||
|
|
@ -89,7 +89,7 @@ describe("DomComponent", () => {
|
|||
child.wrapperEl = wrapper;
|
||||
container.appendChild(wrapper);
|
||||
|
||||
child.onunload();
|
||||
child.unload();
|
||||
|
||||
expect(child.unmounted).toBe(true);
|
||||
expect(wrapper.parentElement).toBe(container);
|
||||
|
|
|
|||
|
|
@ -7,12 +7,6 @@ import { createMockContainer } from "@/__mocks__/obsidian";
|
|||
|
||||
import { createObsidianIcon } from "./obsidianIcon";
|
||||
|
||||
vi.mock("obsidian", () => ({
|
||||
setIcon: vi.fn((containerEl: HTMLElement, icon: string) => {
|
||||
containerEl.innerHTML += `<svg data-icon="${icon}"></svg>`;
|
||||
}),
|
||||
}));
|
||||
|
||||
describe("createObsidianIcon", () => {
|
||||
let container: HTMLElement;
|
||||
|
||||
|
|
|
|||
5
src/components/timesheet.test.ts
Normal file
5
src/components/timesheet.test.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// @vitest-environment happy-dom
|
||||
|
||||
import { describe } from "vitest";
|
||||
|
||||
describe("Timesheet", () => {});
|
||||
5
src/components/timesheetApp.test.ts
Normal file
5
src/components/timesheetApp.test.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// @vitest-environment happy-dom
|
||||
|
||||
import { describe } from "vitest";
|
||||
|
||||
describe("TimesheetApp", () => {});
|
||||
|
|
@ -35,7 +35,7 @@ describe("TimesheetCounters", () => {
|
|||
});
|
||||
|
||||
it("should initialize wrapper and timers on load", () => {
|
||||
component.onload();
|
||||
component.load();
|
||||
|
||||
expect(component.wrapperEl).toBeInstanceOf(HTMLDivElement);
|
||||
expect(component.wrapperEl?.className).toBe("timekeep-timers");
|
||||
|
|
@ -47,13 +47,13 @@ describe("TimesheetCounters", () => {
|
|||
it("should call updateTimers on load", () => {
|
||||
const spy = vi.spyOn(component, "updateTimers");
|
||||
|
||||
component.onload();
|
||||
component.load();
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should set timer values using getEntryDuration and getTotalDuration", () => {
|
||||
component.onload();
|
||||
component.load();
|
||||
|
||||
const currentSetValues = vi.spyOn(component.currentTimer, "setValues");
|
||||
const totalSetValues = vi.spyOn(component.totalTimer, "setValues");
|
||||
|
|
@ -73,7 +73,7 @@ describe("TimesheetCounters", () => {
|
|||
|
||||
const registerSpy = vi.spyOn(component, "registerInterval");
|
||||
|
||||
component.onload();
|
||||
component.load();
|
||||
|
||||
expect(component.currentContentInterval).toBeDefined();
|
||||
expect(registerSpy).toHaveBeenCalledWith(component.currentContentInterval);
|
||||
|
|
@ -87,14 +87,14 @@ describe("TimesheetCounters", () => {
|
|||
const clearSpy = vi.spyOn(global, "clearInterval");
|
||||
|
||||
isKeepRunning.mockReturnValue(true);
|
||||
component.onload();
|
||||
component.load();
|
||||
|
||||
expect(clearSpy).toHaveBeenCalledWith(fakeIntervalID);
|
||||
});
|
||||
|
||||
it("should show the current and total duration if theres a running entry", () => {
|
||||
const start = moment();
|
||||
const oneHourLater = moment().add(1, "hour");
|
||||
const oneHourLater = moment(start).add(1, "hour");
|
||||
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(oneHourLater.toDate());
|
||||
|
|
@ -124,7 +124,7 @@ describe("TimesheetCounters", () => {
|
|||
|
||||
it("should show total duration as the sum of all entry durations", () => {
|
||||
const start = moment();
|
||||
const oneHourLater = moment().add(1, "hour");
|
||||
const oneHourLater = moment(start).add(1, "hour");
|
||||
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(oneHourLater.toDate());
|
||||
|
|
|
|||
5
src/components/timesheetExportActions.test.ts
Normal file
5
src/components/timesheetExportActions.test.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// @vitest-environment happy-dom
|
||||
|
||||
import { describe } from "vitest";
|
||||
|
||||
describe("TimesheetExportActions", () => {});
|
||||
5
src/components/timesheetFileEntry.test.ts
Normal file
5
src/components/timesheetFileEntry.test.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// @vitest-environment happy-dom
|
||||
|
||||
import { describe } from "vitest";
|
||||
|
||||
describe("TimesheetFileEntry", () => {});
|
||||
|
|
@ -34,7 +34,7 @@ describe("TimesheetLoadError", () => {
|
|||
|
||||
expect(container.children.length).toBe(1);
|
||||
|
||||
component.onunload();
|
||||
component.unload();
|
||||
expect(container.children.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
5
src/components/timesheetNameInput.test.ts
Normal file
5
src/components/timesheetNameInput.test.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// @vitest-environment happy-dom
|
||||
|
||||
import { describe } from "vitest";
|
||||
|
||||
describe("TimesheetNameInput", () => {});
|
||||
5
src/components/timesheetRowContainer.test.ts
Normal file
5
src/components/timesheetRowContainer.test.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// @vitest-environment happy-dom
|
||||
|
||||
import { describe } from "vitest";
|
||||
|
||||
describe("TimesheetRowContainer", () => {});
|
||||
5
src/components/timesheetRowContent.test.ts
Normal file
5
src/components/timesheetRowContent.test.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// @vitest-environment happy-dom
|
||||
|
||||
import { describe } from "vitest";
|
||||
|
||||
describe("TimesheetRowContent", () => {});
|
||||
|
|
@ -14,7 +14,7 @@ import { formatTimestamp } from "@/utils/time";
|
|||
import { DomComponent } from "./domComponent";
|
||||
import { createObsidianIcon } from "./obsidianIcon";
|
||||
import { TimekeepName } from "./timesheetName";
|
||||
import { TimesheetRowDurationComponent } from "./timesheetRowDuration";
|
||||
import { TimesheetRowDuration } from "./timesheetRowDuration";
|
||||
|
||||
/**
|
||||
* Component for the contents of a timesheet row
|
||||
|
|
@ -123,7 +123,7 @@ export class TimesheetRowContent extends DomComponent {
|
|||
cls: ["timekeep-col", "timekeep-col--duration"],
|
||||
});
|
||||
|
||||
const duration = new TimesheetRowDurationComponent(durationColEl, entry);
|
||||
const duration = new TimesheetRowDuration(durationColEl, entry);
|
||||
|
||||
this.addChild(duration);
|
||||
|
||||
|
|
|
|||
5
src/components/timesheetRowContentEditing.test.ts
Normal file
5
src/components/timesheetRowContentEditing.test.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// @vitest-environment happy-dom
|
||||
|
||||
import { describe } from "vitest";
|
||||
|
||||
describe("TimesheetRowContentEditing", () => {});
|
||||
|
|
@ -7,12 +7,12 @@ import { createMockContainer } from "@/__mocks__/obsidian";
|
|||
import * as queries from "@/timekeep/queries";
|
||||
import * as timeUtils from "@/utils/time";
|
||||
|
||||
import { TimesheetRowDurationComponent } from "./timesheetRowDuration";
|
||||
import { TimesheetRowDuration } from "./timesheetRowDuration";
|
||||
|
||||
describe("TimesheetRowDurationComponent", () => {
|
||||
describe("TimesheetRowDuration", () => {
|
||||
let container: HTMLElement;
|
||||
let entry: any;
|
||||
let component: TimesheetRowDurationComponent;
|
||||
let component: TimesheetRowDuration;
|
||||
|
||||
beforeEach(() => {
|
||||
container = createMockContainer();
|
||||
|
|
@ -30,7 +30,7 @@ describe("TimesheetRowDurationComponent", () => {
|
|||
// Mock setInterval / clearInterval
|
||||
vi.useFakeTimers();
|
||||
|
||||
component = new TimesheetRowDurationComponent(container, entry);
|
||||
component = new TimesheetRowDuration(container, entry);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
|
@ -38,7 +38,7 @@ describe("TimesheetRowDurationComponent", () => {
|
|||
});
|
||||
|
||||
it("should create a wrapper span with the correct class", () => {
|
||||
component.onload();
|
||||
component.load();
|
||||
|
||||
expect(component.wrapperEl).toBeInstanceOf(HTMLSpanElement);
|
||||
expect(component.wrapperEl?.className).toBe("timekeep-time");
|
||||
|
|
@ -47,13 +47,13 @@ describe("TimesheetRowDurationComponent", () => {
|
|||
it("should call updateTime on load", () => {
|
||||
const spy = vi.spyOn(component, "updateTime");
|
||||
|
||||
component.onload();
|
||||
component.load();
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should set textContent based on getEntryDuration and formatDurationLong", () => {
|
||||
component.onload();
|
||||
component.load();
|
||||
|
||||
expect(queries.getEntryDuration).toHaveBeenCalledWith(entry, expect.any(moment));
|
||||
expect(timeUtils.formatDurationLong).toHaveBeenCalledWith(42);
|
||||
|
|
@ -64,7 +64,7 @@ describe("TimesheetRowDurationComponent", () => {
|
|||
(queries.isEntryRunning as any).mockReturnValue(true);
|
||||
const registerSpy = vi.spyOn(component, "registerInterval");
|
||||
|
||||
component.onload();
|
||||
component.load();
|
||||
|
||||
expect(component.currentContentInterval).toBeDefined();
|
||||
expect(registerSpy).toHaveBeenCalledWith(component.currentContentInterval);
|
||||
|
|
@ -76,7 +76,7 @@ describe("TimesheetRowDurationComponent", () => {
|
|||
const clearSpy = vi.spyOn(global, "clearInterval");
|
||||
|
||||
(queries.isEntryRunning as any).mockReturnValue(true);
|
||||
component.onload();
|
||||
component.load();
|
||||
|
||||
expect(clearSpy).toHaveBeenCalledWith(fakeInterval);
|
||||
});
|
||||
|
|
@ -84,7 +84,7 @@ describe("TimesheetRowDurationComponent", () => {
|
|||
it("should not schedule interval if entry is not running", () => {
|
||||
(queries.isEntryRunning as any).mockReturnValue(false);
|
||||
const registerSpy = vi.spyOn(component, "registerInterval");
|
||||
component.onload();
|
||||
component.load();
|
||||
|
||||
expect(component.currentContentInterval).not.toBeDefined();
|
||||
expect(registerSpy).not.toHaveBeenCalled();
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { DomComponent } from "./domComponent";
|
|||
* Component for rendering the live-updating duration on
|
||||
* an entry row
|
||||
*/
|
||||
export class TimesheetRowDurationComponent extends DomComponent {
|
||||
export class TimesheetRowDuration extends DomComponent {
|
||||
/** The entry this duration belongs to */
|
||||
entry: TimeEntry;
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ describe("TimesheetSaveError", () => {
|
|||
});
|
||||
|
||||
it("renders wrapper, error message, and buttons on load", () => {
|
||||
component.onload();
|
||||
component.load();
|
||||
|
||||
const wrapper = container.querySelector(".timekeep-container");
|
||||
expect(wrapper).not.toBeNull();
|
||||
|
|
@ -54,13 +54,13 @@ describe("TimesheetSaveError", () => {
|
|||
});
|
||||
|
||||
it("calls handleSaveTimekeep on retry button click", () => {
|
||||
component.onload();
|
||||
component.load();
|
||||
component.onRetrySave();
|
||||
expect(handleSaveTimekeep).toHaveBeenCalledWith(timekeepStore.getState());
|
||||
});
|
||||
|
||||
it("writes JSON to clipboard on copy button click", async () => {
|
||||
component.onload();
|
||||
component.load();
|
||||
|
||||
await component.onCopy();
|
||||
|
||||
|
|
@ -70,8 +70,8 @@ describe("TimesheetSaveError", () => {
|
|||
});
|
||||
|
||||
it("removes wrapper on unload", () => {
|
||||
component.onload();
|
||||
component.onunload();
|
||||
component.load();
|
||||
component.unload();
|
||||
const wrapper = container.querySelector(".timekeep-container");
|
||||
expect(wrapper).toBeNull();
|
||||
});
|
||||
|
|
|
|||
5
src/components/timesheetStart.test.ts
Normal file
5
src/components/timesheetStart.test.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// @vitest-environment happy-dom
|
||||
|
||||
import { describe } from "vitest";
|
||||
|
||||
describe("TimesheetStart", () => {});
|
||||
5
src/components/timesheetStartEditing.test.ts
Normal file
5
src/components/timesheetStartEditing.test.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// @vitest-environment happy-dom
|
||||
|
||||
import { describe } from "vitest";
|
||||
|
||||
describe("TimesheetStartEditing", () => {});
|
||||
5
src/components/timesheetStartRunning.test.ts
Normal file
5
src/components/timesheetStartRunning.test.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// @vitest-environment happy-dom
|
||||
|
||||
import { describe } from "vitest";
|
||||
|
||||
describe("TimesheetStartRunning", () => {});
|
||||
76
src/components/timesheetStatusBarItem.test.ts
Normal file
76
src/components/timesheetStatusBarItem.test.ts
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
// @vitest-environment happy-dom
|
||||
|
||||
import moment from "moment";
|
||||
import { v4 } from "uuid";
|
||||
import { describe, beforeEach, it, expect, vi, afterEach } from "vitest";
|
||||
|
||||
import { createMockContainer } from "@/__mocks__/obsidian";
|
||||
import { TimeEntry } from "@/timekeep/schema";
|
||||
|
||||
import { TimesheetStatusBarItem } from "./timesheetStatusBarItem";
|
||||
|
||||
describe("TimesheetStatusBarItem", () => {
|
||||
const start = moment();
|
||||
const oneHourLater = start.add(1, "hour");
|
||||
|
||||
const entry: TimeEntry = {
|
||||
id: v4(),
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
subEntries: null,
|
||||
};
|
||||
let containerEl: HTMLElement;
|
||||
let onOpen: VoidFunction;
|
||||
let onStop: VoidFunction;
|
||||
|
||||
beforeEach(() => {
|
||||
onOpen = vi.fn();
|
||||
onStop = vi.fn();
|
||||
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(oneHourLater.toDate());
|
||||
|
||||
containerEl = createMockContainer();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it("should initialize with the correct entry and callback functions", () => {
|
||||
const statusBarItem = new TimesheetStatusBarItem(containerEl, entry, onOpen, onStop);
|
||||
|
||||
expect(statusBarItem.entry).toBe(entry);
|
||||
expect(statusBarItem.onOpen).toBe(onOpen);
|
||||
expect(statusBarItem.onStop).toBe(onStop);
|
||||
});
|
||||
|
||||
it("should call onStop when the stop icon is clicked", () => {
|
||||
const statusBarItem = new TimesheetStatusBarItem(containerEl, entry, onOpen, onStop);
|
||||
statusBarItem.load();
|
||||
|
||||
// Simulate click on the stop icon
|
||||
const stopIcon = containerEl.querySelector(".button-icon");
|
||||
const event = new MouseEvent("click", { bubbles: true, cancelable: true });
|
||||
if (stopIcon) {
|
||||
stopIcon.dispatchEvent(event);
|
||||
}
|
||||
|
||||
expect(onStop).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("should call onOpen when the content area is clicked", () => {
|
||||
const statusBarItem = new TimesheetStatusBarItem(containerEl, entry, onOpen, onStop);
|
||||
statusBarItem.load();
|
||||
|
||||
// Simulate click on the content element
|
||||
const contentEl = containerEl.querySelector(".timekeep-status-item__content");
|
||||
const event = new MouseEvent("click", { bubbles: true, cancelable: true });
|
||||
if (contentEl) {
|
||||
contentEl.dispatchEvent(event);
|
||||
}
|
||||
|
||||
expect(onOpen).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
|
@ -2,7 +2,7 @@ import { TimeEntry } from "@/timekeep/schema";
|
|||
|
||||
import { DomComponent } from "./domComponent";
|
||||
import { createObsidianIcon } from "./obsidianIcon";
|
||||
import { TimesheetRowDurationComponent } from "./timesheetRowDuration";
|
||||
import { TimesheetRowDuration } from "./timesheetRowDuration";
|
||||
|
||||
export class TimesheetStatusBarItem extends DomComponent {
|
||||
/** The entry this duration belongs to */
|
||||
|
|
@ -12,7 +12,7 @@ export class TimesheetStatusBarItem extends DomComponent {
|
|||
currentContentInterval: number | undefined;
|
||||
|
||||
/** Component for rendering the real time updating duration */
|
||||
duration: TimesheetRowDurationComponent;
|
||||
duration: TimesheetRowDuration;
|
||||
|
||||
/** Callback to open the file when the content is clicked */
|
||||
onOpen: VoidFunction;
|
||||
|
|
@ -44,7 +44,6 @@ export class TimesheetStatusBarItem extends DomComponent {
|
|||
"timekeep-status-item__button",
|
||||
"button-icon",
|
||||
]);
|
||||
this.registerDomEvent(stopIcon, "click", this.onStop);
|
||||
stopIcon.title = "Stop Entry";
|
||||
|
||||
const contentEl = wrapperEl.createDiv({
|
||||
|
|
@ -57,8 +56,9 @@ export class TimesheetStatusBarItem extends DomComponent {
|
|||
text: entry.name + ":",
|
||||
});
|
||||
|
||||
this.addChild(new TimesheetRowDurationComponent(contentEl, entry));
|
||||
this.addChild(new TimesheetRowDuration(contentEl, entry));
|
||||
|
||||
this.registerDomEvent(stopIcon, "click", this.onStop);
|
||||
this.registerDomEvent(contentEl, "click", this.onOpen);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
5
src/components/timesheetTable.test.ts
Normal file
5
src/components/timesheetTable.test.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// @vitest-environment happy-dom
|
||||
|
||||
import { describe } from "vitest";
|
||||
|
||||
describe("TimesheetTable", () => {});
|
||||
|
|
@ -16,7 +16,7 @@ describe("TimesheetTimer", () => {
|
|||
});
|
||||
|
||||
it("should create timer elements on load", () => {
|
||||
timer.onload();
|
||||
timer.load();
|
||||
|
||||
const timerEl = container.children[0] as HTMLElement;
|
||||
expect(timerEl).toBeDefined();
|
||||
|
|
@ -36,16 +36,16 @@ describe("TimesheetTimer", () => {
|
|||
});
|
||||
|
||||
it("should remove timer element on unload", () => {
|
||||
timer.onload();
|
||||
timer.load();
|
||||
const timerEl = container.children[0] as HTMLElement;
|
||||
expect(timerEl).toBeDefined();
|
||||
|
||||
timer.onunload();
|
||||
timer.unload();
|
||||
expect(timerEl.parentElement).toBeNull();
|
||||
});
|
||||
|
||||
it("should hide or show the timer element", () => {
|
||||
timer.onload();
|
||||
timer.load();
|
||||
const timerEl = container.children[0] as HTMLElement;
|
||||
|
||||
timer.setHidden(true);
|
||||
|
|
@ -56,7 +56,7 @@ describe("TimesheetTimer", () => {
|
|||
});
|
||||
|
||||
it("should set primary and secondary values correctly", () => {
|
||||
timer.onload();
|
||||
timer.load();
|
||||
const timerEl = container.children[0] as HTMLElement;
|
||||
const primary = timerEl.children[0] as HTMLDivElement;
|
||||
const secondary = timerEl.children[1] as HTMLDivElement;
|
||||
|
|
@ -73,7 +73,7 @@ describe("TimesheetTimer", () => {
|
|||
});
|
||||
|
||||
it("secondary value should be hidden if it is empty", () => {
|
||||
timer.onload();
|
||||
timer.load();
|
||||
|
||||
const timerEl = container.children[0] as HTMLElement;
|
||||
const secondary = timerEl.children[1] as HTMLDivElement;
|
||||
|
|
|
|||
Loading…
Reference in a new issue