@stillrivercode/agentic-workflow-template
Version:
NPM package to create AI-powered GitHub workflow automation projects
284 lines (234 loc) • 9.02 kB
JavaScript
const fs = require('fs-extra');
const path = require('path');
const { findPackageRoot } = require('../create-project');
// Mock fs-extra
jest.mock('fs-extra');
describe('findPackageRoot Function', () => {
beforeEach(() => {
jest.clearAllMocks();
});
describe('when package.json is found in directory tree', () => {
it('should find package root in current directory', () => {
const testDir = '/test/current';
const packageJsonPath = path.join(testDir, 'package.json');
// Mock fs.existsSync to return true for the package.json and essential files
fs.existsSync.mockImplementation((filePath) => {
return (
filePath === packageJsonPath ||
filePath === path.join(testDir, 'cli/') ||
filePath === path.join(testDir, 'scripts/') ||
filePath === path.join(testDir, 'package.json')
);
});
// Mock fs.readJsonSync to return the correct package
fs.readJsonSync.mockReturnValue({
name: '@stillrivercode/agentic-workflow-template',
version: '1.0.0',
});
const result = findPackageRoot(testDir);
expect(result).toBe(testDir);
});
it('should find package root in parent directory', () => {
const testDir = '/test/current/nested';
const parentDir = '/test/current';
const packageJsonPath = path.join(parentDir, 'package.json');
// Mock fs.existsSync to return true only for parent directory
fs.existsSync.mockImplementation((filePath) => {
return (
filePath === packageJsonPath ||
filePath === path.join(parentDir, 'cli/') ||
filePath === path.join(parentDir, 'scripts/') ||
filePath === path.join(parentDir, 'package.json')
);
});
fs.readJsonSync.mockReturnValue({
name: '@stillrivercode/agentic-workflow-template',
version: '1.0.0',
});
const result = findPackageRoot(testDir);
expect(result).toBe(parentDir);
});
it('should skip wrong packages and continue searching', () => {
const testDir = '/test/current/nested';
const wrongPackageDir = '/test/current/nested';
const correctPackageDir = '/test/current';
const wrongPackageJsonPath = path.join(wrongPackageDir, 'package.json');
const correctPackageJsonPath = path.join(
correctPackageDir,
'package.json'
);
fs.existsSync.mockImplementation((filePath) => {
return (
filePath === wrongPackageJsonPath ||
filePath === correctPackageJsonPath
);
});
fs.readJsonSync.mockImplementation((filePath) => {
if (filePath === wrongPackageJsonPath) {
return { name: 'some-other-package', version: '1.0.0' };
}
if (filePath === correctPackageJsonPath) {
return {
name: '@stillrivercode/agentic-workflow-template',
version: '1.0.0',
};
}
});
const result = findPackageRoot(testDir);
expect(result).toBe(correctPackageDir);
});
it('should skip directories missing essential template files', () => {
const testDir = '/test/current/nested';
const incompleteDir = '/test/current/nested';
const completeDir = '/test/current';
const incompletePackageJsonPath = path.join(
incompleteDir,
'package.json'
);
const completePackageJsonPath = path.join(completeDir, 'package.json');
fs.existsSync.mockImplementation((filePath) => {
// Both directories have package.json
if (
filePath === incompletePackageJsonPath ||
filePath === completePackageJsonPath
) {
return true;
}
// Incomplete directory is missing scripts/
if (
filePath === path.join(incompleteDir, 'cli/') ||
filePath === path.join(incompleteDir, 'package.json')
) {
return true;
}
if (filePath === path.join(incompleteDir, 'scripts/')) {
return false;
}
// Complete directory has all files
if (
filePath === path.join(completeDir, 'cli/') ||
filePath === path.join(completeDir, 'scripts/') ||
filePath === path.join(completeDir, 'package.json')
) {
return true;
}
return false;
});
fs.readJsonSync.mockReturnValue({
name: '@stillrivercode/agentic-workflow-template',
version: '1.0.0',
});
const result = findPackageRoot(testDir);
expect(result).toBe(completeDir);
});
it('should handle corrupted package.json files', () => {
const testDir = '/test/current';
const packageJsonPath = path.join(testDir, 'package.json');
fs.existsSync.mockImplementation((filePath) => {
return filePath === packageJsonPath;
});
// Mock readJsonSync to throw an error (corrupted JSON)
fs.readJsonSync.mockImplementation(() => {
throw new Error('Invalid JSON');
});
// Should fall back to require.resolve behavior
jest.doMock(
'@stillrivercode/agentic-workflow-template/package.json',
() => ({}),
{ virtual: true }
);
const result = findPackageRoot(testDir);
// Should return fallback (parent directory)
expect(result).toBe(path.join(testDir, '..'));
});
});
describe('when package.json is not found in directory tree', () => {
it('should handle directory traversal exhaustion gracefully', () => {
const testDir = '/some/path';
// Mock fs.existsSync to always return false (no package.json found anywhere)
fs.existsSync.mockReturnValue(false);
// Mock require.resolve to fail
const originalResolve = require.resolve;
require.resolve = jest.fn().mockImplementation(() => {
throw new Error('Cannot resolve module');
});
const result = findPackageRoot(testDir);
// Should fall back to parent directory when all else fails
expect(result).toBe(path.join(testDir, '..'));
// Restore original require.resolve
require.resolve = originalResolve;
});
it('should use final fallback when require.resolve fails', () => {
const testDir = '/test/current';
// Mock fs.existsSync to return false
fs.existsSync.mockReturnValue(false);
// Mock require.resolve to throw an error
const originalResolve = require.resolve;
require.resolve = jest.fn().mockImplementation(() => {
throw new Error('Cannot resolve module');
});
const result = findPackageRoot(testDir);
expect(result).toBe(path.join(testDir, '..'));
// Restore original require.resolve
require.resolve = originalResolve;
});
});
describe('edge cases', () => {
it('should handle reaching filesystem root', () => {
const testDir = '/';
fs.existsSync.mockReturnValue(false);
// Mock require.resolve to fail
const originalResolve = require.resolve;
require.resolve = jest.fn().mockImplementation(() => {
throw new Error('Cannot resolve module');
});
const result = findPackageRoot(testDir);
expect(result).toBe(path.join(testDir, '..'));
// Restore original require.resolve
require.resolve = originalResolve;
});
it('should handle deeply nested directories', () => {
const testDir = '/very/deep/nested/directory/structure';
const rootDir = '/very';
const packageJsonPath = path.join(rootDir, 'package.json');
fs.existsSync.mockImplementation((filePath) => {
// Package.json exists at root
if (filePath === packageJsonPath) return true;
// Essential files exist at root
if (
filePath === path.join(rootDir, 'cli/') ||
filePath === path.join(rootDir, 'scripts/') ||
filePath === path.join(rootDir, 'package.json')
) {
return true;
}
return false;
});
fs.readJsonSync.mockReturnValue({
name: '@stillrivercode/agentic-workflow-template',
version: '1.0.0',
});
const result = findPackageRoot(testDir);
expect(result).toBe(rootDir);
});
it('should handle absolute paths correctly', () => {
const testDir = '/test/current';
const packageJsonPath = path.join(testDir, 'package.json');
fs.existsSync.mockImplementation((filePath) => {
// Package.json and essential files exist
return (
filePath === packageJsonPath ||
filePath === path.join(testDir, 'cli/') ||
filePath === path.join(testDir, 'scripts/') ||
filePath === path.join(testDir, 'package.json')
);
});
fs.readJsonSync.mockReturnValue({
name: '@stillrivercode/agentic-workflow-template',
version: '1.0.0',
});
const result = findPackageRoot(testDir);
expect(result).toBe(testDir);
});
});
});