mirror of
https://github.com/ptarmiganlabs/butler-sos.git
synced 2025-12-19 17:58:18 -05:00
266 lines
10 KiB
JavaScript
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');
|
|
}
|
|
});
|
|
}); |