test: add deterministic task behaviour tests
This commit is contained in:
159
tests/tasks.test.cjs
Normal file
159
tests/tasks.test.cjs
Normal file
@@ -0,0 +1,159 @@
|
||||
const assert = require("node:assert/strict");
|
||||
const fs = require("node:fs");
|
||||
const os = require("node:os");
|
||||
const path = require("node:path");
|
||||
const test = require("node:test");
|
||||
|
||||
const {
|
||||
archiveTask,
|
||||
createTask,
|
||||
getTask,
|
||||
listTasks,
|
||||
updateTask,
|
||||
} = require("../.test-build/lib/tasks.js");
|
||||
const { closeDatabaseForTests } = require("../.test-build/lib/db.js");
|
||||
|
||||
function useThrowawayDatabase(t) {
|
||||
const directory = fs.mkdtempSync(path.join(os.tmpdir(), "planner-tests-"));
|
||||
const databasePath = path.join(directory, "tasks.sqlite");
|
||||
|
||||
process.env.TASKS_DB_PATH = databasePath;
|
||||
|
||||
t.after(() => {
|
||||
closeDatabaseForTests();
|
||||
delete process.env.TASKS_DB_PATH;
|
||||
fs.rmSync(directory, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
return databasePath;
|
||||
}
|
||||
|
||||
test("creating a task persists all four required fields", (t) => {
|
||||
useThrowawayDatabase(t);
|
||||
|
||||
const created = createTask({
|
||||
title: "Finish Lab 1",
|
||||
description: "Wire the planner to SQLite",
|
||||
dueDate: "2026-08-20",
|
||||
topic: "Academic",
|
||||
});
|
||||
|
||||
const reloaded = getTask(created.id);
|
||||
|
||||
assert.equal(reloaded.title, "Finish Lab 1");
|
||||
assert.equal(reloaded.description, "Wire the planner to SQLite");
|
||||
assert.equal(reloaded.dueDate, "2026-08-20");
|
||||
assert.equal(reloaded.topic, "Academic");
|
||||
assert.equal(reloaded.status, "Todo");
|
||||
assert.equal(reloaded.archivedAt, null);
|
||||
});
|
||||
|
||||
test("editing a task persists the changed fields and status", (t) => {
|
||||
useThrowawayDatabase(t);
|
||||
|
||||
const created = createTask({
|
||||
title: "Draft notes",
|
||||
description: "Initial wording",
|
||||
dueDate: "2026-08-21",
|
||||
topic: "Academic",
|
||||
});
|
||||
|
||||
const edited = updateTask(created.id, {
|
||||
title: "Submit notes",
|
||||
description: "Final wording",
|
||||
dueDate: "2026-08-22",
|
||||
topic: "Work",
|
||||
status: "In-Progress",
|
||||
});
|
||||
const reloaded = getTask(created.id);
|
||||
|
||||
assert.equal(edited.title, "Submit notes");
|
||||
assert.equal(reloaded.description, "Final wording");
|
||||
assert.equal(reloaded.dueDate, "2026-08-22");
|
||||
assert.equal(reloaded.topic, "Work");
|
||||
assert.equal(reloaded.status, "In-Progress");
|
||||
});
|
||||
|
||||
test("archiving marks a task archived without deleting it", (t) => {
|
||||
useThrowawayDatabase(t);
|
||||
|
||||
const created = createTask({
|
||||
title: "Old task",
|
||||
description: "Keep for records",
|
||||
dueDate: "2026-08-23",
|
||||
topic: "Personal",
|
||||
});
|
||||
|
||||
const archived = archiveTask(created.id);
|
||||
const activeTasks = listTasks();
|
||||
const allTasks = listTasks({ includeArchived: true });
|
||||
|
||||
assert.equal(typeof archived.archivedAt, "string");
|
||||
assert.equal(getTask(created.id).id, created.id);
|
||||
assert.equal(activeTasks.some((task) => task.id === created.id), false);
|
||||
assert.equal(allTasks.some((task) => task.id === created.id), true);
|
||||
});
|
||||
|
||||
test("overdue is derived from due date and is not stored as a status", (t) => {
|
||||
useThrowawayDatabase(t);
|
||||
|
||||
const overdue = createTask({
|
||||
title: "Past task",
|
||||
description: "This date has passed",
|
||||
dueDate: "2000-01-01",
|
||||
topic: "Work",
|
||||
});
|
||||
const future = createTask({
|
||||
title: "Future task",
|
||||
description: "This date has not passed",
|
||||
dueDate: "2999-01-01",
|
||||
topic: "Work",
|
||||
});
|
||||
const completed = updateTask(overdue.id, { status: "Complete" });
|
||||
|
||||
assert.equal(overdue.status, "Todo");
|
||||
assert.equal(overdue.isOverdue, true);
|
||||
assert.equal(future.isOverdue, false);
|
||||
assert.equal(completed.status, "Complete");
|
||||
assert.equal(completed.isOverdue, false);
|
||||
assert.notEqual(completed.status, "Overdue");
|
||||
});
|
||||
|
||||
test("sorting by topic, status, and due date is deterministic", (t) => {
|
||||
useThrowawayDatabase(t);
|
||||
|
||||
const work = createTask({
|
||||
title: "Work item",
|
||||
description: "Second topic alphabetically",
|
||||
dueDate: "2026-09-03",
|
||||
topic: "Work",
|
||||
});
|
||||
const academic = createTask({
|
||||
title: "Academic item",
|
||||
description: "First topic alphabetically",
|
||||
dueDate: "2026-09-02",
|
||||
topic: "Academic",
|
||||
});
|
||||
const personal = createTask({
|
||||
title: "Personal item",
|
||||
description: "Earliest due date",
|
||||
dueDate: "2026-09-01",
|
||||
topic: "Personal",
|
||||
});
|
||||
|
||||
updateTask(work.id, { status: "Complete" });
|
||||
updateTask(academic.id, { status: "In-Progress" });
|
||||
|
||||
assert.deepEqual(
|
||||
listTasks({ sort: "topic" }).map((task) => task.topic),
|
||||
["Academic", "Personal", "Work"]
|
||||
);
|
||||
assert.deepEqual(
|
||||
listTasks({ sort: "status" }).map((task) => task.status),
|
||||
["Todo", "In-Progress", "Complete"]
|
||||
);
|
||||
assert.deepEqual(
|
||||
listTasks({ sort: "dueDate" }).map((task) => task.id),
|
||||
[personal.id, academic.id, work.id]
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user