2017-11-26 20:45:40 +00:00
|
|
|
const tag = require('..').templateTags[0];
|
2017-12-01 14:18:38 +00:00
|
|
|
const iconv = require('iconv-lite');
|
2017-11-26 20:45:40 +00:00
|
|
|
|
|
|
|
describe('Response tag', () => {
|
|
|
|
describe('General', () => {
|
|
|
|
it('fails on no responses', async () => {
|
2018-06-25 17:42:50 +00:00
|
|
|
const requests = [{ _id: 'req_1', parentId: 'wrk_1' }];
|
2017-11-26 20:45:40 +00:00
|
|
|
|
|
|
|
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 () => {
|
2018-06-25 17:42:50 +00:00
|
|
|
const requests = [{ _id: 'req_1', parentId: 'wrk_1' }];
|
|
|
|
|
|
|
|
const responses = [
|
|
|
|
{
|
|
|
|
_id: 'res_1',
|
|
|
|
parentId: 'req_1',
|
|
|
|
statusCode: 200,
|
|
|
|
_body: '{"foo": "bar"}'
|
|
|
|
}
|
|
|
|
];
|
2017-11-26 20:45:40 +00:00
|
|
|
|
|
|
|
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 () => {
|
2018-06-25 17:42:50 +00:00
|
|
|
const requests = [{ _id: 'req_1', parentId: 'wrk_1' }];
|
|
|
|
|
|
|
|
const responses = [
|
|
|
|
{
|
|
|
|
_id: 'res_1',
|
|
|
|
parentId: 'req_1',
|
|
|
|
statusCode: 200,
|
|
|
|
_body: '{"foo": "bar"}'
|
|
|
|
}
|
|
|
|
];
|
2017-11-26 20:45:40 +00:00
|
|
|
|
|
|
|
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 () => {
|
2018-06-25 17:42:50 +00:00
|
|
|
const requests = [{ _id: 'req_1', parentId: 'wrk_1' }];
|
|
|
|
|
|
|
|
const responses = [
|
|
|
|
{
|
|
|
|
_id: 'res_1',
|
|
|
|
parentId: 'req_1',
|
|
|
|
statusCode: 200,
|
|
|
|
contentType: 'application/json',
|
|
|
|
_body: '{"foo": "bar"}'
|
|
|
|
}
|
|
|
|
];
|
2017-11-26 20:45:40 +00:00
|
|
|
|
|
|
|
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 () => {
|
2018-06-25 17:42:50 +00:00
|
|
|
const requests = [{ _id: 'req_1', parentId: 'wrk_1' }];
|
|
|
|
|
|
|
|
const responses = [
|
|
|
|
{
|
|
|
|
_id: 'res_1',
|
|
|
|
parentId: 'req_1',
|
|
|
|
statusCode: 200,
|
|
|
|
contentType: 'application/json',
|
|
|
|
_body: '{"foo": "'
|
|
|
|
}
|
|
|
|
];
|
2017-11-26 20:45:40 +00:00
|
|
|
|
|
|
|
const context = _genTestContext(requests, responses);
|
|
|
|
|
|
|
|
try {
|
|
|
|
await tag.run(context, 'body', 'req_1', '$.foo');
|
|
|
|
fail('JSON should have failed');
|
|
|
|
} catch (err) {
|
2018-10-17 16:42:33 +00:00
|
|
|
expect(err.message).toContain('Invalid JSON: Unexpected end of JSON input');
|
2017-11-26 20:45:40 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
it('fails on invalid query', async () => {
|
2018-06-25 17:42:50 +00:00
|
|
|
const requests = [{ _id: 'req_1', parentId: 'wrk_1' }];
|
|
|
|
|
|
|
|
const responses = [
|
|
|
|
{
|
|
|
|
_id: 'res_1',
|
|
|
|
parentId: 'req_1',
|
|
|
|
statusCode: 200,
|
|
|
|
contentType: 'application/json',
|
|
|
|
_body: '{"foo": "bar"}'
|
|
|
|
}
|
|
|
|
];
|
2017-11-26 20:45:40 +00:00
|
|
|
|
|
|
|
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 () => {
|
2018-06-25 17:42:50 +00:00
|
|
|
const requests = [{ _id: 'req_1', parentId: 'wrk_1' }];
|
|
|
|
|
|
|
|
const responses = [
|
|
|
|
{
|
|
|
|
_id: 'res_1',
|
|
|
|
parentId: 'req_1',
|
|
|
|
statusCode: 200,
|
|
|
|
contentType: 'application/json',
|
|
|
|
_body: '{"foo": "bar"}'
|
|
|
|
}
|
|
|
|
];
|
2017-11-26 20:45:40 +00:00
|
|
|
|
|
|
|
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 () => {
|
2018-06-25 17:42:50 +00:00
|
|
|
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"]}'
|
|
|
|
}
|
|
|
|
];
|
2017-11-26 20:45:40 +00:00
|
|
|
|
|
|
|
const context = _genTestContext(requests, responses);
|
|
|
|
|
|
|
|
try {
|
|
|
|
await tag.run(context, 'body', 'req_1', '$.array.*');
|
|
|
|
fail('JSON should have failed to parse');
|
|
|
|
} catch (err) {
|
2018-10-17 16:42:33 +00:00
|
|
|
expect(err.message).toContain('Returned more than one result: $.array.*');
|
2017-11-26 20:45:40 +00:00
|
|
|
}
|
|
|
|
});
|
2017-12-01 14:18:38 +00:00
|
|
|
|
|
|
|
it('works with utf-16 encoding', async () => {
|
2018-06-25 17:42:50 +00:00
|
|
|
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')
|
|
|
|
}
|
|
|
|
];
|
2017-12-01 14:18:38 +00:00
|
|
|
|
|
|
|
const context = _genTestContext(requests, responses);
|
|
|
|
|
|
|
|
expect(await tag.run(context, 'body', 'req_1', '$.array[0]')).toBe('bar');
|
|
|
|
});
|
2017-11-26 20:45:40 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('XPath', async () => {
|
|
|
|
it('renders basic response "body" query', async () => {
|
2018-06-25 17:42:50 +00:00
|
|
|
const requests = [{ _id: 'req_1', parentId: 'wrk_1' }];
|
|
|
|
|
|
|
|
const responses = [
|
|
|
|
{
|
|
|
|
_id: 'res_1',
|
|
|
|
parentId: 'req_1',
|
|
|
|
statusCode: 200,
|
|
|
|
contentType: 'application/xml',
|
|
|
|
_body: '<foo><bar>Hello World!</bar></foo>'
|
|
|
|
}
|
|
|
|
];
|
2017-11-26 20:45:40 +00:00
|
|
|
|
|
|
|
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 () => {
|
2018-06-25 17:42:50 +00:00
|
|
|
const requests = [{ _id: 'req_1', parentId: 'wrk_1' }];
|
|
|
|
|
|
|
|
const responses = [
|
|
|
|
{
|
|
|
|
_id: 'res_1',
|
|
|
|
parentId: 'req_1',
|
|
|
|
statusCode: 200,
|
|
|
|
contentType: 'application/xml',
|
|
|
|
_body: '<foo><bar hello="World">Hello World!</bar></foo>'
|
|
|
|
}
|
|
|
|
];
|
2017-11-26 20:45:40 +00:00
|
|
|
|
|
|
|
const context = _genTestContext(requests, responses);
|
|
|
|
const result = await tag.run(context, 'body', 'req_1', '/foo/bar/@hello');
|
|
|
|
|
|
|
|
expect(result).toBe('World');
|
|
|
|
});
|
|
|
|
|
2018-01-16 05:46:24 +00:00
|
|
|
it('renders query that does not start with slash', async () => {
|
2018-06-25 17:42:50 +00:00
|
|
|
const requests = [{ _id: 'req_1', parentId: 'wrk_1' }];
|
|
|
|
|
|
|
|
const responses = [
|
|
|
|
{
|
|
|
|
_id: 'res_1',
|
|
|
|
parentId: 'req_1',
|
|
|
|
statusCode: 200,
|
|
|
|
contentType: 'application/xml',
|
|
|
|
_body: '<foo><bar hello="World">Hello World!</bar></foo>'
|
|
|
|
}
|
|
|
|
];
|
2018-01-16 05:46:24 +00:00
|
|
|
|
|
|
|
const context = _genTestContext(requests, responses);
|
2018-10-17 16:42:33 +00:00
|
|
|
const result = await tag.run(context, 'body', 'req_1', 'substring(/foo/bar, 7)');
|
2018-01-16 05:46:24 +00:00
|
|
|
|
|
|
|
expect(result).toBe('World!');
|
|
|
|
});
|
|
|
|
|
2017-11-26 20:45:40 +00:00
|
|
|
it('no results on invalid XML', async () => {
|
2018-06-25 17:42:50 +00:00
|
|
|
const requests = [{ _id: 'req_1', parentId: 'wrk_1' }];
|
|
|
|
|
|
|
|
const responses = [
|
|
|
|
{
|
|
|
|
_id: 'res_1',
|
|
|
|
parentId: 'req_1',
|
|
|
|
statusCode: 200,
|
|
|
|
contentType: 'application/xml',
|
|
|
|
_body: '<hi></hi></sstr>'
|
|
|
|
}
|
|
|
|
];
|
2017-11-26 20:45:40 +00:00
|
|
|
|
|
|
|
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 () => {
|
2018-06-25 17:42:50 +00:00
|
|
|
const requests = [{ _id: 'req_1', parentId: 'wrk_1' }];
|
|
|
|
|
|
|
|
const responses = [
|
|
|
|
{
|
|
|
|
_id: 'res_1',
|
|
|
|
parentId: 'req_1',
|
|
|
|
statusCode: 200,
|
|
|
|
contentType: 'application/xml',
|
|
|
|
_body: '<foo></foo>'
|
|
|
|
}
|
|
|
|
];
|
2017-11-26 20:45:40 +00:00
|
|
|
|
|
|
|
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 () => {
|
2018-06-25 17:42:50 +00:00
|
|
|
const requests = [{ _id: 'req_1', parentId: 'wrk_1' }];
|
|
|
|
|
|
|
|
const responses = [
|
|
|
|
{
|
|
|
|
_id: 'res_1',
|
|
|
|
parentId: 'req_1',
|
|
|
|
statusCode: 200,
|
|
|
|
contentType: 'application/xml',
|
|
|
|
_body: '<foo></foo>'
|
|
|
|
}
|
|
|
|
];
|
2017-11-26 20:45:40 +00:00
|
|
|
|
|
|
|
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 () => {
|
2018-06-25 17:42:50 +00:00
|
|
|
const requests = [{ _id: 'req_1', parentId: 'wrk_1' }];
|
|
|
|
|
|
|
|
const responses = [
|
|
|
|
{
|
|
|
|
_id: 'res_1',
|
|
|
|
parentId: 'req_1',
|
|
|
|
statusCode: 200,
|
|
|
|
contentType: 'application/xml',
|
|
|
|
_body: '<foo><bar>Hello World!</bar><bar>And again!</bar></foo>'
|
|
|
|
}
|
|
|
|
];
|
2017-11-26 20:45:40 +00:00
|
|
|
|
|
|
|
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 () => {
|
2018-06-25 17:42:50 +00:00
|
|
|
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' }
|
|
|
|
]
|
|
|
|
}
|
|
|
|
];
|
2017-11-26 20:45:40 +00:00
|
|
|
|
|
|
|
const context = _genTestContext(requests, responses);
|
|
|
|
|
2018-10-17 16:42:33 +00:00
|
|
|
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(
|
2018-06-25 17:42:50 +00:00
|
|
|
'application/json'
|
|
|
|
);
|
2017-11-26 20:45:40 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('no results on missing header', async () => {
|
2018-06-25 17:42:50 +00:00
|
|
|
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' }
|
|
|
|
]
|
|
|
|
}
|
|
|
|
];
|
2017-11-26 20:45:40 +00:00
|
|
|
|
|
|
|
const context = _genTestContext(requests, responses);
|
|
|
|
|
|
|
|
try {
|
|
|
|
await tag.run(context, 'header', 'req_1', 'missing');
|
|
|
|
fail('should have failed');
|
|
|
|
} catch (err) {
|
2018-06-25 17:42:50 +00:00
|
|
|
expect(err.message).toBe(
|
|
|
|
'No header with name "missing".\n' +
|
|
|
|
'Choices are [\n\t"Content-Type",\n\t"Content-Length"\n]'
|
|
|
|
);
|
2017-11-26 20:45:40 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('Raw', async () => {
|
|
|
|
it('renders basic response', async () => {
|
2018-06-25 17:42:50 +00:00
|
|
|
const requests = [{ _id: 'req_1', parentId: 'wrk_1' }];
|
|
|
|
|
|
|
|
const responses = [
|
|
|
|
{
|
|
|
|
_id: 'res_1',
|
|
|
|
parentId: 'req_1',
|
|
|
|
statusCode: 200,
|
|
|
|
contentType: 'text/plain',
|
|
|
|
_body: 'Hello World!'
|
|
|
|
}
|
|
|
|
];
|
2017-11-26 20:45:40 +00:00
|
|
|
|
|
|
|
const context = _genTestContext(requests, responses);
|
|
|
|
|
|
|
|
expect(await tag.run(context, 'raw', 'req_1')).toBe('Hello World!');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2018-06-25 17:42:50 +00:00
|
|
|
function _genTestContext(requests, responses) {
|
2017-11-26 20:45:40 +00:00
|
|
|
requests = requests || [];
|
|
|
|
responses = responses || [];
|
|
|
|
const bodies = {};
|
|
|
|
for (const res of responses) {
|
|
|
|
bodies[res._id] = res._body || null;
|
|
|
|
delete res._body;
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
util: {
|
|
|
|
models: {
|
|
|
|
request: {
|
2018-06-25 17:42:50 +00:00
|
|
|
getById(requestId) {
|
2017-11-26 20:45:40 +00:00
|
|
|
return requests.find(r => r._id === requestId) || null;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
response: {
|
2018-06-25 17:42:50 +00:00
|
|
|
getLatestForRequestId(requestId) {
|
2017-11-26 20:45:40 +00:00
|
|
|
return responses.find(r => r.parentId === requestId) || null;
|
|
|
|
},
|
2018-06-25 17:42:50 +00:00
|
|
|
getBodyBuffer(response) {
|
2017-12-01 14:18:38 +00:00
|
|
|
const strOrBuffer = bodies[response._id];
|
|
|
|
|
|
|
|
if (typeof strOrBuffer === 'string') {
|
|
|
|
return Buffer.from(strOrBuffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strOrBuffer) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return strOrBuffer;
|
2017-11-26 20:45:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|