Files
butler-sos/src/lib/__tests__/sea-file-interactions.test.js
2025-07-27 20:02:30 +00:00

266 lines
10 KiB
JavaScript

import { jest, describe, test, beforeEach, afterEach } from '@jest/globals';
// Create a comprehensive test for SEA vs non-SEA file interactions
// This test focuses on the behavior differences rather than the exact module implementation
describe('SEA vs non-SEA file interactions integration tests', () => {
let mockGlobals;
let mockFs;
let mockPath;
let originalConsoleLog;
beforeEach(() => {
// Mock console to avoid noise during tests
originalConsoleLog = console.log;
console.log = jest.fn();
// Create mock globals that can toggle between SEA and non-SEA modes
mockGlobals = {
logger: {
verbose: jest.fn(),
error: jest.fn(),
info: jest.fn(),
},
isSea: false, // Start with non-SEA mode
appBasePath: '/mock/app/path',
config: {
get: jest.fn(),
},
};
// Mock filesystem operations
mockFs = {
existsSync: jest.fn(),
readFileSync: jest.fn(),
};
// Mock path operations
mockPath = {
resolve: jest.fn(),
extname: jest.fn(),
};
});
afterEach(() => {
jest.clearAllMocks();
console.log = originalConsoleLog;
});
test('should handle file path resolution differently in SEA vs non-SEA mode', () => {
// Test file path resolution logic that varies between modes
// Non-SEA mode: should use appBasePath for file resolution
const nonSeaFilePath = mockGlobals.isSea
? '/404.html'
: '/mock/app/path/static/404.html';
expect(nonSeaFilePath).toBe('/mock/app/path/static/404.html');
// SEA mode: should use asset paths
mockGlobals.isSea = true;
const seaFilePath = mockGlobals.isSea
? '/404.html'
: '/mock/app/path/static/404.html';
expect(seaFilePath).toBe('/404.html');
});
test('should handle configuration loading in both modes', () => {
// Test config loading scenarios
// Non-SEA mode configuration
mockGlobals.isSea = false;
const shouldUseFilesystem = !mockGlobals.isSea;
expect(shouldUseFilesystem).toBe(true);
// SEA mode configuration
mockGlobals.isSea = true;
const shouldUseAssets = mockGlobals.isSea;
expect(shouldUseAssets).toBe(true);
});
test('should handle static file serving logic for both modes', () => {
// Test static file serving patterns
// Non-SEA mode: register static file plugin
mockGlobals.isSea = false;
const shouldRegisterStaticPlugin = !mockGlobals.isSea;
expect(shouldRegisterStaticPlugin).toBe(true);
// SEA mode: manual route registration
mockGlobals.isSea = true;
const shouldCreateCustomRoutes = mockGlobals.isSea;
expect(shouldCreateCustomRoutes).toBe(true);
});
test('should handle file existence checking in both modes', () => {
// Test file existence logic patterns
// Non-SEA mode: use fs.existsSync
mockGlobals.isSea = false;
mockFs.existsSync.mockReturnValue(true);
const fileExists = mockGlobals.isSea ?
false : // In SEA mode, would check assets differently
mockFs.existsSync('/some/file.txt');
expect(fileExists).toBe(true);
expect(mockFs.existsSync).toHaveBeenCalledWith('/some/file.txt');
// SEA mode: different checking mechanism
mockGlobals.isSea = true;
const assetExists = mockGlobals.isSea ?
true : // In SEA mode, would use sea.getAsset
mockFs.existsSync('/some/file.txt');
expect(assetExists).toBe(true);
});
test('should handle MIME type detection consistently in both modes', () => {
// MIME type detection should work the same in both modes
mockPath.extname.mockReturnValue('.html');
const mimeTypes = {
'.html': 'text/html; charset=utf-8',
'.css': 'text/css',
'.js': 'application/javascript',
'.png': 'image/png',
};
const fileExtension = mockPath.extname('/some/file.html');
const mimeType = mimeTypes[fileExtension] || 'application/octet-stream';
expect(mimeType).toBe('text/html; charset=utf-8');
expect(mockPath.extname).toHaveBeenCalledWith('/some/file.html');
});
test('should handle binary vs text file detection in both modes', () => {
// Binary file detection should work the same regardless of mode
const binaryExtensions = ['.png', '.jpg', '.jpeg', '.gif', '.ico', '.bin', '.exe', '.pdf'];
expect(binaryExtensions.includes('.png')).toBe(true);
expect(binaryExtensions.includes('.html')).toBe(false);
expect(binaryExtensions.includes('.js')).toBe(false);
});
test('should validate error handling patterns for both modes', () => {
// Error handling should be consistent
mockGlobals.logger.error.mockClear();
// Simulate file not found in non-SEA mode
mockGlobals.isSea = false;
mockFs.existsSync.mockReturnValue(false);
if (!mockFs.existsSync('/missing/file.txt')) {
mockGlobals.logger.error('FILE PREP: File not found: /missing/file.txt');
}
expect(mockGlobals.logger.error).toHaveBeenCalledWith('FILE PREP: File not found: /missing/file.txt');
// Reset for SEA mode test
mockGlobals.logger.error.mockClear();
mockGlobals.isSea = true;
// Simulate asset not found in SEA mode
const assetContent = undefined; // Simulating sea.getAsset returning undefined
if (assetContent === undefined) {
mockGlobals.logger.error('FILE PREP: Could not find /missing/asset.txt in SEA assets');
}
expect(mockGlobals.logger.error).toHaveBeenCalledWith('FILE PREP: Could not find /missing/asset.txt in SEA assets');
});
test('should validate template compilation works in both modes', () => {
// Template compilation should work regardless of how the template content was obtained
const templateContent = '<html>Hello {{name}}!</html>';
const templateData = { name: 'World' };
// Mock handlebars compilation
const mockTemplate = jest.fn().mockReturnValue('<html>Hello World!</html>');
const mockHandlebars = {
compile: jest.fn().mockReturnValue(mockTemplate)
};
const compiledTemplate = mockHandlebars.compile(templateContent);
const result = compiledTemplate(templateData);
expect(mockHandlebars.compile).toHaveBeenCalledWith(templateContent);
expect(mockTemplate).toHaveBeenCalledWith(templateData);
expect(result).toBe('<html>Hello World!</html>');
});
test('should validate encoding handling for both modes', () => {
// Encoding should be handled consistently
mockPath.extname.mockReturnValue('.html');
const isTextFile = !(['.png', '.jpg', '.jpeg', '.gif', '.ico', '.bin', '.exe', '.pdf'].includes('.html'));
const encoding = isTextFile ? 'utf8' : undefined;
expect(encoding).toBe('utf8');
// Binary file
mockPath.extname.mockReturnValue('.png');
const isTextFile2 = !(['.png', '.jpg', '.jpeg', '.gif', '.ico', '.bin', '.exe', '.pdf'].includes('.png'));
const encoding2 = isTextFile2 ? 'utf8' : undefined;
expect(encoding2).toBeUndefined();
});
test('should handle certificate file loading patterns in both modes', () => {
// Certificate file loading should work in both modes
const certificatePaths = {
Certificate: '/path/to/client.crt',
CertificateKey: '/path/to/client.key',
CertificateCA: '/path/to/ca.crt'
};
// Non-SEA mode: should use filesystem
mockGlobals.isSea = false;
const shouldUseFilesystem = !mockGlobals.isSea;
expect(shouldUseFilesystem).toBe(true);
// Mock filesystem certificate reading
mockFs.readFileSync
.mockReturnValueOnce('-----BEGIN CERTIFICATE-----\ncert data...')
.mockReturnValueOnce('-----BEGIN PRIVATE KEY-----\nkey data...')
.mockReturnValueOnce('-----BEGIN CERTIFICATE-----\nca data...');
if (!mockGlobals.isSea) {
const certs = {
cert: mockFs.readFileSync(certificatePaths.Certificate),
key: mockFs.readFileSync(certificatePaths.CertificateKey),
ca: mockFs.readFileSync(certificatePaths.CertificateCA)
};
expect(certs.cert).toBe('-----BEGIN CERTIFICATE-----\ncert data...');
expect(certs.key).toBe('-----BEGIN PRIVATE KEY-----\nkey data...');
expect(certs.ca).toBe('-----BEGIN CERTIFICATE-----\nca data...');
}
// SEA mode: should use assets
mockGlobals.isSea = true;
const shouldUseAssets = mockGlobals.isSea;
expect(shouldUseAssets).toBe(true);
// Mock SEA asset certificate reading
const mockSeaGetAsset = jest.fn()
.mockReturnValueOnce('-----BEGIN CERTIFICATE-----\ncert data...')
.mockReturnValueOnce('-----BEGIN PRIVATE KEY-----\nkey data...')
.mockReturnValueOnce('-----BEGIN CERTIFICATE-----\nca data...');
if (mockGlobals.isSea) {
const certs = {
cert: mockSeaGetAsset(certificatePaths.Certificate, 'utf8'),
key: mockSeaGetAsset(certificatePaths.CertificateKey, 'utf8'),
ca: mockSeaGetAsset(certificatePaths.CertificateCA, 'utf8')
};
expect(certs.cert).toBe('-----BEGIN CERTIFICATE-----\ncert data...');
expect(certs.key).toBe('-----BEGIN PRIVATE KEY-----\nkey data...');
expect(certs.ca).toBe('-----BEGIN CERTIFICATE-----\nca data...');
expect(mockSeaGetAsset).toHaveBeenCalledWith('/path/to/client.crt', 'utf8');
expect(mockSeaGetAsset).toHaveBeenCalledWith('/path/to/client.key', 'utf8');
expect(mockSeaGetAsset).toHaveBeenCalledWith('/path/to/ca.crt', 'utf8');
}
});
});