/**
 * Constitution Tests
 *
 * Tests for the constitution schema, loader, and evaluation logic.
 *
 * @module __tests__/autofix/constitution
 */
import { describe, it, expect } from "vitest";
import { ConstitutionSchema, DEFAULT_CONSTITUTION, } from "../../autofix/constitution.schema.js";
import { isPathAllowed, isPatternApproved, getEffectivePatterns, validateConstitution, generateDefaultConstitution, } from "../../autofix/constitution.js";
describe("Constitution Schema", () => {
    describe("validation", () => {
        it("accepts valid constitution with required fields", () => {
            const valid = {
                version: "1.0",
                riskTolerance: "moderate",
                patterns: [],
            };
            expect(() => ConstitutionSchema.parse(valid)).not.toThrow();
        });
        it("provides defaults for missing optional fields", () => {
            const minimal = { version: "1.0" };
            const parsed = ConstitutionSchema.parse(minimal);
            expect(parsed.riskTolerance).toBe("conservative");
            expect(parsed.patterns).toEqual([]);
            expect(parsed.prRules.requireApproval).toBe(true);
            expect(parsed.prRules.minApprovers).toBe(1);
            expect(parsed.prRules.groupBy).toBe("severity");
            expect(parsed.safety.dryRunDefault).toBe(true);
            expect(parsed.safety.maxFilesPerRun).toBe(20);
        });
        it("rejects invalid version", () => {
            const invalid = { version: "2.0" };
            expect(() => ConstitutionSchema.parse(invalid)).toThrow();
        });
        it("rejects invalid risk tolerance", () => {
            const invalid = { version: "1.0", riskTolerance: "reckless" };
            expect(() => ConstitutionSchema.parse(invalid)).toThrow();
        });
        it("validates pattern approvals", () => {
            const valid = {
                version: "1.0",
                patterns: [
                    {
                        patternId: "qual-console-log",
                        autoApprove: true,
                    },
                    {
                        patternId: "sec-sql-injection",
                        autoApprove: false,
                        requiredReviewer: "security-team",
                    },
                ],
            };
            const parsed = ConstitutionSchema.parse(valid);
            expect(parsed.patterns).toHaveLength(2);
            expect(parsed.patterns[0].autoApprove).toBe(true);
            expect(parsed.patterns[1].requiredReviewer).toBe("security-team");
        });
        it("validates pattern conditions", () => {
            const valid = {
                version: "1.0",
                patterns: [
                    {
                        patternId: "type-explicit-any",
                        autoApprove: true,
                        conditions: {
                            excludedPaths: ["src/legacy/"],
                            maxLinesChanged: 10,
                            minSeverity: "medium",
                        },
                    },
                ],
            };
            const parsed = ConstitutionSchema.parse(valid);
            expect(parsed.patterns[0].conditions?.excludedPaths).toContain("src/legacy/");
            expect(parsed.patterns[0].conditions?.maxLinesChanged).toBe(10);
        });
    });
    describe("DEFAULT_CONSTITUTION", () => {
        it("has conservative risk tolerance", () => {
            expect(DEFAULT_CONSTITUTION.riskTolerance).toBe("conservative");
        });
        it("has dry run enabled by default", () => {
            expect(DEFAULT_CONSTITUTION.safety.dryRunDefault).toBe(true);
        });
        it("has standard never-autofix directories", () => {
            expect(DEFAULT_CONSTITUTION.directories.neverAutofix).toContain("node_modules");
            expect(DEFAULT_CONSTITUTION.directories.neverAutofix).toContain("vendor");
        });
    });
});
describe("isPathAllowed", () => {
    const constitution = {
        ...DEFAULT_CONSTITUTION,
        directories: {
            neverAutofix: ["node_modules", "vendor", "dist"],
            requireReview: ["src/auth/", "src/crypto/"],
            ignore: [],
        },
    };
    it("allows regular source files", () => {
        const result = isPathAllowed(constitution, "src/utils/helpers.ts");
        expect(result.allowed).toBe(true);
        expect(result.requiresReview).toBe(false);
    });
    it("blocks node_modules paths", () => {
        const result = isPathAllowed(constitution, "node_modules/lodash/index.js");
        expect(result.allowed).toBe(false);
        expect(result.reason).toContain("never-autofix");
    });
    it("blocks vendor paths", () => {
        const result = isPathAllowed(constitution, "vendor/libs/jquery.js");
        expect(result.allowed).toBe(false);
    });
    it("blocks dist paths", () => {
        const result = isPathAllowed(constitution, "dist/bundle.js");
        expect(result.allowed).toBe(false);
    });
    it("allows but flags require-review paths", () => {
        const result = isPathAllowed(constitution, "src/auth/login.ts");
        expect(result.allowed).toBe(true);
        expect(result.requiresReview).toBe(true);
        expect(result.reason).toContain("review");
    });
    it("flags crypto paths for review", () => {
        const result = isPathAllowed(constitution, "src/crypto/encryption.ts");
        expect(result.allowed).toBe(true);
        expect(result.requiresReview).toBe(true);
    });
});
describe("isPatternApproved", () => {
    const mockPattern = {
        patternId: "test-pattern",
        name: "Test Pattern",
        description: "Test",
        matchPattern: /test/,
        replacement: "test",
        safeToAutoApply: true,
        risk: "low",
    };
    const highRiskPattern = {
        ...mockPattern,
        patternId: "high-risk-pattern",
        safeToAutoApply: false,
        risk: "high",
    };
    describe("conservative risk tolerance", () => {
        const constitution = {
            ...DEFAULT_CONSTITUTION,
            riskTolerance: "conservative",
        };
        it("approves safe, low-risk patterns", () => {
            const result = isPatternApproved(constitution, mockPattern, {
                filePath: "src/test.ts",
                severity: "medium",
            });
            expect(result.approved).toBe(true);
        });
        it("rejects high-risk patterns", () => {
            const result = isPatternApproved(constitution, highRiskPattern, {
                filePath: "src/test.ts",
                severity: "medium",
            });
            expect(result.approved).toBe(false);
            expect(result.reason).toContain("Conservative mode");
        });
        it("rejects unsafe patterns even with low risk", () => {
            const unsafePattern = {
                ...mockPattern,
                safeToAutoApply: false,
                risk: "low",
            };
            const result = isPatternApproved(constitution, unsafePattern, {
                filePath: "src/test.ts",
                severity: "medium",
            });
            expect(result.approved).toBe(false);
        });
    });
    describe("moderate risk tolerance", () => {
        const constitution = {
            ...DEFAULT_CONSTITUTION,
            riskTolerance: "moderate",
        };
        it("approves safe patterns", () => {
            const result = isPatternApproved(constitution, mockPattern, {
                filePath: "src/test.ts",
                severity: "medium",
            });
            expect(result.approved).toBe(true);
        });
        it("approves medium-risk patterns", () => {
            const mediumRiskPattern = {
                ...mockPattern,
                safeToAutoApply: false,
                risk: "medium",
            };
            const result = isPatternApproved(constitution, mediumRiskPattern, {
                filePath: "src/test.ts",
                severity: "medium",
            });
            expect(result.approved).toBe(true);
        });
        it("rejects high-risk patterns", () => {
            const result = isPatternApproved(constitution, highRiskPattern, {
                filePath: "src/test.ts",
                severity: "medium",
            });
            expect(result.approved).toBe(false);
            expect(result.reason).toContain("Moderate mode");
        });
    });
    describe("aggressive risk tolerance", () => {
        const constitution = {
            ...DEFAULT_CONSTITUTION,
            riskTolerance: "aggressive",
        };
        it("approves all patterns", () => {
            const result = isPatternApproved(constitution, highRiskPattern, {
                filePath: "src/test.ts",
                severity: "medium",
            });
            expect(result.approved).toBe(true);
        });
    });
    describe("pattern-specific rules", () => {
        it("respects explicit autoApprove: true", () => {
            const constitution = {
                ...DEFAULT_CONSTITUTION,
                riskTolerance: "conservative",
                patterns: [
                    {
                        patternId: "high-risk-pattern",
                        autoApprove: true,
                    },
                ],
            };
            const result = isPatternApproved(constitution, highRiskPattern, {
                filePath: "src/test.ts",
                severity: "medium",
            });
            expect(result.approved).toBe(true);
        });
        it("respects explicit autoApprove: false with reviewer", () => {
            const constitution = {
                ...DEFAULT_CONSTITUTION,
                riskTolerance: "aggressive",
                patterns: [
                    {
                        patternId: "test-pattern",
                        autoApprove: false,
                        requiredReviewer: "security-team",
                    },
                ],
            };
            const result = isPatternApproved(constitution, mockPattern, {
                filePath: "src/test.ts",
                severity: "medium",
            });
            expect(result.approved).toBe(false);
            expect(result.requiredReviewer).toBe("security-team");
        });
        it("enforces excluded paths condition", () => {
            const constitution = {
                ...DEFAULT_CONSTITUTION,
                patterns: [
                    {
                        patternId: "test-pattern",
                        autoApprove: true,
                        conditions: {
                            excludedPaths: ["src/legacy/"],
                        },
                    },
                ],
            };
            const result = isPatternApproved(constitution, mockPattern, {
                filePath: "src/legacy/old-code.ts",
                severity: "medium",
            });
            expect(result.approved).toBe(false);
            expect(result.reason).toContain("excluded paths");
        });
        it("enforces allowed paths condition", () => {
            const constitution = {
                ...DEFAULT_CONSTITUTION,
                patterns: [
                    {
                        patternId: "test-pattern",
                        autoApprove: true,
                        conditions: {
                            allowedPaths: ["src/safe/"],
                        },
                    },
                ],
            };
            const result = isPatternApproved(constitution, mockPattern, {
                filePath: "src/other/code.ts",
                severity: "medium",
            });
            expect(result.approved).toBe(false);
            expect(result.reason).toContain("not in allowed paths");
        });
        it("enforces maxLinesChanged condition", () => {
            const constitution = {
                ...DEFAULT_CONSTITUTION,
                patterns: [
                    {
                        patternId: "test-pattern",
                        autoApprove: true,
                        conditions: {
                            maxLinesChanged: 5,
                        },
                    },
                ],
            };
            const result = isPatternApproved(constitution, mockPattern, {
                filePath: "src/test.ts",
                severity: "medium",
                linesChanged: 10,
            });
            expect(result.approved).toBe(false);
            expect(result.reason).toContain("exceeds max");
        });
        it("enforces minSeverity condition", () => {
            const constitution = {
                ...DEFAULT_CONSTITUTION,
                patterns: [
                    {
                        patternId: "test-pattern",
                        autoApprove: true,
                        conditions: {
                            minSeverity: "high",
                        },
                    },
                ],
            };
            const result = isPatternApproved(constitution, mockPattern, {
                filePath: "src/test.ts",
                severity: "medium",
            });
            expect(result.approved).toBe(false);
            expect(result.reason).toContain("below minimum");
        });
    });
});
describe("getEffectivePatterns", () => {
    const patterns = [
        {
            patternId: "safe-pattern",
            name: "Safe",
            description: "Safe pattern",
            matchPattern: /safe/,
            replacement: "safe",
            safeToAutoApply: true,
            risk: "low",
        },
        {
            patternId: "unsafe-pattern",
            name: "Unsafe",
            description: "Unsafe pattern",
            matchPattern: /unsafe/,
            replacement: "unsafe",
            safeToAutoApply: false,
            risk: "high",
        },
    ];
    it("respects pattern-specific overrides", () => {
        const constitution = {
            ...DEFAULT_CONSTITUTION,
            patterns: [
                {
                    patternId: "unsafe-pattern",
                    autoApprove: true,
                },
            ],
        };
        const effective = getEffectivePatterns(constitution, patterns);
        const unsafePattern = effective.find((p) => p.patternId === "unsafe-pattern");
        expect(unsafePattern?.safeToAutoApply).toBe(true);
    });
    it("applies risk tolerance to patterns without overrides", () => {
        const constitution = {
            ...DEFAULT_CONSTITUTION,
            riskTolerance: "aggressive",
        };
        const effective = getEffectivePatterns(constitution, patterns);
        const unsafePattern = effective.find((p) => p.patternId === "unsafe-pattern");
        expect(unsafePattern?.safeToAutoApply).toBe(true);
    });
});
describe("validateConstitution", () => {
    it("returns valid for correct constitution", () => {
        const result = validateConstitution({
            version: "1.0",
            riskTolerance: "moderate",
        });
        expect(result.valid).toBe(true);
        expect(result.errors).toBeUndefined();
    });
    it("returns errors for invalid constitution", () => {
        const result = validateConstitution({
            version: "2.0", // Invalid version
        });
        expect(result.valid).toBe(false);
        expect(result.errors).toBeDefined();
        expect(result.errors?.length).toBeGreaterThan(0);
    });
});
describe("generateDefaultConstitution", () => {
    it("generates valid YAML content", () => {
        const content = generateDefaultConstitution();
        expect(content).toContain("version:");
        expect(content).toContain("riskTolerance:");
        expect(content).toContain("patterns:");
        expect(content).toContain("prRules:");
        expect(content).toContain("directories:");
        expect(content).toContain("safety:");
    });
});
//# sourceMappingURL=constitution.test.js.map