const fs = require('fs').promises;
const path = require('path');
// Test the ACTUAL pattern matching logic without ES module imports
// Test utilities
async function createTestFile(content) {
const testPath = path.join(__dirname, 'temp', `test-${Date.now()}.js`);
await fs.mkdir(path.dirname(testPath), { recursive: true });
await fs.writeFile(testPath, content);
return testPath;
}
async function cleanup(filePaths) {
for (const filePath of filePaths) {
try {
await fs.unlink(filePath);
} catch (error) {
// Ignore
}
}
}
// Core pattern matching functions - что РЕАЛЬНО должно работать
async function extractByPattern(filePath, startPattern, endPattern, lineCount) {
const content = await fs.readFile(filePath, 'utf-8');
const startIndex = content.indexOf(startPattern);
if (startIndex === -1) {
throw new Error(`Start pattern "${startPattern}" not found`);
}
if (endPattern) {
const endIndex = content.indexOf(endPattern, startIndex + startPattern.length);
if (endIndex === -1) {
throw new Error(`End pattern "${endPattern}" not found after start pattern`);
}
return content.slice(startIndex, endIndex + endPattern.length);
} else if (lineCount) {
const lines = content.split('\n');
const startLine = content.slice(0, startIndex).split('\n').length - 1;
const endLine = Math.min(startLine + lineCount, lines.length);
return lines.slice(startLine, endLine).join('\n');
} else {
const lines = content.split('\n');
const startLine = content.slice(0, startIndex).split('\n').length - 1;
return lines[startLine];
}
}
async function insertByMarker(filePath, marker, content, position) {
const existingContent = await fs.readFile(filePath, 'utf-8');
if (existingContent.indexOf(marker) === -1) {
throw new Error(`Marker "${marker}" not found`);
}
let newContent;
if (position === 'before') {
newContent = existingContent.replace(marker, `${content}\n${marker}`);
} else if (position === 'after') {
newContent = existingContent.replace(marker, `${marker}\n${content}`);
} else if (position === 'replace') {
newContent = existingContent.replace(marker, content);
}
await fs.writeFile(filePath, newContent);
}
describe('Pattern Matching Logic Tests', () => {
let testFiles = [];
afterEach(async () => {
await cleanup(testFiles);
testFiles = [];
});
test('Extract function with end pattern', async () => {
const testCode = `// Test file
function processData(input) {
console.log('Processing:', input);
return input.toUpperCase();
}
function otherFunction() {
return false;
}`;
const testFile = await createTestFile(testCode);
testFiles = [testFile];
const result = await extractByPattern(testFile, 'function processData', '}');
expect(result).toMatchSnapshot();
expect(result).toContain('function processData');
expect(result).toContain('console.log');
expect(result).toContain('}');
expect(result).not.toContain('function otherFunction');
});
test('Extract with line count', async () => {
const testCode = `// Header comment
function test() {
const a = 1;
const b = 2;
return a + b;
}
// Footer`;
const testFile = await createTestFile(testCode);
testFiles = [testFile];
const result = await extractByPattern(testFile, 'function test()', undefined, 3);
expect(result).toMatchSnapshot();
expect(result.split('\n')).toHaveLength(3);
expect(result).toContain('function test()');
expect(result).toContain('const a = 1');
});
test('Insert after marker', async () => {
const testCode = `class Test {
// Insert utilities here
mainMethod() {
return true;
}
}`;
const testFile = await createTestFile(testCode);
testFiles = [testFile];
await insertByMarker(testFile, '// Insert utilities here', 'function added() {}', 'after');
const result = await fs.readFile(testFile, 'utf-8');
expect(result).toMatchSnapshot();
expect(result).toContain('// Insert utilities here');
expect(result).toContain('function added() {}');
});
test('Replace marker', async () => {
const testCode = `class Test {
// TODO: Add methods here
existingMethod() {
return false;
}
}`;
const testFile = await createTestFile(testCode);
testFiles = [testFile];
await insertByMarker(testFile, '// TODO: Add methods here', 'function newMethod() { return true; }', 'replace');
const result = await fs.readFile(testFile, 'utf-8');
expect(result).toMatchSnapshot();
expect(result).not.toContain('// TODO: Add methods here');
expect(result).toContain('function newMethod()');
});
test('Error - pattern not found', async () => {
const testFile = await createTestFile('function test() {}');
testFiles = [testFile];
await expect(
extractByPattern(testFile, 'NONEXISTENT', undefined, 1)
).rejects.toThrow('not found');
});
test('Error - marker not found', async () => {
const testFile = await createTestFile('function test() {}');
testFiles = [testFile];
await expect(
insertByMarker(testFile, 'NONEXISTENT', 'content', 'after')
).rejects.toThrow('not found');
});
test('Extract single line by pattern', async () => {
const testCode = `const a = 1;
const b = 2;
const TARGET_LINE = 'find me';
const c = 3;`;
const testFile = await createTestFile(testCode);
testFiles = [testFile];
const result = await extractByPattern(testFile, 'TARGET_LINE');
expect(result).toMatchSnapshot();
expect(result).toBe('const TARGET_LINE = \'find me\';');
});
test('Extract multiline block with comments', async () => {
const testCode = `// Before block
/* START_BLOCK */
function complexFunction(a, b, c) {
// Complex logic here
const result = a + b + c;
return result;
}
/* END_BLOCK */
// After block`;
const testFile = await createTestFile(testCode);
testFiles = [testFile];
const result = await extractByPattern(testFile, '/* START_BLOCK */', '/* END_BLOCK */');
expect(result).toMatchSnapshot();
expect(result).toContain('/* START_BLOCK */');
expect(result).toContain('complexFunction');
expect(result).toContain('/* END_BLOCK */');
});
test('Extract class definition', async () => {
const testCode = `import something from 'lib';
class MyClass {
constructor(data) {
this.data = data;
}
process() {
return this.data.map(x => x * 2);
}
}
export default MyClass;`;
const testFile = await createTestFile(testCode);
testFiles = [testFile];
const result = await extractByPattern(testFile, 'class MyClass', undefined, 8);
expect(result).toMatchSnapshot();
expect(result).toContain('class MyClass');
expect(result).toContain('constructor');
expect(result).toContain('process()');
});
test('Insert before first line', async () => {
const testCode = `function existing() {
return true;
}`;
const testFile = await createTestFile(testCode);
testFiles = [testFile];
await insertByMarker(testFile, 'function existing()', '// Added header comment', 'before');
const result = await fs.readFile(testFile, 'utf-8');
expect(result).toMatchSnapshot();
expect(result.startsWith('// Added header comment'));
});
test('Insert complex content after marker', async () => {
const testCode = `class Service {
// INJECT_METHODS_HERE
existing() {
return 'exists';
}
}`;
const complexContent = `async fetchData(url) {
try {
const response = await fetch(url);
return await response.json();
} catch (error) {
throw new Error(\`Fetch failed: \${error.message}\`);
}
}
validateData(data) {
if (!data || typeof data !== 'object') {
return false;
}
return Object.keys(data).length > 0;
}`;
const testFile = await createTestFile(testCode);
testFiles = [testFile];
await insertByMarker(testFile, '// INJECT_METHODS_HERE', complexContent, 'after');
const result = await fs.readFile(testFile, 'utf-8');
expect(result).toMatchSnapshot();
expect(result).toContain('async fetchData');
expect(result).toContain('validateData');
});
test('Extract arrow function block', async () => {
const testCode = `const utils = {
// ARROW_FUNCTIONS_START
processArray: (arr) => arr.filter(x => x > 0),
formatString: (str) => str.trim().toLowerCase(),
calculateSum: (numbers) => numbers.reduce((a, b) => a + b, 0)
// ARROW_FUNCTIONS_END
};`;
const testFile = await createTestFile(testCode);
testFiles = [testFile];
const result = await extractByPattern(testFile, '// ARROW_FUNCTIONS_START', '// ARROW_FUNCTIONS_END');
expect(result).toMatchSnapshot();
expect(result).toContain('processArray');
expect(result).toContain('=>');
});
test('Replace nested content', async () => {
const testCode = `function wrapper() {
// REPLACE_TARGET
const old = 'remove this';
// END_REPLACE
return 'keep this';
}`;
const newContent = `const new = 'added this';
const also = 'and this too';`;
const testFile = await createTestFile(testCode);
testFiles = [testFile];
await insertByMarker(testFile, '// REPLACE_TARGET', newContent, 'replace');
const result = await fs.readFile(testFile, 'utf-8');
expect(result).toMatchSnapshot();
expect(result).not.toContain('// REPLACE_TARGET');
expect(result).toContain('added this');
});
test('Extract with special characters and regex patterns', async () => {
const testCode = 'const regex = /function\\\\s+\\\\w+\\\\(/;\n' +
'const string = "function test() { return \'test\'; }";\n' +
'// SPECIAL_PATTERN: ${}[]^.*+?|()\n' +
'const config = {\n' +
' pattern: "*.{js,ts,jsx,tsx}",\n' +
' exclude: ["node_modules/**", "dist/**"]\n' +
'};';
const testFile = await createTestFile(testCode);
testFiles = [testFile];
const result = await extractByPattern(testFile, '// SPECIAL_PATTERN', undefined, 3);
expect(result).toMatchSnapshot();
expect(result).toContain('SPECIAL_PATTERN');
expect(result).toContain('pattern:');
});
test('Empty line extraction', async () => {
const testCode = `line 1
// EMPTY_LINE_MARKER
line 4`;
const testFile = await createTestFile(testCode);
testFiles = [testFile];
const result = await extractByPattern(testFile, '// EMPTY_LINE_MARKER', undefined, 1);
expect(result).toMatchSnapshot();
expect(result).toBe('// EMPTY_LINE_MARKER');
});
});