mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-29 23:54:24 +00:00
- Added HooksExecutor to centralize hook execution logic across CLI and Electron. - Implemented HooksConsolidator to improve performance by consolidating multiple hook levels into a single execution context. - Refactored existing hook management to utilize the new executor and consolidator, enhancing efficiency and reducing resource usage. - Updated runSingleRequest and network IPC to leverage consolidated hook execution for better performance. - Introduced comprehensive tests for the new hooks functionality, ensuring reliability and correctness.
165 lines
5.4 KiB
JavaScript
165 lines
5.4 KiB
JavaScript
/**
|
|
* Unit tests for Hooks Executor
|
|
*/
|
|
const {
|
|
executeHooksForLevel,
|
|
executeConsolidatedHooks,
|
|
executeAllHookLevels,
|
|
createHookExecutor,
|
|
HOOK_EVENTS
|
|
} = require('../src/runtime/hooks-executor');
|
|
|
|
// Mock the HooksRuntime
|
|
jest.mock('../src/runtime/hooks-runtime', () => {
|
|
return jest.fn().mockImplementation(() => ({
|
|
runHooks: jest.fn().mockResolvedValue({
|
|
hookManager: {
|
|
call: jest.fn().mockResolvedValue(undefined),
|
|
dispose: jest.fn()
|
|
},
|
|
envVariables: {},
|
|
runtimeVariables: {},
|
|
persistentEnvVariables: {},
|
|
globalEnvironmentVariables: {}
|
|
})
|
|
}));
|
|
});
|
|
|
|
describe('Hooks Executor', () => {
|
|
const mockOptions = {
|
|
request: { url: 'http://test.com' },
|
|
envVariables: {},
|
|
runtimeVariables: {},
|
|
collectionPath: '/test/collection',
|
|
onConsoleLog: jest.fn(),
|
|
processEnvVars: {},
|
|
scriptingConfig: { runtime: 'quickjs' },
|
|
runRequestByItemPathname: jest.fn(),
|
|
collectionName: 'Test Collection'
|
|
};
|
|
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
describe('HOOK_EVENTS', () => {
|
|
it('should have correct event names', () => {
|
|
expect(HOOK_EVENTS.HTTP_BEFORE_REQUEST).toBe('http:beforeRequest');
|
|
expect(HOOK_EVENTS.HTTP_AFTER_RESPONSE).toBe('http:afterResponse');
|
|
expect(HOOK_EVENTS.RUNNER_BEFORE_COLLECTION_RUN).toBe('runner:beforeCollectionRun');
|
|
expect(HOOK_EVENTS.RUNNER_AFTER_COLLECTION_RUN).toBe('runner:afterCollectionRun');
|
|
});
|
|
|
|
it('should be frozen', () => {
|
|
expect(Object.isFrozen(HOOK_EVENTS)).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('executeHooksForLevel()', () => {
|
|
it('should return null for empty hooks file', async () => {
|
|
const result = await executeHooksForLevel('', HOOK_EVENTS.HTTP_BEFORE_REQUEST, {}, mockOptions);
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
it('should return null for whitespace-only hooks file', async () => {
|
|
const result = await executeHooksForLevel(' ', HOOK_EVENTS.HTTP_BEFORE_REQUEST, {}, mockOptions);
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
it('should execute hooks for valid hooks file', async () => {
|
|
const HooksRuntime = require('../src/runtime/hooks-runtime');
|
|
await executeHooksForLevel('console.log("test")', HOOK_EVENTS.HTTP_BEFORE_REQUEST, {}, mockOptions);
|
|
expect(HooksRuntime).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should handle errors gracefully', async () => {
|
|
const HooksRuntime = require('../src/runtime/hooks-runtime');
|
|
HooksRuntime.mockImplementationOnce(() => ({
|
|
runHooks: jest.fn().mockRejectedValue(new Error('Test error'))
|
|
}));
|
|
|
|
const consoleSpy = jest.spyOn(console, 'error').mockImplementation();
|
|
const result = await executeHooksForLevel('test()', HOOK_EVENTS.HTTP_BEFORE_REQUEST, {}, mockOptions);
|
|
expect(result).toBeNull();
|
|
consoleSpy.mockRestore();
|
|
});
|
|
});
|
|
|
|
describe('executeConsolidatedHooks()', () => {
|
|
it('should execute consolidated hooks', async () => {
|
|
const HooksRuntime = require('../src/runtime/hooks-runtime');
|
|
const extractedHooks = {
|
|
collectionHooks: 'collection()',
|
|
folderHooks: [{ hooks: 'folder()' }],
|
|
requestHooks: 'request()'
|
|
};
|
|
|
|
await executeConsolidatedHooks(extractedHooks, HOOK_EVENTS.HTTP_BEFORE_REQUEST, {}, mockOptions);
|
|
expect(HooksRuntime).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should handle errors gracefully', async () => {
|
|
const HooksRuntime = require('../src/runtime/hooks-runtime');
|
|
HooksRuntime.mockImplementationOnce(() => ({
|
|
runHooks: jest.fn().mockRejectedValue(new Error('Test error'))
|
|
}));
|
|
|
|
const consoleSpy = jest.spyOn(console, 'error').mockImplementation();
|
|
const result = await executeConsolidatedHooks(
|
|
{ collectionHooks: 'test()', folderHooks: [], requestHooks: '' },
|
|
HOOK_EVENTS.HTTP_BEFORE_REQUEST,
|
|
{},
|
|
mockOptions
|
|
);
|
|
expect(result).toBeNull();
|
|
consoleSpy.mockRestore();
|
|
});
|
|
});
|
|
|
|
describe('executeAllHookLevels()', () => {
|
|
it('should always use consolidated execution', async () => {
|
|
const extractedHooks = {
|
|
collectionHooks: 'collection()',
|
|
folderHooks: [{ hooks: 'folder()' }],
|
|
requestHooks: 'request()'
|
|
};
|
|
|
|
const HooksRuntime = require('../src/runtime/hooks-runtime');
|
|
await executeAllHookLevels(
|
|
extractedHooks,
|
|
HOOK_EVENTS.HTTP_BEFORE_REQUEST,
|
|
{},
|
|
mockOptions
|
|
);
|
|
|
|
// Should always use consolidated execution
|
|
const runtimeInstance = HooksRuntime.mock.results[0].value;
|
|
expect(runtimeInstance.runHooks).toHaveBeenCalledWith(
|
|
expect.objectContaining({ consolidated: true })
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('createHookExecutor()', () => {
|
|
it('should create executor with base options', () => {
|
|
const executor = createHookExecutor(mockOptions);
|
|
expect(executor).toBeDefined();
|
|
expect(typeof executor.executeLevel).toBe('function');
|
|
expect(typeof executor.executeConsolidated).toBe('function');
|
|
expect(typeof executor.executeAll).toBe('function');
|
|
});
|
|
|
|
it('should allow overriding options', async () => {
|
|
const executor = createHookExecutor(mockOptions);
|
|
const newConsoleLog = jest.fn();
|
|
|
|
await executor.executeLevel('test()', HOOK_EVENTS.HTTP_BEFORE_REQUEST, {}, {
|
|
onConsoleLog: newConsoleLog
|
|
});
|
|
|
|
// The override should be merged with base options
|
|
// Actual verification depends on implementation details
|
|
});
|
|
});
|
|
});
|