import { describe, expect, it } from "vitest";
import {
  projectDocumentUtf8ByteLength,
  serializedProjectDocumentUtf8ByteLength,
} from "./project-limits";

describe("project document byte limits", () => {
  it("counts the exact UTF-8 bytes emitted by indented JSON", () => {
    const values: readonly unknown[] = [
      {},
      { ascii: "text", control: "\0\n\t", unicode: "Grüße 😀" },
      [true, false, null, 12.5, Number.POSITIVE_INFINITY],
      { nested: [{ value: "\ud800" }, { value: "\udc00" }] },
    ];

    for (const value of values) {
      const serialized = JSON.stringify(value, null, 2);
      expect(projectDocumentUtf8ByteLength(value)).toBe(
        new TextEncoder().encode(serialized).byteLength,
      );
    }
  });

  it("checks UTF-8 bytes rather than JavaScript string length", () => {
    expect(serializedProjectDocumentUtf8ByteLength("é", 2)).toBe(2);
    expect(() => serializedProjectDocumentUtf8ByteLength("é", 1)).toThrow(
      /32 MiB/u,
    );
  });

  it("stops before an over-limit JSON document is materialized", () => {
    const value = { text: "\0".repeat(100) };
    const exact = new TextEncoder().encode(
      JSON.stringify(value, null, 2),
    ).byteLength;

    expect(projectDocumentUtf8ByteLength(value, exact)).toBe(exact);
    expect(() => projectDocumentUtf8ByteLength(value, exact - 1)).toThrow(
      /32 MiB/u,
    );
  });
});
