mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-15 20:01:28 +00:00
210 lines
8.2 KiB
JavaScript
210 lines
8.2 KiB
JavaScript
// Mocked so bru.sendRequest doesn't hit the network.
|
|
jest.mock('@usebruno/requests', () => {
|
|
const realCookies = jest.requireActual('@usebruno/requests').cookies;
|
|
return {
|
|
cookies: realCookies,
|
|
scripting: {
|
|
createSendRequest: jest.fn((_config, options) => {
|
|
return async (requestConfig) => {
|
|
const normalized = typeof requestConfig === 'string' ? { url: requestConfig } : requestConfig;
|
|
options?.onComplete?.({
|
|
request: {
|
|
method: (normalized.method || 'GET').toUpperCase(),
|
|
url: normalized.url,
|
|
headers: normalized.headers || {},
|
|
data: normalized.data
|
|
},
|
|
response: {
|
|
statusCode: 200,
|
|
statusText: 'OK',
|
|
headers: {},
|
|
data: 'mocked',
|
|
dataBuffer: Buffer.from('mocked').toString('base64'),
|
|
size: 6,
|
|
duration: 3
|
|
},
|
|
error: null,
|
|
startedAt: 1,
|
|
completedAt: 4
|
|
});
|
|
return { status: 200, data: 'mocked' };
|
|
};
|
|
})
|
|
}
|
|
};
|
|
});
|
|
|
|
const ScriptRuntime = require('../src/runtime/script-runtime');
|
|
const TestRuntime = require('../src/runtime/test-runtime');
|
|
|
|
const baseRequest = { method: 'GET', url: 'http://localhost/', headers: {}, data: undefined };
|
|
const baseResponse = { status: 200, statusText: 'OK', data: {} };
|
|
|
|
describe('ScriptRuntime — scripted entries across the three script phases', () => {
|
|
describe('pre-request (runRequestScript)', () => {
|
|
test('drains bru.sendRequest calls into result.scriptedRequestEntries', async () => {
|
|
const script = `await bru.sendRequest('https://example.com/ping');`;
|
|
const runtime = new ScriptRuntime({ runtime: 'nodevm' });
|
|
const result = await runtime.runRequestScript(
|
|
script, { ...baseRequest }, {}, {}, '.', null, process.env
|
|
);
|
|
|
|
expect(result.scriptedRequestEntries).toHaveLength(1);
|
|
expect(result.scriptedRequestEntries[0]).toEqual(
|
|
expect.objectContaining({
|
|
source: 'sendRequest',
|
|
request: expect.objectContaining({ url: 'https://example.com/ping' })
|
|
})
|
|
);
|
|
});
|
|
|
|
test('returns an empty array when the script makes no scripted requests', async () => {
|
|
const runtime = new ScriptRuntime({ runtime: 'nodevm' });
|
|
const result = await runtime.runRequestScript(
|
|
`bru.setVar('foo', 'bar');`, { ...baseRequest }, {}, {}, '.', null, process.env
|
|
);
|
|
expect(result.scriptedRequestEntries).toEqual([]);
|
|
});
|
|
|
|
test('__bruSetScope from inside the script stamps scope onto every later entry', async () => {
|
|
const script = `
|
|
__bruSetScope({ type: 'collection', sourceFile: 'collection.bru' });
|
|
await bru.sendRequest('https://example.com/a');
|
|
__bruSetScope({ type: 'request', sourceFile: 'auth/login.bru' });
|
|
await bru.sendRequest('https://example.com/b');
|
|
`;
|
|
const runtime = new ScriptRuntime({ runtime: 'nodevm' });
|
|
const result = await runtime.runRequestScript(
|
|
script, { ...baseRequest }, {}, {}, '.', null, process.env
|
|
);
|
|
|
|
expect(result.scriptedRequestEntries).toHaveLength(2);
|
|
expect(result.scriptedRequestEntries[0].scope).toEqual({ type: 'collection', sourceFile: 'collection.bru' });
|
|
expect(result.scriptedRequestEntries[1].scope).toEqual({ type: 'request', sourceFile: 'auth/login.bru' });
|
|
});
|
|
|
|
test('bru.runRequest is wired to the host function and records a runRequest entry', async () => {
|
|
// Stands in for the electron-side runRequestByItemPathname bridge.
|
|
const host = jest.fn(async (pathname, callerBru) => {
|
|
callerBru._recordScriptedRequest({
|
|
source: 'runRequest',
|
|
request: { method: 'GET', url: 'inferred/from/' + pathname, headers: {}, data: undefined },
|
|
response: { statusCode: 200, statusText: 'OK', headers: {}, data: '', dataBuffer: '', size: 0, duration: 1 },
|
|
error: null,
|
|
startedAt: 0,
|
|
completedAt: 1
|
|
});
|
|
return { status: 200 };
|
|
});
|
|
|
|
const script = `
|
|
__bruSetScope({ type: 'request', sourceFile: 'driver.bru' });
|
|
await bru.runRequest('target.bru');
|
|
`;
|
|
const runtime = new ScriptRuntime({ runtime: 'nodevm' });
|
|
const result = await runtime.runRequestScript(
|
|
script, { ...baseRequest }, {}, {}, '.', null, process.env, {}, host
|
|
);
|
|
|
|
expect(host).toHaveBeenCalledTimes(1);
|
|
// bindRunRequest must forward the caller's bru as the second arg.
|
|
expect(host.mock.calls[0][0]).toBe('target.bru');
|
|
expect(host.mock.calls[0][1]).toBeDefined();
|
|
expect(result.scriptedRequestEntries).toHaveLength(1);
|
|
expect(result.scriptedRequestEntries[0]).toEqual(
|
|
expect.objectContaining({
|
|
source: 'runRequest',
|
|
scope: { type: 'request', sourceFile: 'driver.bru' }
|
|
})
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('post-response (runResponseScript)', () => {
|
|
test('drains bru.sendRequest calls into result.scriptedRequestEntries', async () => {
|
|
const script = `await bru.sendRequest('https://example.com/after');`;
|
|
const runtime = new ScriptRuntime({ runtime: 'nodevm' });
|
|
const result = await runtime.runResponseScript(
|
|
script, { ...baseRequest }, { ...baseResponse }, {}, {}, '.', null, process.env
|
|
);
|
|
expect(result.scriptedRequestEntries).toHaveLength(1);
|
|
expect(result.scriptedRequestEntries[0].source).toBe('sendRequest');
|
|
});
|
|
|
|
test('records bru.runRequest calls with the current scope', async () => {
|
|
const host = jest.fn(async (_pathname, callerBru) => {
|
|
callerBru._recordScriptedRequest({
|
|
source: 'runRequest',
|
|
request: { method: 'GET', url: 'x', headers: {}, data: undefined },
|
|
response: null,
|
|
error: null,
|
|
startedAt: 0,
|
|
completedAt: 0
|
|
});
|
|
});
|
|
const script = `
|
|
__bruSetScope({ type: 'folder', sourceFile: 'auth/folder.bru' });
|
|
await bru.runRequest('next.bru');
|
|
`;
|
|
const runtime = new ScriptRuntime({ runtime: 'nodevm' });
|
|
const result = await runtime.runResponseScript(
|
|
script, { ...baseRequest }, { ...baseResponse }, {}, {}, '.', null, process.env, {}, host
|
|
);
|
|
|
|
expect(result.scriptedRequestEntries).toHaveLength(1);
|
|
expect(result.scriptedRequestEntries[0]).toEqual(
|
|
expect.objectContaining({
|
|
source: 'runRequest',
|
|
scope: { type: 'folder', sourceFile: 'auth/folder.bru' }
|
|
})
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('tests (TestRuntime.runTests)', () => {
|
|
test('drains scripted requests issued from inside test scripts', async () => {
|
|
const testsFile = `
|
|
__bruSetScope({ type: 'request', sourceFile: 'spec.bru' });
|
|
test('calls sendRequest', async () => {
|
|
await bru.sendRequest('https://example.com/from-tests');
|
|
});
|
|
`;
|
|
const runtime = new TestRuntime({ runtime: 'nodevm' });
|
|
const result = await runtime.runTests(
|
|
testsFile, { ...baseRequest }, { ...baseResponse }, {}, {}, '.', null, process.env
|
|
);
|
|
|
|
expect(result.scriptedRequestEntries).toHaveLength(1);
|
|
expect(result.scriptedRequestEntries[0]).toEqual(
|
|
expect.objectContaining({
|
|
source: 'sendRequest',
|
|
scope: { type: 'request', sourceFile: 'spec.bru' },
|
|
request: expect.objectContaining({ url: 'https://example.com/from-tests' })
|
|
})
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('partial results on script error', () => {
|
|
test('pre-request: entries recorded before the throw are preserved on partialResults', async () => {
|
|
const script = `
|
|
await bru.sendRequest('https://example.com/before');
|
|
throw new Error('explode');
|
|
`;
|
|
const runtime = new ScriptRuntime({ runtime: 'nodevm' });
|
|
|
|
let captured;
|
|
try {
|
|
await runtime.runRequestScript(script, { ...baseRequest }, {}, {}, '.', null, process.env);
|
|
} catch (err) {
|
|
captured = err;
|
|
}
|
|
|
|
expect(captured).toBeDefined();
|
|
expect(captured.partialResults).toBeDefined();
|
|
expect(captured.partialResults.scriptedRequestEntries).toHaveLength(1);
|
|
expect(captured.partialResults.scriptedRequestEntries[0].source).toBe('sendRequest');
|
|
});
|
|
});
|
|
});
|