import { afterEach, describe, expect, it } from "bun:test" import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs" import { join } from "node:path" import { tmpdir } from "node:os" const originalXdgDataHome = process.env.XDG_DATA_HOME function createDataHomePath(): string { return join(tmpdir(), `posthog-activity-state-${Date.now()}-${Math.random()}`) } async function importPostHogActivityStateModule(): Promise { return import(`./posthog-activity-state?test=${Date.now()}-${Math.random()}`) } afterEach(() => { if (originalXdgDataHome === undefined) { delete process.env.XDG_DATA_HOME } else { process.env.XDG_DATA_HOME = originalXdgDataHome } }) describe("getPostHogActivityCaptureState", () => { it("returns default state when activity file contains null", async () => { // given const dataHomePath = createDataHomePath() const cachePath = join(dataHomePath, "oh-my-opencode") mkdirSync(cachePath, { recursive: true }) writeFileSync(join(cachePath, "posthog-activity.json"), "null\n") process.env.XDG_DATA_HOME = dataHomePath const { getPostHogActivityCaptureState } = await importPostHogActivityStateModule() // when const result = getPostHogActivityCaptureState(new Date("2026-04-11T10:15:00.000Z")) // then expect(result).toEqual({ dayUTC: "2026-04-11", captureDaily: true, }) rmSync(dataHomePath, { recursive: true, force: true }) }) it("returns default state when activity file contains an array", async () => { // given const dataHomePath = createDataHomePath() const cachePath = join(dataHomePath, "oh-my-opencode") mkdirSync(cachePath, { recursive: true }) writeFileSync(join(cachePath, "posthog-activity.json"), "[]\n") process.env.XDG_DATA_HOME = dataHomePath const { getPostHogActivityCaptureState } = await importPostHogActivityStateModule() // when const result = getPostHogActivityCaptureState(new Date("2026-04-11T10:15:00.000Z")) // then expect(result).toEqual({ dayUTC: "2026-04-11", captureDaily: true, }) rmSync(dataHomePath, { recursive: true, force: true }) }) it("returns default state when activity file contains a number", async () => { // given const dataHomePath = createDataHomePath() const cachePath = join(dataHomePath, "oh-my-opencode") mkdirSync(cachePath, { recursive: true }) writeFileSync(join(cachePath, "posthog-activity.json"), "42\n") process.env.XDG_DATA_HOME = dataHomePath const { getPostHogActivityCaptureState } = await importPostHogActivityStateModule() // when const result = getPostHogActivityCaptureState(new Date("2026-04-11T10:15:00.000Z")) // then expect(result).toEqual({ dayUTC: "2026-04-11", captureDaily: true, }) rmSync(dataHomePath, { recursive: true, force: true }) }) it("reads valid activity state JSON", async () => { // given const dataHomePath = createDataHomePath() const cachePath = join(dataHomePath, "oh-my-opencode") mkdirSync(cachePath, { recursive: true }) writeFileSync( join(cachePath, "posthog-activity.json"), `${JSON.stringify({ lastActiveDayUTC: "2026-04-11", lastActiveHourUTC: "2026-04-11T10", })}\n`, ) process.env.XDG_DATA_HOME = dataHomePath const { getPostHogActivityCaptureState } = await importPostHogActivityStateModule() // when const result = getPostHogActivityCaptureState(new Date("2026-04-11T10:15:00.000Z")) // then expect(result).toEqual({ dayUTC: "2026-04-11", captureDaily: false, }) rmSync(dataHomePath, { recursive: true, force: true }) }) it("reads legacy hourly state without crashing", async () => { // given const dataHomePath = createDataHomePath() const cachePath = join(dataHomePath, "oh-my-opencode") mkdirSync(cachePath, { recursive: true }) writeFileSync( join(cachePath, "posthog-activity.json"), `${JSON.stringify({ lastActiveHourUTC: "2026-04-11T10", })}\n`, ) process.env.XDG_DATA_HOME = dataHomePath const { getPostHogActivityCaptureState } = await importPostHogActivityStateModule() // when const result = getPostHogActivityCaptureState(new Date("2026-04-11T10:15:00.000Z")) // then expect(result).toEqual({ dayUTC: "2026-04-11", captureDaily: true, }) rmSync(dataHomePath, { recursive: true, force: true }) }) it("preserves unrelated state fields when writing lastActiveDayUTC", async () => { // given const dataHomePath = createDataHomePath() const cachePath = join(dataHomePath, "oh-my-opencode") mkdirSync(cachePath, { recursive: true }) writeFileSync( join(cachePath, "posthog-activity.json"), `${JSON.stringify({ lastActiveDayUTC: "2026-04-10", lastPluginLoadedDayUTC: "2026-04-11", })}\n`, ) process.env.XDG_DATA_HOME = dataHomePath const { getPostHogActivityCaptureState } = await importPostHogActivityStateModule() // when getPostHogActivityCaptureState(new Date("2026-04-11T10:15:00.000Z")) // then const persistedState = JSON.parse( readFileSync(join(cachePath, "posthog-activity.json"), "utf-8"), ) expect(persistedState).toEqual({ lastActiveDayUTC: "2026-04-11", lastPluginLoadedDayUTC: "2026-04-11", }) rmSync(dataHomePath, { recursive: true, force: true }) }) })