Ctrl K
ComunidadGuías…

test/shared/build-tag.test.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
/**
 * Tests for the release-tag format shared between build-edge.ts (which
 * writes .build-tag) and src/shared/update.ts (which parses tags from
 * GitHub releases to decide whether a newer version is available).
 *
 * Any drift between these two halves silently breaks self-update, so the
 * roundtrip tests here are the single source of truth for the tag format.
 */

import { expect } from "@std/expect";
import { describe, it as test } from "@std/testing/bdd";
import { isoToTag } from "#shared/build-tag.ts";
import {
  isNewerVersion,
  parseReleaseTag,
  setBuildTimestampForTest,
} from "#shared/update.ts";

const RELEASE_TAG_FORMAT = /^v\d{4}-\d{2}-\d{2}-\d{6}$/;

describe("isoToTag", () => {
  test("produces the vYYYY-MM-DD-HHMMSS format the release workflow expects", () => {
    expect(isoToTag("2026-03-28T14:30:22.000Z")).toBe("v2026-03-28-143022");
  });

  test("matches the shape parsed by parseReleaseTag", () => {
    const tag = isoToTag(new Date().toISOString());
    expect(tag).toMatch(RELEASE_TAG_FORMAT);
  });

  test("uses UTC so local timezone does not shift the tag", () => {
    const iso = "2026-06-15T23:59:59.000Z";
    const tag = isoToTag(iso);
    expect(tag).toBe("v2026-06-15-235959");
    expect(tag).toBe(isoToTag(new Date(iso).toISOString()));
  });

  test("zero-pads single-digit month/day/hour/minute/second", () => {
    expect(isoToTag("2026-01-02T03:04:05.000Z")).toBe("v2026-01-02-030405");
  });

  test("rounds down sub-second precision (releases are second-resolution)", () => {
    expect(isoToTag("2026-03-28T14:30:22.999Z")).toBe("v2026-03-28-143022");
  });
});

describe("isoToTag / parseReleaseTag roundtrip", () => {
  test("parseReleaseTag recovers the original ISO timestamp (to the second)", () => {
    const iso = "2026-03-28T14:30:22.000Z";
    const parsed = parseReleaseTag(isoToTag(iso));
    expect(parsed).not.toBeNull();
    expect(parsed!.toISOString()).toBe(iso);
  });

  test("roundtrips a freshly built timestamp", () => {
    const now = new Date();
    now.setUTCMilliseconds(0);
    const parsed = parseReleaseTag(isoToTag(now.toISOString()));
    expect(parsed?.getTime()).toBe(now.getTime());
  });

  test("isNewerVersion treats a tag built from a later timestamp as newer", () => {
    setBuildTimestampForTest("2026-01-01T00:00:00.000Z");
    try {
      const newerTag = isoToTag("2026-02-01T00:00:00.000Z");
      expect(isNewerVersion(newerTag)).toBe(true);
    } finally {
      setBuildTimestampForTest(null);
    }
  });

  test("isNewerVersion treats a tag built from the same timestamp as not newer", () => {
    const iso = "2026-03-28T14:30:22.000Z";
    setBuildTimestampForTest(iso);
    try {
      expect(isNewerVersion(isoToTag(iso))).toBe(false);
    } finally {
      setBuildTimestampForTest(null);
    }
  });

  test("isNewerVersion treats an earlier tag as not newer", () => {
    setBuildTimestampForTest("2026-03-01T00:00:00.000Z");
    try {
      const olderTag = isoToTag("2026-01-01T00:00:00.000Z");
      expect(isNewerVersion(olderTag)).toBe(false);
    } finally {
      setBuildTimestampForTest(null);
    }
  });

  test("isNewerVersion returns false (never throws) for an unparseable tag", () => {
    // Guard must short-circuit before dereferencing the null parsed date, even
    // when a real build timestamp is present.
    setBuildTimestampForTest("2026-01-01T00:00:00.000Z");
    try {
      expect(isNewerVersion("not-a-release-tag")).toBe(false);
    } finally {
      setBuildTimestampForTest(null);
    }
  });

  test("isNewerVersion returns false when the build timestamp is empty", () => {
    // Development/source builds carry no timestamp; nothing is ever "newer".
    setBuildTimestampForTest("");
    try {
      const tag = isoToTag("2026-02-01T00:00:00.000Z");
      expect(isNewerVersion(tag)).toBe(false);
    } finally {
      setBuildTimestampForTest(null);
    }
  });
});