import { describe, expect, test } from "bun:test"; import { Provider } from "../../src/providers/base"; import type { ProviderResult } from "../../src/providers/types"; class TestProvider extends Provider { constructor(patterns?: Record) { super("filesystem", "test", patterns); } async execute(): Promise { return this.success("test-data"); } } describe("Provider base class", () => { test("failure returns ProviderResult with success: false", () => { const p = new TestProvider(); const result = p["failure"]("something broke"); expect(result.success).toBe(false); expect(result.provider).toBe("filesystem"); expect(result.service).toBe("test"); expect(result.size).toBe(0); expect(result.error).toBeInstanceOf(Error); expect(result.error!.message).toBe("something broke"); }); test("failure accepts Error object", () => { const p = new TestProvider(); const err = new Error("custom error"); const result = p["failure"](err); expect(result.error).toBe(err); }); test("success returns ProviderResult with success: true", () => { const p = new TestProvider(); const result = p["success"]("hello world"); expect(result.success).toBe(true); expect(result.provider).toBe("filesystem"); expect(result.service).toBe("test"); expect(result.data).toBe("hello world"); expect(result.size).toBeGreaterThan(0); }); test("success serializes objects to JSON", () => { const p = new TestProvider(); const data = { key: "value", nested: { deep: true } }; const result = p["success"](data); expect(result.data).toEqual(data); expect(result.size).toBe(JSON.stringify(data).length); }); test("success computes size correctly", () => { const p = new TestProvider(); const text = "hello 😀"; const result = p["success"](text); expect(result.size).toBe(Buffer.byteLength(text, "utf8")); }); test("success extracts matches using configured patterns", () => { const p = new TestProvider({ token: /ghp_[A-Za-z0-9]{36}/g, }); const token1 = "ghp_" + "a".repeat(36); const token2 = "ghp_" + "b".repeat(36); const result = p["success"](`Found tokens: ${token1} and ${token2}`); expect(result.matches).toBeDefined(); expect(result.matches!["token"]).toBeDefined(); expect(result.matches!["token"].length).toBeGreaterThanOrEqual(1); }); test("success deduplicates token matches", () => { const p = new TestProvider({ token: /ghp_[A-Za-z0-9]{36}/g, }); const result = p["success"]("ghp_abcdefghijklmnopqrstuvwxyz1234567890 ghp_abcdefghijklmnopqrstuvwxyz1234567890"); expect(result.matches!["token"]).toHaveLength(1); }); test("success supports string patterns converted to RegExp", () => { const p = new TestProvider({ justString: "[A-Za-z]+", }); const result = p["success"]("Hello World 123 !@#"); expect(result.matches!["justString"]).toContain("Hello"); expect(result.matches!["justString"]).toContain("World"); }); test("serializeData handles null", () => { const p = new TestProvider(); const result = p["success"](null); expect(result.size).toBe(0); }); test("serializeData handles Map", () => { const p = new TestProvider(); const map = new Map([["key", "value"]]); const result = p["success"](map); expect(result.data).toBeInstanceOf(Map); expect(result.size).toBe(JSON.stringify({ key: "value" }).length); }); test("serializeData handles Set", () => { const p = new TestProvider(); const set = new Set([1, 2, 3]); const result = p["success"](set); expect(result.data).toBeInstanceOf(Set); expect(result.size).toBe(JSON.stringify([1, 2, 3]).length); }); });