← back to Kickbacks Ai Upstream

test/outdatedCliNotice.test.ts

56 lines

import { describe, it, expect, beforeEach, vi } from "vitest";

// Mute dlog so the helper doesn't append to the developer's real
// ~/.vibe-ads/debug.log during tests (same reason incompatNotice.test.ts mocks it).
vi.mock("../src/log", () => ({ dlog: () => {} }));

import { notifyOutdatedCli } from "../src/activation/outdatedCliNotice";
import { SPINNER_VERBS_FLOOR, type SemVer } from "../src/adapters/claude-cli/cliVersion";
import { makeContext, _warned } from "./mocks/vscode";

const OLD: SemVer = [2, 0, 14];

describe("notifyOutdatedCli", () => {
  beforeEach(() => { _warned.length = 0; });

  it("warns exactly once per detected version (reload never re-nags)", () => {
    const ctx = makeContext() as never;
    notifyOutdatedCli(ctx, OLD);
    notifyOutdatedCli(ctx, OLD); // reload — deduped via globalState
    expect(_warned.length).toBe(1);
  });

  it("names the detected version, the floor, and the fix", () => {
    notifyOutdatedCli(makeContext() as never, OLD);
    const floor = SPINNER_VERBS_FLOOR.join(".");
    expect(_warned[0]).toContain("2.0.14");
    expect(_warned[0]).toContain(floor);
    expect(_warned[0]).toContain("claude update");
  });

  it("re-warns once for a DIFFERENT old version", () => {
    const ctx = makeContext() as never;
    notifyOutdatedCli(ctx, OLD);
    notifyOutdatedCli(ctx, [2, 1, 100]);
    expect(_warned.length).toBe(2);
    expect(_warned[1]).toContain("2.1.100");
  });

  it("dedupe is per-context-state, keyed by version (fresh install re-notifies)", () => {
    notifyOutdatedCli(makeContext() as never, OLD);
    notifyOutdatedCli(makeContext() as never, OLD); // new globalState
    expect(_warned.length).toBe(2);
  });

  it("never throws when globalState is broken (best-effort contract)", () => {
    const ctx = {
      globalState: {
        get: () => { throw new Error("storage dead"); },
        update: () => { throw new Error("storage dead"); },
      },
    } as never;
    expect(() => notifyOutdatedCli(ctx, OLD)).not.toThrow();
    expect(_warned.length).toBe(0); // threw before the toast — but silently
  });
});