import { describe, it, expect, vi } from "vitest";
import { NoopTracer } from "@/instrumentation/noop-tracer";
import type { ISpan } from "@/instrumentation/tracer.interface";

describe("NoopTracer", () => {
  it("startSpan returns the function result", async () => {
    const tracer = new NoopTracer();
    const result = await tracer.startSpan({ name: "test.op" }, async () => 42);
    expect(result).toBe(42);
  });

  it("startSpan passes a no-op ISpan to the function", async () => {
    const tracer = new NoopTracer();
    let received: ISpan | undefined;
    await tracer.startSpan({ name: "test.op" }, async (span) => {
      received = span;
      return undefined;
    });
    expect(received).toBeDefined();
    expect(() => received!.setAttribute("k", "v")).not.toThrow();
    expect(() => received!.setStatus("ok")).not.toThrow();
    expect(() => received!.setStatus("error", "msg")).not.toThrow();
  });

  it("propagates exceptions from the wrapped function", async () => {
    const tracer = new NoopTracer();
    const err = new Error("boom");
    await expect(
      tracer.startSpan({ name: "test.op" }, async () => {
        throw err;
      }),
    ).rejects.toBe(err);
  });

  it("does not invoke external services", async () => {
    const tracer = new NoopTracer();
    const fn = vi.fn(async () => "ok");
    await tracer.startSpan({ name: "test.op" }, fn);
    expect(fn).toHaveBeenCalledTimes(1);
  });
});
