Files
markitect-main/capabilities/testdrive-jsui/node_modules/css-tree/cjs/lexer/structure.cjs
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

169 lines
5.1 KiB
JavaScript

'use strict';
const List = require('../utils/List.cjs');
const { hasOwnProperty } = Object.prototype;
function isValidNumber(value) {
// Number.isInteger(value) && value >= 0
return (
typeof value === 'number' &&
isFinite(value) &&
Math.floor(value) === value &&
value >= 0
);
}
function isValidLocation(loc) {
return (
Boolean(loc) &&
isValidNumber(loc.offset) &&
isValidNumber(loc.line) &&
isValidNumber(loc.column)
);
}
function createNodeStructureChecker(type, fields) {
return function checkNode(node, warn) {
if (!node || node.constructor !== Object) {
return warn(node, 'Type of node should be an Object');
}
for (let key in node) {
let valid = true;
if (hasOwnProperty.call(node, key) === false) {
continue;
}
if (key === 'type') {
if (node.type !== type) {
warn(node, 'Wrong node type `' + node.type + '`, expected `' + type + '`');
}
} else if (key === 'loc') {
if (node.loc === null) {
continue;
} else if (node.loc && node.loc.constructor === Object) {
if (typeof node.loc.source !== 'string') {
key += '.source';
} else if (!isValidLocation(node.loc.start)) {
key += '.start';
} else if (!isValidLocation(node.loc.end)) {
key += '.end';
} else {
continue;
}
}
valid = false;
} else if (fields.hasOwnProperty(key)) {
valid = false;
for (let i = 0; !valid && i < fields[key].length; i++) {
const fieldType = fields[key][i];
switch (fieldType) {
case String:
valid = typeof node[key] === 'string';
break;
case Boolean:
valid = typeof node[key] === 'boolean';
break;
case null:
valid = node[key] === null;
break;
default:
if (typeof fieldType === 'string') {
valid = node[key] && node[key].type === fieldType;
} else if (Array.isArray(fieldType)) {
valid = node[key] instanceof List.List;
}
}
}
} else {
warn(node, 'Unknown field `' + key + '` for ' + type + ' node type');
}
if (!valid) {
warn(node, 'Bad value for `' + type + '.' + key + '`');
}
}
for (const key in fields) {
if (hasOwnProperty.call(fields, key) &&
hasOwnProperty.call(node, key) === false) {
warn(node, 'Field `' + type + '.' + key + '` is missed');
}
}
};
}
function processStructure(name, nodeType) {
const structure = nodeType.structure;
const fields = {
type: String,
loc: true
};
const docs = {
type: '"' + name + '"'
};
for (const key in structure) {
if (hasOwnProperty.call(structure, key) === false) {
continue;
}
const docsTypes = [];
const fieldTypes = fields[key] = Array.isArray(structure[key])
? structure[key].slice()
: [structure[key]];
for (let i = 0; i < fieldTypes.length; i++) {
const fieldType = fieldTypes[i];
if (fieldType === String || fieldType === Boolean) {
docsTypes.push(fieldType.name);
} else if (fieldType === null) {
docsTypes.push('null');
} else if (typeof fieldType === 'string') {
docsTypes.push('<' + fieldType + '>');
} else if (Array.isArray(fieldType)) {
docsTypes.push('List'); // TODO: use type enum
} else {
throw new Error('Wrong value `' + fieldType + '` in `' + name + '.' + key + '` structure definition');
}
}
docs[key] = docsTypes.join(' | ');
}
return {
docs,
check: createNodeStructureChecker(name, fields)
};
}
function getStructureFromConfig(config) {
const structure = {};
if (config.node) {
for (const name in config.node) {
if (hasOwnProperty.call(config.node, name)) {
const nodeType = config.node[name];
if (nodeType.structure) {
structure[name] = processStructure(name, nodeType);
} else {
throw new Error('Missed `structure` field in `' + name + '` node type definition');
}
}
}
}
return structure;
}
exports.getStructureFromConfig = getStructureFromConfig;