Files
markitect-main/capabilities/testdrive-jsui/node_modules/@istanbuljs/load-nyc-config/index.js
tegwick 17c62aadaa feat: complete testdrive-jsui capability extraction with full JavaScript test integration
Extract JavaScript UI framework functionality into dedicated testdrive-jsui capability
while maintaining 100% functionality preservation and integrating JavaScript tests
into the main Python test suite.

Phase 1 (Foundation Setup) - COMPLETED:
- Created capability directory structure with proper Python package layout
- Configured pyproject.toml with Node.js subprocess dependencies
- Set up package.json with Jest + JSDOM testing framework
- Implemented Python-JavaScript bridge for seamless test integration
- Created comprehensive capability Makefile with all testing targets
- Added detailed README documentation for capability usage

Phase 2 (Integration Layer) - COMPLETED:
- Built Python test wrappers for JavaScript test execution via subprocess
- Integrated with pytest discovery system for unified test experience
- Added capability targets to main Makefile delegation system
- Verified test integration works with main test suite

Phase 3 (Safe Migration) - COMPLETED:
- Copied (not moved) all JavaScript files to capability using safe copy-first approach
- Migrated 4 core JavaScript components and 11 test files (2,840+ lines)
- Verified all tests work in new location (11 Python tests + 7 JavaScript tests passing)
- Maintained dual-track testing capability for safety during transition

Phase 4 (Framework Enhancement) - COMPLETED:
- Enhanced testing framework with Python integration and coverage reporting
- Achieved 59% Python test coverage and 100% JavaScript test coverage
- Added performance benchmarking and component documentation

Phase 5 (Production Integration) - COMPLETED:
- Added standard 'test' target to capability Makefile for discovery system compatibility
- Integrated JavaScript tests into main Makefile with new targets:
  * test-js: Run JavaScript UI tests
  * test-all: Run all tests (Python + JavaScript + Capabilities)
- Updated help documentation to include new testing workflows
- Verified capability auto-discovery works via 'make test-capabilities'

Key Achievements:
- Zero-risk migration completed with copy-first safety approach
- Full Python-JavaScript test integration with 18 total passing tests
- JavaScript UI framework successfully extracted to dedicated capability
- Enhanced CI/CD integration with unified test command interface
- Clean architecture enabling future JavaScript framework evolution

Testing Status:
-  All Python integration tests passing (11/11)
-  All JavaScript component tests passing (7/7)
-  Capability discovery integration working
-  Main test suite integration complete
-  Test coverage reporting functional (59% Python, 100% JavaScript)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-09 22:29:30 +01:00

167 lines
4.2 KiB
JavaScript

'use strict';
const fs = require('fs');
const path = require('path');
const {promisify} = require('util');
const camelcase = require('camelcase');
const findUp = require('find-up');
const resolveFrom = require('resolve-from');
const getPackageType = require('get-package-type');
const readFile = promisify(fs.readFile);
let loadActive = false;
function isLoading() {
return loadActive;
}
const standardConfigFiles = [
'.nycrc',
'.nycrc.json',
'.nycrc.yml',
'.nycrc.yaml',
'nyc.config.js',
'nyc.config.cjs',
'nyc.config.mjs'
];
function camelcasedConfig(config) {
const results = {};
for (const [field, value] of Object.entries(config)) {
results[camelcase(field)] = value;
}
return results;
}
async function findPackage(options) {
const cwd = options.cwd || process.env.NYC_CWD || process.cwd();
const pkgPath = await findUp('package.json', {cwd});
if (pkgPath) {
const pkgConfig = JSON.parse(await readFile(pkgPath, 'utf8')).nyc || {};
if ('cwd' in pkgConfig) {
pkgConfig.cwd = path.resolve(path.dirname(pkgPath), pkgConfig.cwd);
}
return {
cwd: path.dirname(pkgPath),
pkgConfig
};
}
return {
cwd,
pkgConfig: {}
};
}
async function actualLoad(configFile) {
if (!configFile) {
return {};
}
const configExt = path.extname(configFile).toLowerCase();
switch (configExt) {
case '.js':
/* istanbul ignore next: coverage for 13.2.0+ is shown in load-esm.js */
if (await getPackageType(configFile) === 'module') {
return require('./load-esm')(configFile);
}
/* fallthrough */
case '.cjs':
return require(configFile);
/* istanbul ignore next: coverage for 13.2.0+ is shown in load-esm.js */
case '.mjs':
return require('./load-esm')(configFile);
case '.yml':
case '.yaml':
return require('js-yaml').load(await readFile(configFile, 'utf8'));
default:
return JSON.parse(await readFile(configFile, 'utf8'));
}
}
async function loadFile(configFile) {
/* This lets @istanbuljs/esm-loader-hook avoid circular initialization when loading
* configuration. This should generally only happen when the loader hook is active
* on the main nyc process. */
loadActive = true;
try {
return await actualLoad(configFile);
} finally {
loadActive = false;
}
}
async function applyExtends(config, filename, loopCheck = new Set()) {
config = camelcasedConfig(config);
if ('extends' in config) {
const extConfigs = [].concat(config.extends);
if (extConfigs.some(e => typeof e !== 'string')) {
throw new TypeError(`${filename} contains an invalid 'extends' option`);
}
delete config.extends;
const filePath = path.dirname(filename);
for (const extConfig of extConfigs) {
const configFile = resolveFrom.silent(filePath, extConfig) ||
resolveFrom.silent(filePath, './' + extConfig);
if (!configFile) {
throw new Error(`Could not resolve configuration file ${extConfig} from ${path.dirname(filename)}.`);
}
if (loopCheck.has(configFile)) {
throw new Error(`Circular extended configurations: '${configFile}'.`);
}
loopCheck.add(configFile);
// eslint-disable-next-line no-await-in-loop
const configLoaded = await loadFile(configFile);
if ('cwd' in configLoaded) {
configLoaded.cwd = path.resolve(path.dirname(configFile), configLoaded.cwd);
}
Object.assign(
config,
// eslint-disable-next-line no-await-in-loop
await applyExtends(configLoaded, configFile, loopCheck)
);
}
}
return config;
}
async function loadNycConfig(options = {}) {
const {cwd, pkgConfig} = await findPackage(options);
const configFiles = [].concat(options.nycrcPath || standardConfigFiles);
const configFile = await findUp(configFiles, {cwd});
if (options.nycrcPath && !configFile) {
throw new Error(`Requested configuration file ${options.nycrcPath} not found`);
}
const config = {
cwd,
...(await applyExtends(pkgConfig, path.join(cwd, 'package.json'))),
...(await applyExtends(await loadFile(configFile), configFile))
};
const arrayFields = ['require', 'extension', 'exclude', 'include'];
for (const arrayField of arrayFields) {
if (config[arrayField]) {
config[arrayField] = [].concat(config[arrayField]);
}
}
return config;
}
module.exports = {
loadNycConfig,
isLoading
};