const tag = require('..').templateTags[0];
const iconv = require('iconv-lite');
describe('Response tag', () => {
describe('General', () => {
it('fails on no responses', async () => {
const requests = [{_id: 'req_1', parentId: 'wrk_1'}];
const context = _genTestContext(requests);
try {
await tag.run(context, 'body', 'req_1', '$.foo');
fail('JSON should have failed');
} catch (err) {
expect(err.message).toContain('No responses for request');
}
});
it('fails on no request', async () => {
const requests = [{_id: 'req_1', parentId: 'wrk_1'}];
const responses = [{
_id: 'res_1',
parentId: 'req_1',
statusCode: 200,
_body: '{"foo": "bar"}'
}];
const context = _genTestContext(requests, responses);
try {
await tag.run(context, 'body', 'req_test', '$.foo');
fail('JSON should have failed');
} catch (err) {
expect(err.message).toContain('Could not find request req_test');
}
});
it('fails on empty filter', async () => {
const requests = [{_id: 'req_1', parentId: 'wrk_1'}];
const responses = [{
_id: 'res_1',
parentId: 'req_1',
statusCode: 200,
_body: '{"foo": "bar"}'
}];
const context = _genTestContext(requests, responses);
try {
await tag.run(context, 'body', 'req_1', '');
fail('JSON should have failed');
} catch (err) {
expect(err.message).toContain('No body filter specified');
}
});
});
describe('JSONPath', () => {
it('basic query', async () => {
const requests = [{_id: 'req_1', parentId: 'wrk_1'}];
const responses = [{
_id: 'res_1',
parentId: 'req_1',
statusCode: 200,
contentType: 'application/json',
_body: '{"foo": "bar"}'
}];
const context = _genTestContext(requests, responses);
const result = await tag.run(context, 'body', 'req_1', '$.foo');
expect(result).toBe('bar');
});
it('fails on invalid JSON', async () => {
const requests = [{_id: 'req_1', parentId: 'wrk_1'}];
const responses = [{
_id: 'res_1',
parentId: 'req_1',
statusCode: 200,
contentType: 'application/json',
_body: '{"foo": "'
}];
const context = _genTestContext(requests, responses);
try {
await tag.run(context, 'body', 'req_1', '$.foo');
fail('JSON should have failed');
} catch (err) {
expect(err.message).toContain('Invalid JSON: Unexpected end of JSON input');
}
});
it('fails on invalid query', async () => {
const requests = [{_id: 'req_1', parentId: 'wrk_1'}];
const responses = [{
_id: 'res_1',
parentId: 'req_1',
statusCode: 200,
contentType: 'application/json',
_body: '{"foo": "bar"}'
}];
const context = _genTestContext(requests, responses);
try {
await tag.run(context, 'body', 'req_1', '$$');
fail('JSON should have failed');
} catch (err) {
expect(err.message).toContain('Invalid JSONPath query: $$');
}
});
it('fails on no results', async () => {
const requests = [{_id: 'req_1', parentId: 'wrk_1'}];
const responses = [{
_id: 'res_1',
parentId: 'req_1',
statusCode: 200,
contentType: 'application/json',
_body: '{"foo": "bar"}'
}];
const context = _genTestContext(requests, responses);
try {
await tag.run(context, 'body', 'req_1', '$.missing');
fail('JSON should have failed');
} catch (err) {
expect(err.message).toContain('Returned no results: $.missing');
}
});
it('fails on more than 1 result', async () => {
const requests = [{_id: 'req_1', parentId: 'wrk_1'}];
const responses = [{
_id: 'res_1',
parentId: 'req_1',
statusCode: 200,
contentType: 'application/json',
_body: '{"array": ["bar", "baz"]}'
}];
const context = _genTestContext(requests, responses);
try {
await tag.run(context, 'body', 'req_1', '$.array.*');
fail('JSON should have failed to parse');
} catch (err) {
expect(err.message).toContain('Returned more than one result: $.array.*');
}
});
it('works with utf-16 encoding', async () => {
const requests = [{_id: 'req_1', parentId: 'wrk_1'}];
const responses = [{
_id: 'res_1',
parentId: 'req_1',
statusCode: 200,
contentType: 'application/json; charset=UTF-16',
_body: iconv.encode('{"array": ["bar", "baz"]}', 'UTF-16')
}];
const context = _genTestContext(requests, responses);
expect(await tag.run(context, 'body', 'req_1', '$.array[0]')).toBe('bar');
});
});
describe('XPath', async () => {
it('renders basic response "body" query', async () => {
const requests = [{_id: 'req_1', parentId: 'wrk_1'}];
const responses = [{
_id: 'res_1',
parentId: 'req_1',
statusCode: 200,
contentType: 'application/xml',
_body: 'Hello World!'
}];
const context = _genTestContext(requests, responses);
const result = await tag.run(context, 'body', 'req_1', '/foo/bar');
expect(result).toBe('Hello World!');
});
it('renders basic response "body" attribute query', async () => {
const requests = [{_id: 'req_1', parentId: 'wrk_1'}];
const responses = [{
_id: 'res_1',
parentId: 'req_1',
statusCode: 200,
contentType: 'application/xml',
_body: 'Hello World!'
}];
const context = _genTestContext(requests, responses);
const result = await tag.run(context, 'body', 'req_1', '/foo/bar/@hello');
expect(result).toBe('World');
});
it('renders query that does not start with slash', async () => {
const requests = [{_id: 'req_1', parentId: 'wrk_1'}];
const responses = [{
_id: 'res_1',
parentId: 'req_1',
statusCode: 200,
contentType: 'application/xml',
_body: 'Hello World!'
}];
const context = _genTestContext(requests, responses);
const result = await tag.run(context, 'body', 'req_1', 'substring(/foo/bar, 7)');
expect(result).toBe('World!');
});
it('no results on invalid XML', async () => {
const requests = [{_id: 'req_1', parentId: 'wrk_1'}];
const responses = [{
_id: 'res_1',
parentId: 'req_1',
statusCode: 200,
contentType: 'application/xml',
_body: ''
}];
const context = _genTestContext(requests, responses);
try {
await tag.run(context, 'body', 'req_1', '/foo');
fail('Should have failed');
} catch (err) {
expect(err.message).toContain('Returned no results: /foo');
}
});
it('fails on invalid query', async () => {
const requests = [{_id: 'req_1', parentId: 'wrk_1'}];
const responses = [{
_id: 'res_1',
parentId: 'req_1',
statusCode: 200,
contentType: 'application/xml',
_body: ''
}];
const context = _genTestContext(requests, responses);
try {
await tag.run(context, 'body', 'req_1', '//');
fail('Should have failed');
} catch (err) {
expect(err.message).toContain('Invalid XPath query: //');
}
});
it('fails on no results', async () => {
const requests = [{_id: 'req_1', parentId: 'wrk_1'}];
const responses = [{
_id: 'res_1',
parentId: 'req_1',
statusCode: 200,
contentType: 'application/xml',
_body: ''
}];
const context = _genTestContext(requests, responses);
try {
await tag.run(context, 'body', 'req_1', '/missing');
fail('Should have failed');
} catch (err) {
expect(err.message).toContain('Returned no results: /missing');
}
});
it('fails on more than 1 result', async () => {
const requests = [{_id: 'req_1', parentId: 'wrk_1'}];
const responses = [{
_id: 'res_1',
parentId: 'req_1',
statusCode: 200,
contentType: 'application/xml',
_body: 'Hello World!And again!'
}];
const context = _genTestContext(requests, responses);
try {
await tag.run(context, 'body', 'req_1', '/foo/*');
fail('Should have failed');
} catch (err) {
expect(err.message).toContain('Returned more than one result: /foo/*');
}
});
});
describe('ResponseExtension Header', async () => {
it('renders basic response "header"', async () => {
const requests = [{_id: 'req_1', parentId: 'wrk_1'}];
const responses = [{
_id: 'res_1',
parentId: 'req_1',
statusCode: 200,
contentType: '',
headers: [
{name: 'Content-Type', value: 'application/json'},
{name: 'Content-Length', value: '20'}
]
}];
const context = _genTestContext(requests, responses);
expect(await tag.run(context, 'header', 'req_1', 'content-type')).toBe('application/json');
expect(await tag.run(context, 'header', 'req_1', 'Content-Type')).toBe('application/json');
expect(await tag.run(context, 'header', 'req_1', 'CONTENT-type')).toBe('application/json');
expect(await tag.run(context, 'header', 'req_1', 'CONTENT-type ')).toBe('application/json');
});
it('no results on missing header', async () => {
const requests = [{_id: 'req_1', parentId: 'wrk_1'}];
const responses = [{
_id: 'res_1',
parentId: 'req_1',
statusCode: 200,
headers: [
{name: 'Content-Type', value: 'application/json'},
{name: 'Content-Length', value: '20'}
]
}];
const context = _genTestContext(requests, responses);
try {
await tag.run(context, 'header', 'req_1', 'missing');
fail('should have failed');
} catch (err) {
expect(err.message).toBe('No header with name "missing".\n' +
'Choices are [\n\t"Content-Type",\n\t"Content-Length"\n]');
}
});
});
describe('Raw', async () => {
it('renders basic response', async () => {
const requests = [{_id: 'req_1', parentId: 'wrk_1'}];
const responses = [{
_id: 'res_1',
parentId: 'req_1',
statusCode: 200,
contentType: 'text/plain',
_body: 'Hello World!'
}];
const context = _genTestContext(requests, responses);
expect(await tag.run(context, 'raw', 'req_1')).toBe('Hello World!');
});
});
});
function _genTestContext (requests, responses) {
requests = requests || [];
responses = responses || [];
const bodies = {};
for (const res of responses) {
bodies[res._id] = res._body || null;
delete res._body;
}
return {
util: {
models: {
request: {
getById (requestId) {
return requests.find(r => r._id === requestId) || null;
}
},
response: {
getLatestForRequestId (requestId) {
return responses.find(r => r.parentId === requestId) || null;
},
getBodyBuffer (response) {
const strOrBuffer = bodies[response._id];
if (typeof strOrBuffer === 'string') {
return Buffer.from(strOrBuffer);
}
if (!strOrBuffer) {
return null;
}
return strOrBuffer;
}
}
}
}
};
}