import { describe, it, expect, vi } from "vitest"; import "reflect-metadata"; import { Container } from "inversify"; import { wireUseCase } from "@/conformance/wire-use-case"; import { isInstrumented, isCaptured, isAudited, isAnalyzed, isRateLimited, } from "@/conformance/brand-runtime"; import type { ITracer, ISpan, SpanOpts, } from "@/instrumentation/tracer.interface"; import type { ILogger } from "@/instrumentation/logger.interface"; import type { AuditLogProtocol, AnalyticsProtocol } from "@/di/bind-protocols"; import { NoopRateLimit } from "@/rate-limit/noop-rate-limit"; function makeTracer() { const calls: SpanOpts[] = []; const tracer: ITracer = { startSpan: vi.fn(async (opts, fn) => { calls.push(opts); const span: ISpan = { setAttribute: () => {}, setStatus: () => {} }; return fn(span); }), }; return { tracer, calls }; } function makeLogger(): ILogger & { captureException: ReturnType; } { return { captureException: vi.fn(), captureMessage: vi.fn(), addBreadcrumb: vi.fn(), setUser: vi.fn(), }; } function makeAuditLog(): AuditLogProtocol { return { record: vi.fn() }; } function makeAnalytics(): AnalyticsProtocol { return { track: vi.fn() }; } const doubleFactory = () => async (x: number) => x * 2; describe("wireUseCase — no-audit path", () => { it("attaches Instrumented + Captured brands, no Audited brand", () => { const { tracer } = makeTracer(); const logger = makeLogger(); const container = new Container(); const sym = Symbol("test.double"); const wired = wireUseCase({ container, symbol: sym, factory: doubleFactory, deps: [], feature: "test", layer: "use-case", name: "double", tracer, logger, }); expect(isInstrumented(wired)).toBe(true); expect(isCaptured(wired)).toBe(true); expect(isAudited(wired)).toBe(false); }); it("executes the factory result on invocation", async () => { const { tracer } = makeTracer(); const logger = makeLogger(); const container = new Container(); const sym = Symbol("test.double"); const wired = wireUseCase({ container, symbol: sym, factory: doubleFactory, deps: [], feature: "test", layer: "use-case", name: "double", tracer, logger, }); await expect(wired(3)).resolves.toBe(6); }); }); describe("wireUseCase — audit path", () => { it("attaches Instrumented + Captured + Audited brands when auditLog is provided", () => { const { tracer } = makeTracer(); const logger = makeLogger(); const container = new Container(); const sym = Symbol("test.double"); const auditLog = makeAuditLog(); const wired = wireUseCase({ container, symbol: sym, factory: doubleFactory, deps: [], feature: "test", layer: "use-case", name: "double", tracer, logger, auditLog, }); expect(isInstrumented(wired)).toBe(true); expect(isCaptured(wired)).toBe(true); expect(isAudited(wired)).toBe(true); }); it("executes the factory result on invocation (audit path)", async () => { const { tracer } = makeTracer(); const logger = makeLogger(); const container = new Container(); const sym = Symbol("test.double"); const auditLog = makeAuditLog(); const wired = wireUseCase({ container, symbol: sym, factory: doubleFactory, deps: [], feature: "test", layer: "use-case", name: "double", tracer, logger, auditLog, }); await expect(wired(5)).resolves.toBe(10); }); }); describe("wireUseCase — span-name derivation", () => { it("derives span name as . and uses layer as op", async () => { const { tracer, calls } = makeTracer(); const logger = makeLogger(); const container = new Container(); const sym = Symbol("auth.signIn"); const wired = wireUseCase({ container, symbol: sym, factory: doubleFactory, deps: [], feature: "auth", layer: "use-case", name: "signIn", tracer, logger, }); await wired(1); expect(calls).toHaveLength(1); expect(calls[0]).toMatchObject({ name: "auth.signIn", op: "use-case" }); }); }); describe("wireUseCase — capture-tag structure", () => { it("captures with { feature, layer, name: '.' } when an error is thrown", async () => { const { tracer } = makeTracer(); const logger = makeLogger(); const container = new Container(); const sym = Symbol("blog.getArticles"); const err = new Error("boom"); const wired = wireUseCase({ container, symbol: sym, factory: () => async () => { throw err; }, deps: [], feature: "blog", layer: "use-case", name: "getArticles", tracer, logger, }); await expect(wired()).rejects.toBe(err); expect(logger.captureException).toHaveBeenCalledWith(err, { tags: { feature: "blog", layer: "use-case", name: "blog.getArticles" }, }); }); }); describe("wireUseCase — container binding", () => { it("binds the wired value to the container symbol", () => { const { tracer } = makeTracer(); const logger = makeLogger(); const container = new Container(); const sym = Symbol("test.double"); const wired = wireUseCase({ container, symbol: sym, factory: doubleFactory, deps: [], feature: "test", layer: "use-case", name: "double", tracer, logger, }); expect(container.get(sym)).toBe(wired); }); it("passes deps tuple to the factory", async () => { const { tracer } = makeTracer(); const logger = makeLogger(); const container = new Container(); const sym = Symbol("test.scale"); const scaleFactory = (multiplier: number) => async (x: number) => x * multiplier; const wired = wireUseCase({ container, symbol: sym, factory: scaleFactory, deps: [3] as [number], feature: "test", layer: "use-case", name: "scale", tracer, logger, }); await expect(wired(4)).resolves.toBe(12); }); }); describe("wireUseCase — analytics path", () => { it("attaches Analyzed brand when analytics is provided", () => { const { tracer } = makeTracer(); const logger = makeLogger(); const container = new Container(); const sym = Symbol("test.double"); const analytics = makeAnalytics(); const wired = wireUseCase({ container, symbol: sym, factory: doubleFactory, deps: [], feature: "test", layer: "use-case", name: "double", tracer, logger, analytics, }); expect(isAnalyzed(wired)).toBe(true); expect(isInstrumented(wired)).toBe(true); expect(isCaptured(wired)).toBe(true); }); it("attaches Analyzed + Audited brands when both analytics and auditLog are provided", () => { const { tracer } = makeTracer(); const logger = makeLogger(); const container = new Container(); const sym = Symbol("test.double"); const analytics = makeAnalytics(); const auditLog = makeAuditLog(); const wired = wireUseCase({ container, symbol: sym, factory: doubleFactory, deps: [], feature: "test", layer: "use-case", name: "double", tracer, logger, analytics, auditLog, }); expect(isAnalyzed(wired)).toBe(true); expect(isAudited(wired)).toBe(true); expect(isInstrumented(wired)).toBe(true); expect(isCaptured(wired)).toBe(true); }); it("executes the factory result on invocation (analytics path)", async () => { const { tracer } = makeTracer(); const logger = makeLogger(); const container = new Container(); const sym = Symbol("test.double"); const analytics = makeAnalytics(); const wired = wireUseCase({ container, symbol: sym, factory: doubleFactory, deps: [], feature: "test", layer: "use-case", name: "double", tracer, logger, analytics, }); await expect(wired(7)).resolves.toBe(14); }); }); describe("wireUseCase — no-analytics path", () => { it("does not attach Analyzed brand when analytics is absent", () => { const { tracer } = makeTracer(); const logger = makeLogger(); const container = new Container(); const sym = Symbol("test.double"); const wired = wireUseCase({ container, symbol: sym, factory: doubleFactory, deps: [], feature: "test", layer: "use-case", name: "double", tracer, logger, }); expect(isAnalyzed(wired)).toBe(false); }); }); describe("wireUseCase — idempotent re-bind", () => { it("unbinds the existing binding and replaces it when the symbol is already bound", () => { const { tracer } = makeTracer(); const logger = makeLogger(); const container = new Container(); const sym = Symbol("test.double"); wireUseCase({ container, symbol: sym, factory: doubleFactory, deps: [], feature: "test", layer: "use-case", name: "double", tracer, logger, }); const second = wireUseCase({ container, symbol: sym, factory: doubleFactory, deps: [], feature: "test", layer: "use-case", name: "double", tracer, logger, }); expect(container.get(sym)).toBe(second); }); }); describe("wireUseCase — rate limit path", () => { it("attaches RateLimited brand when rateLimit is provided", () => { const { tracer } = makeTracer(); const logger = makeLogger(); const container = new Container(); const sym = Symbol("test.double"); const rateLimit = new NoopRateLimit(); const wired = wireUseCase({ container, symbol: sym, factory: doubleFactory, deps: [], feature: "test", layer: "use-case", name: "double", tracer, logger, rateLimit, }); expect(isRateLimited(wired)).toBe(true); expect(isInstrumented(wired)).toBe(true); expect(isCaptured(wired)).toBe(true); }); it("does not attach RateLimited brand when rateLimit is absent", () => { const { tracer } = makeTracer(); const logger = makeLogger(); const container = new Container(); const sym = Symbol("test.double"); const wired = wireUseCase({ container, symbol: sym, factory: doubleFactory, deps: [], feature: "test", layer: "use-case", name: "double", tracer, logger, }); expect(isRateLimited(wired)).toBe(false); }); it("executes factory correctly when rateLimit is provided", async () => { const { tracer } = makeTracer(); const logger = makeLogger(); const container = new Container(); const sym = Symbol("test.double"); const rateLimit = new NoopRateLimit(); const wired = wireUseCase({ container, symbol: sym, factory: doubleFactory, deps: [], feature: "test", layer: "use-case", name: "double", tracer, logger, rateLimit, }); await expect(wired(5)).resolves.toBe(10); }); it("attaches RateLimited + Analyzed brands when both rateLimit and analytics are provided", () => { const { tracer } = makeTracer(); const logger = makeLogger(); const container = new Container(); const sym = Symbol("test.double"); const rateLimit = new NoopRateLimit(); const analytics = makeAnalytics(); const wired = wireUseCase({ container, symbol: sym, factory: doubleFactory, deps: [], feature: "test", layer: "use-case", name: "double", tracer, logger, rateLimit, analytics, }); expect(isRateLimited(wired)).toBe(true); expect(isAnalyzed(wired)).toBe(true); expect(isInstrumented(wired)).toBe(true); expect(isCaptured(wired)).toBe(true); }); it("attaches RateLimited + Audited brands when both rateLimit and auditLog are provided", () => { const { tracer } = makeTracer(); const logger = makeLogger(); const container = new Container(); const sym = Symbol("test.double"); const rateLimit = new NoopRateLimit(); const auditLog = makeAuditLog(); const wired = wireUseCase({ container, symbol: sym, factory: doubleFactory, deps: [], feature: "test", layer: "use-case", name: "double", tracer, logger, rateLimit, auditLog, }); expect(isRateLimited(wired)).toBe(true); expect(isAudited(wired)).toBe(true); expect(isInstrumented(wired)).toBe(true); expect(isCaptured(wired)).toBe(true); }); });