/**
 * Tests for Chat Notifications
 */
import { describe, it, expect, beforeEach, vi } from "vitest";
import { SlackClient, TeamsClient, DiscordClient, ChatClient, MultiPlatformNotifier, createSlackClient, createTeamsClient, createDiscordClient, createChatClient, createMultiPlatformNotifier, } from "./chat.js";
// Mock fetch
const mockFetch = vi.fn();
global.fetch = mockFetch;
describe("SlackClient", () => {
    let client;
    beforeEach(() => {
        vi.clearAllMocks();
        client = new SlackClient("https://hooks.slack.com/services/xxx/yyy/zzz");
    });
    describe("sendNotification", () => {
        it("sends notification successfully", async () => {
            mockFetch.mockResolvedValueOnce({ ok: true });
            const notification = {
                certificationId: "cert-123",
                target: "test-repo",
                status: "completed",
                score: 85,
                grade: "B",
            };
            const result = await client.sendNotification(notification);
            expect(result.success).toBe(true);
            expect(result.platform).toBe("slack");
            expect(result.timestamp).toBeDefined();
        });
        it("includes findings summary", async () => {
            mockFetch.mockResolvedValueOnce({ ok: true });
            const notification = {
                certificationId: "cert-123",
                target: "test-repo",
                status: "completed",
                score: 75,
                findings: {
                    total: 10,
                    critical: 1,
                    high: 2,
                    medium: 3,
                    low: 3,
                    info: 1,
                },
            };
            await client.sendNotification(notification);
            expect(mockFetch).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
                body: expect.stringContaining("Critical"),
            }));
        });
        it("includes top findings", async () => {
            mockFetch.mockResolvedValueOnce({ ok: true });
            const notification = {
                certificationId: "cert-123",
                target: "test-repo",
                status: "completed",
                findings: {
                    total: 3,
                    critical: 1,
                    high: 1,
                    medium: 1,
                    low: 0,
                    info: 0,
                    topFindings: [
                        { id: "f1", severity: "critical", description: "SQL injection found in login form" },
                    ],
                },
            };
            await client.sendNotification(notification);
            expect(mockFetch).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
                body: expect.stringContaining("Top Findings"),
            }));
        });
        it("includes report link button", async () => {
            mockFetch.mockResolvedValueOnce({ ok: true });
            const notification = {
                certificationId: "cert-123",
                target: "test-repo",
                status: "completed",
                reportUrl: "https://app.example.com/reports/cert-123",
            };
            await client.sendNotification(notification);
            expect(mockFetch).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
                body: expect.stringContaining("View Full Report"),
            }));
        });
        it("handles webhook failure", async () => {
            mockFetch.mockResolvedValueOnce({ ok: false, status: 403 });
            const notification = {
                certificationId: "cert-123",
                target: "test-repo",
                status: "started",
            };
            const result = await client.sendNotification(notification);
            expect(result.success).toBe(false);
            expect(result.error).toContain("403");
        });
        it("handles network errors", async () => {
            mockFetch.mockRejectedValueOnce(new Error("Network error"));
            const notification = {
                certificationId: "cert-123",
                target: "test-repo",
                status: "started",
            };
            const result = await client.sendNotification(notification);
            expect(result.success).toBe(false);
            expect(result.error).toContain("Network error");
        });
        it("uses correct emoji for different statuses", async () => {
            mockFetch.mockResolvedValue({ ok: true });
            // Started
            await client.sendNotification({
                certificationId: "c1",
                target: "repo",
                status: "started",
            });
            expect(mockFetch).toHaveBeenLastCalledWith(expect.any(String), expect.objectContaining({
                body: expect.stringContaining("🔄"),
            }));
            // Failed
            await client.sendNotification({
                certificationId: "c2",
                target: "repo",
                status: "failed",
            });
            expect(mockFetch).toHaveBeenLastCalledWith(expect.any(String), expect.objectContaining({
                body: expect.stringContaining("❌"),
            }));
            // High score
            await client.sendNotification({
                certificationId: "c3",
                target: "repo",
                status: "completed",
                score: 95,
            });
            expect(mockFetch).toHaveBeenLastCalledWith(expect.any(String), expect.objectContaining({
                body: expect.stringContaining("🏆"),
            }));
        });
    });
});
describe("TeamsClient", () => {
    let client;
    beforeEach(() => {
        vi.clearAllMocks();
        client = new TeamsClient("https://outlook.office.com/webhook/xxx");
    });
    describe("sendNotification", () => {
        it("sends adaptive card notification", async () => {
            mockFetch.mockResolvedValueOnce({ ok: true });
            const notification = {
                certificationId: "cert-123",
                target: "test-repo",
                status: "completed",
                score: 85,
            };
            const result = await client.sendNotification(notification);
            expect(result.success).toBe(true);
            expect(result.platform).toBe("teams");
            expect(mockFetch).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
                body: expect.stringContaining("AdaptiveCard"),
            }));
        });
        it("includes FactSet for findings", async () => {
            mockFetch.mockResolvedValueOnce({ ok: true });
            const notification = {
                certificationId: "cert-123",
                target: "test-repo",
                status: "completed",
                findings: {
                    total: 5,
                    critical: 0,
                    high: 1,
                    medium: 2,
                    low: 1,
                    info: 1,
                },
            };
            await client.sendNotification(notification);
            expect(mockFetch).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
                body: expect.stringContaining("FactSet"),
            }));
        });
        it("includes action button for report", async () => {
            mockFetch.mockResolvedValueOnce({ ok: true });
            const notification = {
                certificationId: "cert-123",
                target: "test-repo",
                status: "completed",
                reportUrl: "https://reports.example.com/123",
            };
            await client.sendNotification(notification);
            expect(mockFetch).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
                body: expect.stringContaining("Action.OpenUrl"),
            }));
        });
        it("handles webhook failure", async () => {
            mockFetch.mockResolvedValueOnce({ ok: false, status: 404 });
            const result = await client.sendNotification({
                certificationId: "cert-123",
                target: "test-repo",
                status: "started",
            });
            expect(result.success).toBe(false);
            expect(result.error).toContain("404");
        });
    });
});
describe("DiscordClient", () => {
    let client;
    beforeEach(() => {
        vi.clearAllMocks();
        client = new DiscordClient("https://discord.com/api/webhooks/xxx/yyy");
    });
    describe("sendNotification", () => {
        it("sends embed notification", async () => {
            mockFetch.mockResolvedValueOnce({ ok: true });
            const notification = {
                certificationId: "cert-123",
                target: "test-repo",
                status: "completed",
                score: 90,
            };
            const result = await client.sendNotification(notification);
            expect(result.success).toBe(true);
            expect(result.platform).toBe("discord");
            expect(mockFetch).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
                body: expect.stringContaining("embeds"),
            }));
        });
        it("includes findings in embed fields", async () => {
            mockFetch.mockResolvedValueOnce({ ok: true });
            const notification = {
                certificationId: "cert-123",
                target: "test-repo",
                status: "completed",
                findings: {
                    total: 8,
                    critical: 0,
                    high: 2,
                    medium: 3,
                    low: 2,
                    info: 1,
                },
            };
            await client.sendNotification(notification);
            expect(mockFetch).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
                body: expect.stringContaining("Findings"),
            }));
        });
        it("uses correct embed colors", async () => {
            mockFetch.mockResolvedValue({ ok: true });
            // Green for high score
            await client.sendNotification({
                certificationId: "c1",
                target: "repo",
                status: "completed",
                score: 85,
            });
            expect(mockFetch).toHaveBeenLastCalledWith(expect.any(String), expect.objectContaining({
                body: expect.stringContaining("3066993"), // Green
            }));
            // Orange for medium score
            await client.sendNotification({
                certificationId: "c2",
                target: "repo",
                status: "completed",
                score: 55,
            });
            expect(mockFetch).toHaveBeenLastCalledWith(expect.any(String), expect.objectContaining({
                body: expect.stringContaining("15965202"), // Orange (0xf39c12)
            }));
            // Red for failed
            await client.sendNotification({
                certificationId: "c3",
                target: "repo",
                status: "failed",
            });
            expect(mockFetch).toHaveBeenLastCalledWith(expect.any(String), expect.objectContaining({
                body: expect.stringContaining("15158332"), // Red
            }));
        });
        it("includes report link in field", async () => {
            mockFetch.mockResolvedValueOnce({ ok: true });
            const notification = {
                certificationId: "cert-123",
                target: "test-repo",
                status: "completed",
                reportUrl: "https://reports.example.com/123",
            };
            await client.sendNotification(notification);
            expect(mockFetch).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
                body: expect.stringContaining("reports.example.com"),
            }));
        });
        it("includes footer and timestamp", async () => {
            mockFetch.mockResolvedValueOnce({ ok: true });
            await client.sendNotification({
                certificationId: "cert-123",
                target: "test-repo",
                status: "completed",
            });
            expect(mockFetch).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
                body: expect.stringContaining("Vaspera Hardening MCP"),
            }));
        });
    });
});
describe("ChatClient", () => {
    beforeEach(() => {
        vi.clearAllMocks();
        mockFetch.mockResolvedValue({ ok: true });
    });
    describe("constructor", () => {
        it("creates Slack client", () => {
            const client = new ChatClient({
                platform: "slack",
                webhookUrl: "https://hooks.slack.com/xxx",
            });
            expect(client.getPlatform()).toBe("slack");
        });
        it("creates Teams client", () => {
            const client = new ChatClient({
                platform: "teams",
                webhookUrl: "https://outlook.office.com/webhook/xxx",
            });
            expect(client.getPlatform()).toBe("teams");
        });
        it("creates Discord client", () => {
            const client = new ChatClient({
                platform: "discord",
                webhookUrl: "https://discord.com/api/webhooks/xxx",
            });
            expect(client.getPlatform()).toBe("discord");
        });
        it("throws for unsupported platform", () => {
            expect(() => new ChatClient({
                platform: "telegram",
                webhookUrl: "https://example.com",
            })).toThrow("Unsupported chat platform");
        });
    });
    describe("sendNotification", () => {
        it("delegates to underlying client", async () => {
            const client = new ChatClient({
                platform: "slack",
                webhookUrl: "https://hooks.slack.com/xxx",
            });
            const result = await client.sendNotification({
                certificationId: "cert-123",
                target: "test-repo",
                status: "completed",
            });
            expect(result.success).toBe(true);
            expect(mockFetch).toHaveBeenCalled();
        });
    });
});
describe("MultiPlatformNotifier", () => {
    beforeEach(() => {
        vi.clearAllMocks();
        mockFetch.mockResolvedValue({ ok: true });
    });
    describe("addPlatform", () => {
        it("adds multiple platforms", () => {
            const notifier = new MultiPlatformNotifier();
            notifier.addPlatform({
                platform: "slack",
                webhookUrl: "https://hooks.slack.com/xxx",
            });
            notifier.addPlatform({
                platform: "discord",
                webhookUrl: "https://discord.com/api/webhooks/xxx",
            });
            // Should be able to send to both
            expect(notifier).toBeDefined();
        });
    });
    describe("sendNotification", () => {
        it("sends to all platforms", async () => {
            const notifier = new MultiPlatformNotifier();
            notifier.addPlatform({
                platform: "slack",
                webhookUrl: "https://hooks.slack.com/xxx",
            });
            notifier.addPlatform({
                platform: "teams",
                webhookUrl: "https://outlook.office.com/webhook/xxx",
            });
            notifier.addPlatform({
                platform: "discord",
                webhookUrl: "https://discord.com/api/webhooks/xxx",
            });
            const results = await notifier.sendNotification({
                certificationId: "cert-123",
                target: "test-repo",
                status: "completed",
            });
            expect(results).toHaveLength(3);
            expect(results.every((r) => r.success)).toBe(true);
            expect(mockFetch).toHaveBeenCalledTimes(3);
        });
        it("handles partial failures", async () => {
            mockFetch
                .mockResolvedValueOnce({ ok: true })
                .mockResolvedValueOnce({ ok: false, status: 500 })
                .mockResolvedValueOnce({ ok: true });
            const notifier = new MultiPlatformNotifier();
            notifier.addPlatform({
                platform: "slack",
                webhookUrl: "https://hooks.slack.com/xxx",
            });
            notifier.addPlatform({
                platform: "teams",
                webhookUrl: "https://outlook.office.com/webhook/xxx",
            });
            notifier.addPlatform({
                platform: "discord",
                webhookUrl: "https://discord.com/api/webhooks/xxx",
            });
            const results = await notifier.sendNotification({
                certificationId: "cert-123",
                target: "test-repo",
                status: "completed",
            });
            expect(results[0].success).toBe(true);
            expect(results[1].success).toBe(false);
            expect(results[2].success).toBe(true);
        });
    });
    describe("notifyFindings", () => {
        it("creates notification from findings", async () => {
            const notifier = new MultiPlatformNotifier();
            notifier.addPlatform({
                platform: "slack",
                webhookUrl: "https://hooks.slack.com/xxx",
            });
            const findings = [
                {
                    id: "f1",
                    severity: "critical",
                    category: "vulnerability",
                    description: "SQL injection",
                    evidence: "",
                    confidence: 95,
                    verifications: [],
                    created_at: new Date().toISOString(),
                },
                {
                    id: "f2",
                    severity: "high",
                    category: "code-quality",
                    description: "Hardcoded credentials",
                    evidence: "",
                    confidence: 90,
                    verifications: [],
                    created_at: new Date().toISOString(),
                },
                {
                    id: "f3",
                    severity: "medium",
                    category: "code-quality",
                    description: "Missing input validation",
                    evidence: "",
                    confidence: 85,
                    verifications: [],
                    created_at: new Date().toISOString(),
                },
            ];
            const results = await notifier.notifyFindings("cert-123", "test-repo", findings, 65, "https://reports.example.com/123");
            expect(results).toHaveLength(1);
            expect(results[0].success).toBe(true);
            // Verify the body contains finding summary
            const body = JSON.parse(mockFetch.mock.calls[0][1].body);
            expect(body.blocks).toBeDefined();
        });
        it("calculates correct grade", async () => {
            const notifier = new MultiPlatformNotifier();
            notifier.addPlatform({
                platform: "slack",
                webhookUrl: "https://hooks.slack.com/xxx",
            });
            await notifier.notifyFindings("c1", "repo", [], 95);
            expect(mockFetch).toHaveBeenLastCalledWith(expect.any(String), expect.objectContaining({
                body: expect.stringContaining("A"),
            }));
            await notifier.notifyFindings("c2", "repo", [], 85);
            expect(mockFetch).toHaveBeenLastCalledWith(expect.any(String), expect.objectContaining({
                body: expect.stringContaining("B"),
            }));
            await notifier.notifyFindings("c3", "repo", [], 55);
            expect(mockFetch).toHaveBeenLastCalledWith(expect.any(String), expect.objectContaining({
                body: expect.stringContaining("F"),
            }));
        });
        it("extracts top findings by severity", async () => {
            const notifier = new MultiPlatformNotifier();
            notifier.addPlatform({
                platform: "slack",
                webhookUrl: "https://hooks.slack.com/xxx",
            });
            const findings = [
                {
                    id: "low-finding",
                    severity: "low",
                    category: "style",
                    description: "Minor style issue",
                    evidence: "",
                    confidence: 80,
                    verifications: [],
                    created_at: new Date().toISOString(),
                },
                {
                    id: "critical-finding",
                    severity: "critical",
                    category: "vulnerability",
                    description: "Critical security issue",
                    evidence: "",
                    confidence: 95,
                    verifications: [],
                    created_at: new Date().toISOString(),
                },
            ];
            await notifier.notifyFindings("cert-123", "repo", findings, 50);
            // Critical should appear first in top findings
            expect(mockFetch).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
                body: expect.stringContaining("critical-finding"),
            }));
        });
    });
});
describe("Factory Functions", () => {
    it("createSlackClient creates Slack client", () => {
        const client = createSlackClient("https://hooks.slack.com/xxx");
        expect(client).toBeInstanceOf(SlackClient);
    });
    it("createTeamsClient creates Teams client", () => {
        const client = createTeamsClient("https://outlook.office.com/webhook/xxx");
        expect(client).toBeInstanceOf(TeamsClient);
    });
    it("createDiscordClient creates Discord client", () => {
        const client = createDiscordClient("https://discord.com/api/webhooks/xxx");
        expect(client).toBeInstanceOf(DiscordClient);
    });
    it("createChatClient creates ChatClient", () => {
        const client = createChatClient({
            platform: "slack",
            webhookUrl: "https://hooks.slack.com/xxx",
        });
        expect(client).toBeInstanceOf(ChatClient);
    });
    it("createMultiPlatformNotifier creates notifier", () => {
        const notifier = createMultiPlatformNotifier();
        expect(notifier).toBeInstanceOf(MultiPlatformNotifier);
    });
});
//# sourceMappingURL=chat.test.js.map