UNPKG

@craftapit/tester

Version:

A focused, LLM-powered testing framework for natural language test scenarios

133 lines (132 loc) 4.79 kB
"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; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.loadConfig = loadConfig; const fs = __importStar(require("fs/promises")); const path = __importStar(require("path")); async function loadConfig(configPath, cliOptions) { // Default configuration let config = { browser: { headless: false }, llm: { provider: 'openai', model: 'gpt-4' }, logging: { level: 'info', screenshots: true } }; // Load from config file if provided if (configPath) { try { const configFile = await fs.readFile(path.resolve(configPath), 'utf-8'); const fileConfig = JSON.parse(configFile); config = mergeConfigs(config, fileConfig); } catch (error) { console.warn(`Warning: Could not load config file: ${configPath}`); } } else { // Try to load from default locations const defaultLocations = [ './craft-a-tester.json', './craftatester.json', './config/craft-a-tester.json', './.craft-a-tester.json' ]; for (const location of defaultLocations) { try { const configFile = await fs.readFile(path.resolve(location), 'utf-8'); const fileConfig = JSON.parse(configFile); config = mergeConfigs(config, fileConfig); break; } catch (error) { // Ignore errors, just try the next location } } } // Override with CLI options if (cliOptions) { if (cliOptions.headless !== undefined) { config.browser = { ...config.browser, headless: cliOptions.headless }; } if (cliOptions.model || cliOptions.provider || cliOptions.apiKey) { config.llm = { ...config.llm, ...(cliOptions.model && { model: cliOptions.model }), ...(cliOptions.provider && { provider: cliOptions.provider }), ...(cliOptions.apiKey && { apiKey: cliOptions.apiKey }) }; } } // Load API keys from environment if not provided if (config.llm && !config.llm.apiKey) { if (config.llm.provider === 'openai') { config.llm.apiKey = process.env.OPENAI_API_KEY; } else if (config.llm.provider === 'anthropic') { config.llm.apiKey = process.env.ANTHROPIC_API_KEY; } } return config; } /** * Helper function to merge configs with proper handling of nested properties */ function mergeConfigs(baseConfig, overrideConfig) { const result = { ...baseConfig }; for (const [key, value] of Object.entries(overrideConfig)) { // If the override has a property that's an object and not null, and the base has the same property as an object if (value !== null && typeof value === 'object' && !Array.isArray(value) && result[key] !== null && typeof result[key] === 'object' && !Array.isArray(result[key])) { // Recursively merge the nested objects result[key] = mergeConfigs(result[key], value); } else { // Otherwise just override the value result[key] = value; } } return result; }