testify-universal-cli
Version:
Universal interactive CLI tool for scanning and executing tests across multiple programming languages
128 lines (112 loc) • 3.77 kB
JavaScript
import fs from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { detectLanguage } from './lib/utils/detector.js';
import { logger } from './lib/utils/logger.js';
import { runTests } from './lib/utils/runner.js';
import { scanRepository } from './lib/utils/scanner.js';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const CDN_CONFIG_PATH = path.join(__dirname, '.cdn-config.json');
/**
* Main Testify function
*
* @param {object} options - CLI options
* @param {string} options.cwd - Current working directory
* @param {string[]} options.markers - Test markers to filter by
* @param {string} options.runner - Custom test runner
* @param {string} options.language - Force specific language
* @param {boolean} options.debug - Enable debug mode
* @returns {Promise<void>}
*/
export default async function testify(options = {}) {
const { cwd = process.cwd(), markers = [], runner, language: forcedLanguage, debug = false } = options;
// Configure logger based on debug flag
logger.setDebugMode(debug);
logger.debug('Testify started with options:', options);
// Log working directory
logger.debug(`Working directory: ${cwd}`);
if (markers.length > 0) {
logger.debug(`Test markers: ${markers.join(', ')}`);
}
if (runner) {
logger.debug(`Custom runner: ${runner}`);
}
if (forcedLanguage) {
logger.debug(`Forced language: ${forcedLanguage}`);
}
// Check for CDN updates if enabled
logger.debug('Checking for CDN updates...');
const endCdnCheck = logger.timer('CDN update check');
await checkForUpdates();
endCdnCheck();
// Detect repository language (or use forced language)
logger.info('Detecting repository language...');
const endLanguageDetection = logger.timer('Language detection');
const language = forcedLanguage || await detectLanguage(cwd);
endLanguageDetection();
logger.info(`Detected language: ${language}`);
// Scan repository for test files
logger.info('Scanning repository for test files...');
const endScan = logger.timer('Repository scan');
const testFiles = await scanRepository(cwd, language);
endScan();
logger.info(`Found ${testFiles.length} test files`);
logger.debug('Test files:', testFiles);
// Run tests
logger.info(`Running tests with ${runner || 'default'} runner...`);
const endTests = logger.timer('Test execution');
const result = await runTests({
language,
testFiles,
cwd,
markers,
customRunner: runner,
debug
});
endTests();
logger.debug('Test execution completed with result:', result);
return result;
}
/**
* Check for updates from CDN if enabled
*
* @returns {Promise<void>}
*/
async function checkForUpdates() {
try {
// Check if CDN is enabled
const cdnConfig = await readCdnConfig();
logger.debug('CDN configuration:', cdnConfig);
if (cdnConfig.enabled) {
logger.debug('CDN updates enabled, checking for updates...');
// In a real implementation, this would check for updates
// and potentially download new language adapters
} else {
logger.debug('CDN updates disabled, skipping update check');
}
} catch (error) {
// Silently fail on CDN errors - don't block testing
logger.debug('Error checking for CDN updates:', error);
}
}
/**
* Read CDN configuration
*
* @returns {Promise<object>} - CDN configuration
*/
async function readCdnConfig() {
try {
logger.trace(`Reading CDN config from: ${CDN_CONFIG_PATH}`);
const data = await fs.readFile(CDN_CONFIG_PATH, 'utf8');
return JSON.parse(data);
} catch (error) {
logger.trace(`CDN config not found, using defaults: ${error.message}`);
// Return default config if file doesn't exist
return {
enabled: false,
region: 'auto',
cacheTime: 86400,
preferredEndpoints: []
};
}
}