Files
bruno/packages/bruno-js/tests/bru-scripted-entries.spec.js

133 lines
4.7 KiB
JavaScript

// Mocked so we can drive onComplete directly without hitting the network. We
// defer onComplete to a microtask so it fires after the synchronous call site
// returns (same timing as a real network call, and what the race-condition
// test below relies on).
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;
await Promise.resolve();
options?.onComplete?.({
request: {
method: (normalized.method || 'GET').toUpperCase(),
url: normalized.url,
headers: normalized.headers || {},
data: normalized.data
},
response: {
statusCode: 200,
statusText: 'OK',
headers: { 'content-type': 'text/plain' },
data: 'ok',
dataBuffer: Buffer.from('ok').toString('base64'),
size: 2,
duration: 4
},
error: null,
startedAt: 1,
completedAt: 5
});
return { status: 200, data: 'ok' };
};
})
}
};
});
const Bru = require('../src/bru');
const makeBru = () =>
new Bru({
runtime: 'quickjs',
envVariables: {},
runtimeVariables: {},
processEnvVars: {},
collectionPath: '/coll',
collectionName: 'Test',
certsAndProxyConfig: { collectionPath: '/coll' }
});
describe('Bru — scripted request capture', () => {
test('starts with an empty scriptedRequestEntries array', () => {
const bru = makeBru();
expect(bru.scriptedRequestEntries).toEqual([]);
});
test('records a sendRequest call with source = "sendRequest"', async () => {
const bru = makeBru();
await bru.sendRequest({ method: 'get', url: 'https://example.com/ping' });
expect(bru.scriptedRequestEntries).toHaveLength(1);
expect(bru.scriptedRequestEntries[0]).toEqual(
expect.objectContaining({
source: 'sendRequest',
request: expect.objectContaining({ method: 'GET', url: 'https://example.com/ping' }),
response: expect.objectContaining({ statusCode: 200, statusText: 'OK' })
})
);
});
test('records null scope when no _currentScope is set', async () => {
const bru = makeBru();
await bru.sendRequest('https://example.com');
expect(bru.scriptedRequestEntries[0].scope).toBeNull();
});
test('stamps the current scope onto each entry (snapshot, not reference)', async () => {
const bru = makeBru();
bru._currentScope = { type: 'collection', sourceFile: 'collection.bru' };
await bru.sendRequest('https://example.com/a');
// Flip scope. The earlier entry must keep its original snapshot.
bru._currentScope = { type: 'request', sourceFile: 'auth/login.bru' };
await bru.sendRequest('https://example.com/b');
expect(bru.scriptedRequestEntries).toHaveLength(2);
expect(bru.scriptedRequestEntries[0].scope).toEqual({ type: 'collection', sourceFile: 'collection.bru' });
expect(bru.scriptedRequestEntries[1].scope).toEqual({ type: 'request', sourceFile: 'auth/login.bru' });
});
test('uses scope at call time, not completion time, for non-awaited sendRequest', async () => {
const bru = makeBru();
// Fire-and-forget call in scope A.
bru._currentScope = { type: 'collection', sourceFile: 'collection.bru' };
const inFlight = bru.sendRequest('https://example.com/late');
// The host moves to the next segment and __bruSetScope flips the scope
// before the network call settles.
bru._currentScope = { type: 'request', sourceFile: 'auth/login.bru' };
await inFlight;
expect(bru.scriptedRequestEntries).toHaveLength(1);
expect(bru.scriptedRequestEntries[0].scope).toEqual({ type: 'collection', sourceFile: 'collection.bru' });
});
test('_recordScriptedRequest accepts entries from other sources (e.g. runRequest)', () => {
const bru = makeBru();
bru._currentScope = { type: 'folder', sourceFile: 'auth/folder.bru' };
bru._recordScriptedRequest({
source: 'runRequest',
request: { method: 'GET', url: 'https://example.com/user' },
response: { statusCode: 200, statusText: 'OK', headers: {}, data: 'x', dataBuffer: '', size: 0, duration: 1 },
error: null,
startedAt: 10,
completedAt: 11
});
expect(bru.scriptedRequestEntries).toHaveLength(1);
expect(bru.scriptedRequestEntries[0]).toEqual(
expect.objectContaining({
source: 'runRequest',
scope: { type: 'folder', sourceFile: 'auth/folder.bru' }
})
);
});
});