"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const logger_1 = __importDefault(require("../../../src/logger"));
const redteam_1 = require("../../../src/redteam");
const generate_1 = require("../../../src/redteam/commands/generate");
const configModule = __importStar(require("../../../src/util/config/load"));
const manage_1 = require("../../../src/util/config/manage");
jest.mock('fs');
jest.mock('../../../src/logger');
jest.mock('../../../src/redteam');
jest.mock('../../../src/telemetry');
jest.mock('../../../src/util/config/load', () => ({
    combineConfigs: jest.fn(),
    resolveConfigs: jest.fn(),
}));
jest.mock('../../../src/globalConfig/cloud', () => ({
    CloudConfig: jest.fn().mockImplementation(() => ({
        isEnabled: jest.fn().mockReturnValue(false),
        getApiHost: jest.fn().mockReturnValue('https://api.promptfoo.app'),
    })),
}));
jest.mock('../../../src/redteam/remoteGeneration', () => ({
    shouldGenerateRemote: jest.fn().mockReturnValue(false),
    neverGenerateRemote: jest.fn().mockReturnValue(false),
    getRemoteGenerationUrl: jest.fn().mockReturnValue('http://test-url'),
}));
jest.mock('../../../src/util/config/manage');
describe('doGenerateRedteam', () => {
    beforeEach(() => {
        jest.clearAllMocks();
        jest.mocked(configModule.resolveConfigs).mockResolvedValue({
            basePath: '/mock/path',
            testSuite: {
                prompts: [],
                providers: [],
            },
            config: {
                redteam: {
                    plugins: [],
                    strategies: [],
                },
            },
        });
    });
    it('should generate redteam tests and write to output file', async () => {
        jest.mocked(configModule.combineConfigs).mockResolvedValue([
            {
                prompts: [{ raw: 'Test prompt', label: 'Test label' }],
                providers: [],
                tests: [],
            },
        ]);
        const options = {
            output: 'output.yaml',
            config: 'config.yaml',
            cache: true,
            defaultConfig: {},
            write: true,
        };
        jest.mocked(fs_1.default.readFileSync).mockReturnValue(JSON.stringify({
            prompts: [{ raw: 'Test prompt' }],
            providers: [],
            tests: [],
        }));
        jest.mocked(redteam_1.synthesize).mockResolvedValue({
            testCases: [
                {
                    vars: { input: 'Test input' },
                    assert: [{ type: 'equals', value: 'Test output' }],
                    metadata: { pluginId: 'redteam' },
                },
            ],
            purpose: 'Test purpose',
            entities: ['Test entity'],
            injectVar: 'input',
        });
        await (0, generate_1.doGenerateRedteam)(options);
        expect(redteam_1.synthesize).toHaveBeenCalledWith(expect.objectContaining({
            language: undefined,
            numTests: undefined,
            plugins: expect.any(Array),
            prompts: [],
            strategies: expect.any(Array),
        }));
        expect(manage_1.writePromptfooConfig).toHaveBeenCalledWith(expect.objectContaining({
            prompts: [{ raw: 'Test prompt' }],
            providers: [],
            tests: [
                {
                    vars: { input: 'Test input' },
                    assert: [{ type: 'equals', value: 'Test output' }],
                    metadata: { pluginId: 'redteam' },
                },
            ],
            redteam: expect.objectContaining({
                purpose: 'Test purpose',
                entities: ['Test entity'],
            }),
            defaultTest: {
                metadata: {
                    purpose: 'Test purpose',
                    entities: ['Test entity'],
                },
            },
        }), 'output.yaml');
    });
    it('should write to config file when write option is true', async () => {
        const options = {
            config: 'config.yaml',
            cache: true,
            defaultConfig: {},
            write: true,
        };
        jest.mocked(fs_1.default.readFileSync).mockReturnValue(JSON.stringify({}));
        jest.mocked(redteam_1.synthesize).mockResolvedValue({
            testCases: [
                {
                    vars: { input: 'Test input' },
                    assert: [{ type: 'equals', value: 'Test output' }],
                    metadata: { pluginId: 'redteam' },
                },
            ],
            purpose: 'Test purpose',
            entities: [],
            injectVar: 'input',
        });
        await (0, generate_1.doGenerateRedteam)(options);
        expect(manage_1.writePromptfooConfig).toHaveBeenCalledWith(expect.objectContaining({
            defaultTest: {
                metadata: {
                    purpose: 'Test purpose',
                    entities: [],
                },
            },
            redteam: expect.objectContaining({
                purpose: 'Test purpose',
                entities: [],
            }),
            tests: [
                {
                    vars: { input: 'Test input' },
                    assert: [{ type: 'equals', value: 'Test output' }],
                    metadata: { pluginId: 'redteam' },
                },
            ],
        }), 'config.yaml');
    });
    it('should handle missing configuration file', async () => {
        const options = {
            cache: true,
            defaultConfig: {},
            write: true,
            output: 'redteam.yaml',
        };
        await (0, generate_1.doGenerateRedteam)(options);
        expect(logger_1.default.info).toHaveBeenCalledWith(expect.stringContaining("Can't generate without configuration"));
    });
    it('should use purpose when no config is provided', async () => {
        const options = {
            purpose: 'Test purpose',
            cache: true,
            defaultConfig: {},
            write: true,
            output: 'redteam.yaml',
        };
        jest.mocked(redteam_1.synthesize).mockResolvedValue({
            testCases: [
                {
                    vars: { input: 'Test input' },
                    assert: [{ type: 'equals', value: 'Test output' }],
                    metadata: { pluginId: 'redteam' },
                },
            ],
            purpose: 'Test purpose',
            entities: ['Test entity'],
            injectVar: 'input',
        });
        await (0, generate_1.doGenerateRedteam)(options);
        expect(redteam_1.synthesize).toHaveBeenCalledWith({
            language: undefined,
            numTests: undefined,
            purpose: 'Test purpose',
            plugins: expect.any(Array),
            prompts: expect.any(Array),
            strategies: expect.any(Array),
        });
        expect(manage_1.writePromptfooConfig).toHaveBeenCalledWith(expect.objectContaining({
            tests: expect.arrayContaining([
                expect.objectContaining({
                    vars: { input: 'Test input' },
                    assert: [{ type: 'equals', value: 'Test output' }],
                    metadata: { pluginId: 'redteam' },
                }),
            ]),
            redteam: expect.objectContaining({
                purpose: 'Test purpose',
                entities: ['Test entity'],
            }),
        }), 'redteam.yaml');
    });
    it('should properly handle numTests for both string and object-style plugins', async () => {
        jest.mocked(configModule.resolveConfigs).mockResolvedValue({
            basePath: '/mock/path',
            testSuite: {
                prompts: [{ raw: 'Test prompt', label: 'Test label' }],
                providers: [],
            },
            config: {
                redteam: {
                    numTests: 1, // Global setting
                    plugins: [
                        'contracts', // String-style plugin
                        { id: 'competitors' }, // Object-style plugin without override
                        { id: 'overreliance', numTests: 3 }, // Object-style plugin with override
                    ],
                    strategies: [],
                },
            },
        });
        jest.mocked(fs_1.default.readFileSync).mockReturnValue(JSON.stringify({
            prompts: [{ raw: 'Test prompt' }],
            providers: [],
            tests: [],
        }));
        jest.mocked(redteam_1.synthesize).mockResolvedValue({
            testCases: [
                {
                    vars: { input: 'Test input' },
                    assert: [{ type: 'equals', value: 'Test output' }],
                    metadata: { pluginId: 'redteam' },
                },
            ],
            purpose: 'Test purpose',
            entities: ['Test entity'],
            injectVar: 'input',
        });
        const options = {
            output: 'output.yaml',
            cache: true,
            defaultConfig: {},
            write: true,
            force: true,
            purpose: 'Test purpose',
            config: 'config.yaml',
        };
        await (0, generate_1.doGenerateRedteam)(options);
        expect(redteam_1.synthesize).toHaveBeenCalledTimes(1);
        expect(redteam_1.synthesize).toHaveBeenCalledWith(expect.objectContaining({
            language: undefined,
            numTests: 1,
            plugins: [
                expect.objectContaining({ id: 'competitors', numTests: 1 }), // Should inherit global numTests
                expect.objectContaining({ id: 'contracts', numTests: 1 }), // Should inherit global numTests
                expect.objectContaining({ id: 'overreliance', numTests: 3 }), // Should use its own numTests
            ],
            prompts: ['Test prompt'],
            strategies: [],
        }));
    });
    it('should pass entities from redteam config to synthesize', async () => {
        jest.mocked(configModule.resolveConfigs).mockResolvedValue({
            basePath: '/mock/path',
            testSuite: {
                prompts: [{ raw: 'Test prompt', label: 'Test label' }],
                providers: [],
            },
            config: {
                redteam: {
                    entities: ['Company X', 'John Doe', 'Product Y'],
                    plugins: ['harmful:hate'],
                    strategies: [],
                },
            },
        });
        jest.mocked(fs_1.default.readFileSync).mockReturnValue(JSON.stringify({
            prompts: [{ raw: 'Test prompt' }],
            providers: [],
            tests: [],
        }));
        jest.mocked(redteam_1.synthesize).mockResolvedValue({
            testCases: [
                {
                    vars: { input: 'Test input' },
                    assert: [{ type: 'equals', value: 'Test output' }],
                    metadata: { pluginId: 'redteam' },
                },
            ],
            purpose: 'Test purpose',
            entities: ['Company X', 'John Doe', 'Product Y'],
            injectVar: 'input',
        });
        const options = {
            output: 'output.yaml',
            cache: true,
            defaultConfig: {},
            write: true,
            force: true,
            config: 'config.yaml',
        };
        await (0, generate_1.doGenerateRedteam)(options);
        expect(redteam_1.synthesize).toHaveBeenCalledWith(expect.objectContaining({
            entities: ['Company X', 'John Doe', 'Product Y'],
            plugins: expect.any(Array),
            prompts: ['Test prompt'],
            strategies: expect.any(Array),
        }));
    });
    it('should handle undefined entities in redteam config', async () => {
        jest.mocked(configModule.resolveConfigs).mockResolvedValue({
            basePath: '/mock/path',
            testSuite: {
                prompts: [{ raw: 'Test prompt', label: 'Test label' }],
                providers: [],
            },
            config: {
                redteam: {
                    plugins: ['harmful:hate'],
                    strategies: [],
                },
            },
        });
        jest.mocked(fs_1.default.readFileSync).mockReturnValue(JSON.stringify({
            prompts: [{ raw: 'Test prompt' }],
            providers: [],
            tests: [],
        }));
        jest.mocked(redteam_1.synthesize).mockResolvedValue({
            testCases: [
                {
                    vars: { input: 'Test input' },
                    assert: [{ type: 'equals', value: 'Test output' }],
                    metadata: { pluginId: 'redteam' },
                },
            ],
            purpose: 'Test purpose',
            entities: [],
            injectVar: 'input',
        });
        const options = {
            output: 'output.yaml',
            cache: true,
            defaultConfig: {},
            write: true,
            force: true,
            config: 'config.yaml',
        };
        await (0, generate_1.doGenerateRedteam)(options);
        expect(redteam_1.synthesize).toHaveBeenCalledWith(expect.objectContaining({
            plugins: [expect.objectContaining({ id: 'harmful:hate', numTests: 5 })],
            prompts: ['Test prompt'],
            strategies: [],
            abortSignal: undefined,
            delay: undefined,
            language: undefined,
            maxConcurrency: undefined,
            numTests: undefined,
        }));
    });
    it('should write entities to output config', async () => {
        jest.mocked(configModule.resolveConfigs).mockResolvedValue({
            basePath: '/mock/path',
            testSuite: {
                prompts: [{ raw: 'Test prompt', label: 'Test label' }],
                providers: [],
            },
            config: {
                redteam: {
                    entities: ['Company X', 'John Doe', 'Product Y'],
                    plugins: ['harmful:hate'],
                    strategies: [],
                },
            },
        });
        jest.mocked(fs_1.default.readFileSync).mockReturnValue(JSON.stringify({
            prompts: [{ raw: 'Test prompt' }],
            providers: [],
            tests: [],
        }));
        jest.mocked(redteam_1.synthesize).mockResolvedValue({
            testCases: [
                {
                    vars: { input: 'Test input' },
                    assert: [{ type: 'equals', value: 'Test output' }],
                    metadata: { pluginId: 'redteam' },
                },
            ],
            purpose: 'Test purpose',
            entities: ['Company X', 'John Doe', 'Product Y'],
            injectVar: 'input',
        });
        const options = {
            output: 'output.yaml',
            cache: true,
            defaultConfig: {},
            write: true,
            force: true,
            config: 'config.yaml',
        };
        await (0, generate_1.doGenerateRedteam)(options);
        expect(manage_1.writePromptfooConfig).toHaveBeenCalledWith(expect.objectContaining({
            redteam: expect.objectContaining({
                entities: ['Company X', 'John Doe', 'Product Y'],
            }),
            defaultTest: expect.objectContaining({
                metadata: expect.objectContaining({
                    entities: ['Company X', 'John Doe', 'Product Y'],
                }),
            }),
        }), 'output.yaml');
    });
});
//# sourceMappingURL=generate.test.js.map