tests/reflection.test.ts
Rama main · réplica de lectura del repositorio original.
// The evening reflection (shared/reflection.ts): "How did the day go?"
// appends under `## Reflection` in the day's note — and never a second heading.
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import { appendReflection, EVENING_HOUR, isEvening, reflectionOf } from "../shared/reflection.ts";
describe("appending the reflection", () => {
it("adds the heading at the end of a note that has none", () => {
assert.equal(appendReflection("# Tuesday\n\nSome words.\n", "A good day."), "# Tuesday\n\nSome words.\n\n## Reflection\n\nA good day.\n");
});
it("writes into a template's empty section instead of adding a second heading", () => {
const template = "# Tuesday\n\n## Reflection\n\n## Tomorrow\n\n- [ ] call\n";
const out = appendReflection(template, "Slow, then good.");
assert.equal(out, "# Tuesday\n\n## Reflection\n\nSlow, then good.\n\n## Tomorrow\n\n- [ ] call\n");
assert.equal(out.match(/## Reflection/g)?.length, 1);
});
it("is idempotent in its heading: a second evening's line joins the first", () => {
const once = appendReflection("# Tuesday\n", "First.");
const twice = appendReflection(once, "Second.");
assert.equal(twice, "# Tuesday\n\n## Reflection\n\nFirst.\n\nSecond.\n");
assert.equal(twice.match(/## Reflection/g)?.length, 1);
});
it("finds the heading however it is cased, and leaves a `###` under it inside the section", () => {
const note = "## reflection\n\n### morning\nearly\n\n## Next\n";
assert.equal(appendReflection(note, "Late."), "## reflection\n\n### morning\nearly\n\nLate.\n\n## Next\n");
});
it("gives a heading that followed the section straight away its blank line back", () => {
assert.equal(appendReflection("## Reflection\n## Next\n", "Ok."), "## Reflection\n\nOk.\n\n## Next\n");
});
it("does not take a heading inside a code fence for the section", () => {
const note = "```\n## Reflection\n```\n";
assert.equal(appendReflection(note, "Real."), "```\n## Reflection\n```\n\n## Reflection\n\nReal.\n");
});
it("keeps the note's own line endings and the text's own lines", () => {
assert.equal(appendReflection("# Day\r\n", "one\ntwo"), "# Day\r\n\r\n## Reflection\r\n\r\none\r\ntwo\r\n");
});
it("writes nothing for an empty answer", () => {
assert.equal(appendReflection("# Day\n", " \n"), "# Day\n");
});
it("starts an empty note with the section alone", () => {
assert.equal(appendReflection("", "Fine."), "## Reflection\n\nFine.\n");
});
});
describe("reading the reflection back", () => {
it("is null with no heading, empty under a template's heading, and the text once written", () => {
assert.equal(reflectionOf("# Day\n"), null);
assert.equal(reflectionOf("## Reflection\n\n## Next\n"), "");
assert.equal(reflectionOf(appendReflection("# Day\n", "Good.")), "Good.");
});
});
describe("the evening", () => {
it("begins at six", () => {
assert.equal(EVENING_HOUR, 18);
assert.equal(isEvening(new Date(2026, 8, 23, 17, 59)), false);
assert.equal(isEvening(new Date(2026, 8, 23, 18, 0)), true);
assert.equal(isEvening(new Date(2026, 8, 23, 23, 59)), true);
});
});