mirror of
https://github.com/jacobtread/obsidian-timekeep.git
synced 2026-07-22 10:10:27 +00:00
tests: more tests for remaining parser, queries, and update logic
This commit is contained in:
parent
632bd67a4f
commit
aaa93c3371
14 changed files with 506 additions and 4 deletions
|
|
@ -0,0 +1,32 @@
|
|||
import moment from "moment";
|
||||
|
||||
import { TimeEntry } from "@/timekeep/schema";
|
||||
|
||||
export const currentTime = moment();
|
||||
|
||||
export const targetEntryId = "9054dee3-8c15-493b-ad31-f070e08c2699";
|
||||
|
||||
export const input: TimeEntry[] = [
|
||||
{
|
||||
id: "7054dee3-8c15-493b-ad31-f070e08c2699",
|
||||
name: "Part 1",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [
|
||||
{
|
||||
id: "7054dee3-8c15-493b-ad31-f070e08c2699",
|
||||
name: "Part 1",
|
||||
startTime: currentTime,
|
||||
endTime: currentTime,
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: "7054dee3-8c15-493b-ad31-f070e08c269a",
|
||||
name: "Part 2",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
import moment from "moment";
|
||||
|
||||
import { TimeEntry } from "@/timekeep/schema";
|
||||
|
||||
export const currentTime = moment();
|
||||
|
||||
export const targetEntryId = "9054dee3-8c15-493b-ad31-f070e08c2699";
|
||||
|
||||
export const targetEntry: TimeEntry = {
|
||||
id: "9054dee3-8c15-493b-ad31-f070e08c2699",
|
||||
name: "Running Entry",
|
||||
startTime: currentTime,
|
||||
endTime: null,
|
||||
subEntries: null,
|
||||
};
|
||||
|
||||
export const input: TimeEntry[] = [
|
||||
{
|
||||
id: "8054dee3-8c15-493b-ad31-f070e08c2699",
|
||||
name: "Block 1",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [
|
||||
{
|
||||
id: "7054dee3-8c15-493b-ad31-f070e08c2699",
|
||||
name: "Part 1",
|
||||
startTime: currentTime,
|
||||
endTime: currentTime,
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: "7054dee3-8c15-493b-ad31-f070e08c269a",
|
||||
name: "Part 2",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [
|
||||
{
|
||||
id: "dcd7dca3-2471-4855-a49b-397e388c3204",
|
||||
name: "Part 1",
|
||||
startTime: currentTime,
|
||||
endTime: currentTime,
|
||||
subEntries: null,
|
||||
},
|
||||
targetEntry,
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
import moment from "moment";
|
||||
|
||||
import { createCodeBlock } from "@/utils/codeblock";
|
||||
|
||||
import { Timekeep } from "@/timekeep/schema";
|
||||
|
||||
// Input data to find
|
||||
export const input1 = createCodeBlock(
|
||||
`{"entries":[{"name":"Block 1","startTime":"2024-03-17T01:33:51.630Z","endTime":"2024-03-17T01:33:55.151Z","subEntries":null}]}`,
|
||||
4,
|
||||
4
|
||||
);
|
||||
|
||||
// Input data to find
|
||||
export const input2 = createCodeBlock(
|
||||
`{"entries":[{"name":"Block 2","startTime":"2024-03-17T01:33:51.630Z","endTime":"2024-03-17T01:33:55.151Z","subEntries":null}]}`,
|
||||
4,
|
||||
4
|
||||
);
|
||||
|
||||
// Timekeep with a renamed block
|
||||
export const inputTimekeep1: Timekeep = {
|
||||
entries: [
|
||||
{
|
||||
id: "9054dee3-8c15-493b-ad31-f070e08c2699",
|
||||
name: "Block 1",
|
||||
startTime: moment("2024-03-17T01:33:51.630Z"),
|
||||
endTime: moment("2024-03-17T01:33:55.151Z"),
|
||||
subEntries: null,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// Timekeep with a renamed block
|
||||
export const inputTimekeep2: Timekeep = {
|
||||
entries: [
|
||||
{
|
||||
id: "9054dee3-8c15-493b-ad31-f070e08c2699",
|
||||
name: "Block 2",
|
||||
startTime: moment("2024-03-17T01:33:51.630Z"),
|
||||
endTime: moment("2024-03-17T01:33:55.151Z"),
|
||||
subEntries: null,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const text = "\n\n\n" + input1 + "\n\n\n\n" + input2;
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
import { createCodeBlock } from "@/utils/codeblock";
|
||||
|
||||
// Input data to find
|
||||
export const input1 = createCodeBlock(`{"invalid_json}]}`, 4, 4);
|
||||
|
||||
export const text = "\n\n\n" + input1 + "\n\n\n\n";
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
import moment from "moment";
|
||||
|
||||
import { createCodeBlock } from "@/utils/codeblock";
|
||||
|
||||
import { Timekeep } from "@/timekeep/schema";
|
||||
|
||||
// Input data to find
|
||||
export const input1 = createCodeBlock(
|
||||
`{"entries":[{"name":"Block 1","startTime":"2024-03-17T01:33:51.630Z","endTime":"2024-03-17T01:33:55.151Z","subEntries":null}]}`,
|
||||
4,
|
||||
4
|
||||
);
|
||||
|
||||
// Timekeep with a renamed block
|
||||
export const inputTimekeep1: Timekeep = {
|
||||
entries: [
|
||||
{
|
||||
id: "9054dee3-8c15-493b-ad31-f070e08c2699",
|
||||
name: "Block 1",
|
||||
startTime: moment("2024-03-17T01:33:51.630Z"),
|
||||
endTime: moment("2024-03-17T01:33:55.151Z"),
|
||||
subEntries: null,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const text = "\n\n\n" + input1 + "\n\n\n\n```timekeep\n\n";
|
||||
|
|
@ -19,6 +19,44 @@ export const entries: TimeEntry[] = [
|
|||
endTime: currentTime,
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: "1f683adc-0205-4a18-9b1b-ada64a4b0553",
|
||||
name: "Block Should be removed",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [],
|
||||
},
|
||||
{
|
||||
id: "36c3a34a-208c-4975-bae7-ff833e8017ac",
|
||||
name: "Block 4",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [
|
||||
{
|
||||
id: "cbfb3b78-dd7f-4ee2-99ea-34d6b0626e23",
|
||||
name: "Block 5",
|
||||
startTime: currentTime,
|
||||
endTime: currentTime,
|
||||
subEntries: null,
|
||||
},
|
||||
|
||||
{
|
||||
id: "35ff21e3-af83-45b6-86a2-7e141a12c37f",
|
||||
name: "Block 12",
|
||||
startTime: currentTime,
|
||||
endTime: currentTime,
|
||||
subEntries: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "a9bda6f2-568c-4d11-a3be-e8586bde8b1c",
|
||||
name: "Block 6",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [],
|
||||
folder: true,
|
||||
},
|
||||
entryToRemove,
|
||||
{
|
||||
id: "b8fbcb98-f1e9-4d80-8867-994f58191046",
|
||||
|
|
@ -37,6 +75,36 @@ export const expectedEntries: TimeEntry[] = [
|
|||
endTime: currentTime,
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: "36c3a34a-208c-4975-bae7-ff833e8017ac",
|
||||
name: "Block 4",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [
|
||||
{
|
||||
id: "cbfb3b78-dd7f-4ee2-99ea-34d6b0626e23",
|
||||
name: "Block 5",
|
||||
startTime: currentTime,
|
||||
endTime: currentTime,
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: "35ff21e3-af83-45b6-86a2-7e141a12c37f",
|
||||
name: "Block 12",
|
||||
startTime: currentTime,
|
||||
endTime: currentTime,
|
||||
subEntries: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "a9bda6f2-568c-4d11-a3be-e8586bde8b1c",
|
||||
name: "Block 6",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [],
|
||||
folder: true,
|
||||
},
|
||||
{
|
||||
id: "b8fbcb98-f1e9-4d80-8867-994f58191046",
|
||||
name: "Block 2",
|
||||
|
|
|
|||
27
src/timekeep/__fixtures__/path/pathChild.ts
Normal file
27
src/timekeep/__fixtures__/path/pathChild.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import moment from "moment";
|
||||
|
||||
import { TimeEntry } from "@/timekeep/schema";
|
||||
|
||||
export const currentTime = moment();
|
||||
|
||||
export const targetEntry: TimeEntry = {
|
||||
id: "9054dee3-8c15-493b-ad31-f070e08c2699",
|
||||
name: "Part 1",
|
||||
startTime: currentTime,
|
||||
endTime: currentTime,
|
||||
subEntries: null,
|
||||
};
|
||||
|
||||
export const entries = [
|
||||
{
|
||||
id: "7054dee3-8c15-493b-ad31-f070e08c2699",
|
||||
name: "Part 1",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [targetEntry],
|
||||
},
|
||||
];
|
||||
export const expected = [
|
||||
{ id: "7054dee3-8c15-493b-ad31-f070e08c2699", name: "Part 1" },
|
||||
{ id: "9054dee3-8c15-493b-ad31-f070e08c2699", name: "Part 1" },
|
||||
];
|
||||
52
src/timekeep/__fixtures__/path/pathDeepChild.ts
Normal file
52
src/timekeep/__fixtures__/path/pathDeepChild.ts
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
import moment from "moment";
|
||||
|
||||
import { TimeEntry } from "@/timekeep/schema";
|
||||
|
||||
export const currentTime = moment();
|
||||
|
||||
export const targetEntry: TimeEntry = {
|
||||
id: "9054dee3-8c15-493b-ad31-f070e08c2699",
|
||||
name: "Part 1",
|
||||
startTime: currentTime,
|
||||
endTime: currentTime,
|
||||
subEntries: null,
|
||||
};
|
||||
|
||||
export const entries = [
|
||||
{
|
||||
id: "7054dee3-8c15-493b-ad31-f070e08c2699",
|
||||
name: "Part 1",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [
|
||||
{
|
||||
id: "7054dee3-8c15-493b-ad31-f070e08c2699",
|
||||
name: "Part 1",
|
||||
startTime: currentTime,
|
||||
endTime: currentTime,
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: "7054dee3-8c15-493b-ad31-f070e08c269a",
|
||||
name: "Part 2",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [targetEntry],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
export const expected = [
|
||||
{
|
||||
id: "7054dee3-8c15-493b-ad31-f070e08c2699",
|
||||
name: "Part 1",
|
||||
},
|
||||
{
|
||||
id: "7054dee3-8c15-493b-ad31-f070e08c269a",
|
||||
name: "Part 2",
|
||||
},
|
||||
{
|
||||
id: "9054dee3-8c15-493b-ad31-f070e08c2699",
|
||||
name: "Part 1",
|
||||
},
|
||||
];
|
||||
39
src/timekeep/__fixtures__/path/pathNotFoundDeep.ts
Normal file
39
src/timekeep/__fixtures__/path/pathNotFoundDeep.ts
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import moment from "moment";
|
||||
|
||||
import { TimeEntry } from "@/timekeep/schema";
|
||||
|
||||
export const currentTime = moment();
|
||||
|
||||
export const targetEntry: TimeEntry = {
|
||||
id: "9054dee3-8c15-493b-ad31-f070e08c2699",
|
||||
name: "Part 1",
|
||||
startTime: currentTime,
|
||||
endTime: currentTime,
|
||||
subEntries: null,
|
||||
};
|
||||
|
||||
export const entries = [
|
||||
{
|
||||
id: "7054dee3-8c15-493b-ad31-f070e08c2699",
|
||||
name: "Part 1",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [
|
||||
{
|
||||
id: "7054dee3-8c15-493b-ad31-f070e08c2699",
|
||||
name: "Part 1",
|
||||
startTime: currentTime,
|
||||
endTime: currentTime,
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: "7054dee3-8c15-493b-ad31-f070e08c269a",
|
||||
name: "Part 2",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
export const expected = [];
|
||||
21
src/timekeep/__fixtures__/path/pathTopLevel.ts
Normal file
21
src/timekeep/__fixtures__/path/pathTopLevel.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import moment from "moment";
|
||||
|
||||
import { TimeEntry } from "@/timekeep/schema";
|
||||
|
||||
export const currentTime = moment();
|
||||
|
||||
export const targetEntry: TimeEntry = {
|
||||
id: "9054dee3-8c15-493b-ad31-f070e08c2699",
|
||||
name: "Part 1",
|
||||
startTime: currentTime,
|
||||
endTime: currentTime,
|
||||
subEntries: null,
|
||||
};
|
||||
|
||||
export const entries = [targetEntry];
|
||||
export const expected = [
|
||||
{
|
||||
id: "9054dee3-8c15-493b-ad31-f070e08c2699",
|
||||
name: "Part 1",
|
||||
},
|
||||
];
|
||||
42
src/timekeep/__fixtures__/startTime/earlyStartTime.ts
Normal file
42
src/timekeep/__fixtures__/startTime/earlyStartTime.ts
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import moment from "moment";
|
||||
|
||||
export const currentTime = moment();
|
||||
|
||||
export const entry = {
|
||||
id: "9054dee3-8c15-493b-ad31-f070e08c2699",
|
||||
name: "Part 1",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [
|
||||
{
|
||||
id: "d7afcb74-a6f2-4cb7-80ed-48a2f71aa7a6",
|
||||
name: "Part 1",
|
||||
startTime: currentTime.add(1, "hours"),
|
||||
endTime: currentTime.add(1, "hours"),
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: "da783535-08d3-4f65-97f3-e331273da934",
|
||||
name: "Part 1",
|
||||
startTime: currentTime,
|
||||
endTime: currentTime,
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: "5c305879-61ba-4bc9-8373-568948abf27f",
|
||||
name: "Part 1",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: "8d491c4c-2441-4f87-bd29-4758b8108500",
|
||||
name: "Part 1",
|
||||
startTime: currentTime.add(2, "hours"),
|
||||
endTime: currentTime.add(2, "hours"),
|
||||
subEntries: null,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const output = currentTime;
|
||||
|
|
@ -9,6 +9,7 @@ import {
|
|||
LoadSuccess,
|
||||
replaceTimekeepCodeblock,
|
||||
extractTimekeepCodeblocks,
|
||||
extractTimekeepCodeblocksWithPosition,
|
||||
} from "./parser";
|
||||
import { Timekeep, stripTimekeepRuntimeData } from "./schema";
|
||||
|
||||
|
|
@ -40,6 +41,50 @@ describe("extracting code blocks", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("extracting code blocks with position", () => {
|
||||
it("should extract codeblock contents", async () => {
|
||||
const { text, inputTimekeep1, inputTimekeep2 } =
|
||||
await import("./__fixtures__/extracting/codeblockContentsPosition");
|
||||
|
||||
const output = extractTimekeepCodeblocksWithPosition(text);
|
||||
|
||||
expect(stripTimekeepRuntimeData(output[0].timekeep)).toStrictEqual(
|
||||
stripTimekeepRuntimeData(inputTimekeep1)
|
||||
);
|
||||
expect(output[0].startLine).toEqual(7);
|
||||
expect(output[0].endLine).toEqual(9);
|
||||
expect(stripTimekeepRuntimeData(output[1].timekeep)).toStrictEqual(
|
||||
stripTimekeepRuntimeData(inputTimekeep2)
|
||||
);
|
||||
|
||||
expect(output[1].startLine).toEqual(21);
|
||||
expect(output[1].endLine).toEqual(23);
|
||||
expect(output.length).toBe(2);
|
||||
});
|
||||
|
||||
it("should ignore codeblocks that are not closed", async () => {
|
||||
const { text, inputTimekeep1 } =
|
||||
await import("./__fixtures__/extracting/unclosedCodeBlockPosition");
|
||||
const output = extractTimekeepCodeblocksWithPosition(text);
|
||||
|
||||
expect(stripTimekeepRuntimeData(output[0].timekeep)).toStrictEqual(
|
||||
stripTimekeepRuntimeData(inputTimekeep1)
|
||||
);
|
||||
expect(output[0].startLine).toEqual(7);
|
||||
expect(output[0].endLine).toEqual(9);
|
||||
expect(output.length).toBe(1);
|
||||
});
|
||||
|
||||
it("should ignore codeblocks that are not closed", async () => {
|
||||
const consoleError = vi.spyOn(console, "error").mockImplementation(() => {});
|
||||
const { text } = await import("./__fixtures__/extracting/invalidCodeBlockContentPosition");
|
||||
const output = extractTimekeepCodeblocksWithPosition(text);
|
||||
|
||||
expect(output.length).toBe(0);
|
||||
expect(consoleError).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("replacing content", () => {
|
||||
it("should replace codeblock contents", () => {
|
||||
const lineStart = 4; // Line the codeblock should start on
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
getEntryDuration,
|
||||
getTotalDuration,
|
||||
getEntriesNames,
|
||||
getStartTime,
|
||||
} from "./queries";
|
||||
import { TimeEntry } from "./schema";
|
||||
|
||||
|
|
@ -29,6 +30,14 @@ describe("getEntryById", () => {
|
|||
expect(output).toEqual(targetEntry);
|
||||
});
|
||||
|
||||
it("find nested entry second element", async () => {
|
||||
const { input, targetEntry, targetEntryId } =
|
||||
await import("./__fixtures__/checking/findEntryByIdNestedSecond");
|
||||
|
||||
const output = getEntryById(targetEntryId, input);
|
||||
expect(output).toEqual(targetEntry);
|
||||
});
|
||||
|
||||
it("find entry non existent", async () => {
|
||||
const { input, targetEntryId } =
|
||||
await import("./__fixtures__/checking/findEntryByIdMissing");
|
||||
|
|
@ -36,6 +45,14 @@ describe("getEntryById", () => {
|
|||
const output = getEntryById(targetEntryId, input);
|
||||
expect(output).toBeUndefined();
|
||||
});
|
||||
|
||||
it("find entry non existent nested", async () => {
|
||||
const { input, targetEntryId } =
|
||||
await import("./__fixtures__/checking/findEntryByIdMissingNested");
|
||||
|
||||
const output = getEntryById(targetEntryId, input);
|
||||
expect(output).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("getPathToEntry", () => {
|
||||
|
|
@ -45,9 +62,31 @@ describe("getPathToEntry", () => {
|
|||
expect(output).toEqual(expected);
|
||||
});
|
||||
|
||||
it("top level path found", () => {});
|
||||
it("top level path found", async () => {
|
||||
const { targetEntry, entries, expected } = await import("./__fixtures__/path/pathTopLevel");
|
||||
const output = getPathToEntry(entries, targetEntry);
|
||||
expect(output).toEqual(expected);
|
||||
});
|
||||
|
||||
it("deep path found", () => {});
|
||||
it("child path found", async () => {
|
||||
const { targetEntry, entries, expected } = await import("./__fixtures__/path/pathChild");
|
||||
const output = getPathToEntry(entries, targetEntry);
|
||||
expect(output).toEqual(expected);
|
||||
});
|
||||
|
||||
it("deep child path found", async () => {
|
||||
const { targetEntry, entries, expected } =
|
||||
await import("./__fixtures__/path/pathDeepChild");
|
||||
const output = getPathToEntry(entries, targetEntry);
|
||||
expect(output).toEqual(expected);
|
||||
});
|
||||
|
||||
it("deep child path not found", async () => {
|
||||
const { targetEntry, entries, expected } =
|
||||
await import("./__fixtures__/path/pathNotFoundDeep");
|
||||
const output = getPathToEntry(entries, targetEntry);
|
||||
expect(output).toEqual(expected);
|
||||
});
|
||||
|
||||
it("should find running entry path", async () => {
|
||||
const { input, runningEntry, path } =
|
||||
|
|
@ -203,3 +242,11 @@ describe("getEntriesNames", () => {
|
|||
expect(outputSet).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getStartTime", () => {
|
||||
it("should pick the earliest start time", async () => {
|
||||
const { entry, output } = await import("./__fixtures__/startTime/earlyStartTime");
|
||||
|
||||
expect(getStartTime(entry, false)).toEqual(output);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -170,8 +170,8 @@ function makeEntrySingle(target: TimeEntry): TimeEntry {
|
|||
return target;
|
||||
}
|
||||
|
||||
// Don't collapse if more than 1 entry
|
||||
if (target.subEntries.length > 1) {
|
||||
// Don't collapse if more than 1 entry or no entries at all
|
||||
if (target.subEntries.length != 1) {
|
||||
return target;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue