monorepo-dep-checker/tests/dependency-checker.test.ts

156 lines
4.9 KiB
TypeScript

import { describe, test, expect, beforeEach, vi } from 'vitest';
import fs from 'fs';
import path from 'path';
import { DependencyChecker } from '../src/lib';
// Mock console.log to prevent output during tests
const _log = console.log
console.log = vi.fn();
console.error = vi.fn();
describe('DependencyChecker', () => {
const appPackageJsonPath = path.resolve(__dirname, './app/package.json');
const packagesPath = path.resolve(__dirname, './packages');
let checker: DependencyChecker;
beforeEach(() => {
checker = new DependencyChecker(appPackageJsonPath, packagesPath);
// Clear console mocks before each test
console.log = vi.fn();
console.error = vi.fn();
});
test('should correctly identify version differences', async () => {
await checker.run({ checkVersions: true });
expect(console.log).toHaveBeenCalledWith(
expect.stringContaining('Version Differences Summary')
);
// Verify major version difference detection
const calls = (console.log as jest.Mock).mock.calls.map(call => call[0]).join('\n');
expect(calls).toContain('Major version difference');
});
test('should detect missing dependencies', async () => {
await checker.run({ checkMissing: true });
expect(console.log).toHaveBeenCalledWith(
expect.stringContaining('Checking for missing dependencies')
);
});
test('should handle update with dry run', async () => {
const originalContent = fs.readFileSync(
path.join(packagesPath, 'pkg1/package.json'),
'utf8'
);
await checker.run({ update: true, dryRun: true });
const newContent = fs.readFileSync(
path.join(packagesPath, 'pkg1/package.json'),
'utf8'
);
expect(originalContent).toBe(newContent);
expect(console.log).toHaveBeenCalledWith(
expect.stringContaining('[DRY RUN]')
);
});
test('should output JSON format correctly', async () => {
const consoleSpy = vi.spyOn(console, 'log');
await checker.run({ format: 'json' });
const lastCall = consoleSpy.mock.calls[consoleSpy.mock.calls.length - 1][0];
expect(() => JSON.parse(lastCall)).not.toThrow();
const output = JSON.parse(lastCall);
expect(output).toHaveProperty('summary');
expect(output).toHaveProperty('fullAnalysis');
});
test('should handle multiple package paths', async () => {
const multiPathChecker = new DependencyChecker(
appPackageJsonPath,
`${packagesPath},${path.join(packagesPath, 'pkg1/package.json')}`
);
await multiPathChecker.run({ checkVersions: true });
// Verify that dependencies from both paths are processed
const calls = (console.log as jest.Mock).mock.calls.map(call => call[0]).join('\n');
expect(calls).toContain('Version Differences Summary');
expect(calls).toContain('pkg1');
});
test('should identify workspace dependencies', async () => {
// First create test files with workspace deps
const pkg3Path = path.join(packagesPath, 'pkg3/package.json');
const pkg3Content = {
name: "pkg3",
version: "1.0.0",
dependencies: {
"workspace-pkg": "workspace:*",
"react": "^18.2.0"
}
};
// Ensure directory exists
fs.mkdirSync(path.dirname(pkg3Path), { recursive: true });
fs.writeFileSync(pkg3Path, JSON.stringify(pkg3Content, null, 2));
// Run with default options to get full analysis
await checker.run({ format: 'json' });
// Get the last console.log call
const calls = (console.log as jest.Mock).mock.calls;
expect(calls.length).toBeGreaterThan(0);
const lastCall = calls[calls.length - 1][0];
expect(() => JSON.parse(lastCall)).not.toThrow();
const output = JSON.parse(lastCall);
expect(output.fullAnalysis).toHaveProperty('workspace-pkg');
// Clean up
fs.unlinkSync(pkg3Path);
});
test('should handle errors gracefully', async () => {
const invalidChecker = new DependencyChecker(
'invalid/path/package.json',
packagesPath
);
await expect(invalidChecker.run()).rejects.toThrow();
});
test('should handle empty package directories', async () => {
// Create a temporary empty directory
const emptyDir = path.join(__dirname, 'empty');
fs.mkdirSync(emptyDir, { recursive: true });
const emptyChecker = new DependencyChecker(appPackageJsonPath, emptyDir);
await emptyChecker.run({ checkVersions: true });
// Clean up
fs.rmdirSync(emptyDir);
// Verify appropriate handling of empty directory
const calls = (console.log as jest.Mock).mock.calls.map(call => call[0]).join('\n');
expect(calls).toContain('No version differences found');
});
test('should detect version conflicts correctly', async () => {
await checker.run({ checkVersions: true });
const calls = (console.log as jest.Mock).mock.calls.map(call => call[0]).join('\n');
expect(calls).toMatch(/Difference \((?:major|minor|patch)\)/);
});
});