From 6aecf5d764e5dac608eeba9a0067a9ca57a15571 Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Wed, 17 May 2017 09:06:42 -0700 Subject: [PATCH] Add tests for XPath response queries --- .../__tests__/response-extension.test.js | 122 ++++++++++++++---- .../extensions/response-extension.js | 18 +-- app/ui/components/templating/tag-editor.js | 6 +- 3 files changed, 107 insertions(+), 39 deletions(-) diff --git a/app/templating/extensions/__tests__/response-extension.test.js b/app/templating/extensions/__tests__/response-extension.test.js index 498823024..618af28ea 100644 --- a/app/templating/extensions/__tests__/response-extension.test.js +++ b/app/templating/extensions/__tests__/response-extension.test.js @@ -2,7 +2,32 @@ import * as templating from '../../index'; import * as db from '../../../common/database'; import * as models from '../../../models'; -describe('ResponseExtension', async () => { +describe('ResponseExtension General', async () => { + beforeEach(() => db.init(models.types(), {inMemoryOnly: true}, true)); + it('fails on no responses', async () => { + const request = await models.request.create({parentId: 'foo'}); + + try { + await templating.render(`{% response "body", "${request._id}", "$.foo" %}`); + fail('JSON should have failed to parse'); + } catch (err) { + expect(err.message).toContain('No responses for request'); + } + }); + + it('fails on no request', async () => { + await models.response.create({parentId: 'req_test', body: '{"foo": "bar"}'}); + + try { + await templating.render(`{% response "body", "req_test", "$.foo" %}`); + fail('JSON should have failed to parse'); + } catch (err) { + expect(err.message).toContain('Could not find request req_test'); + } + }); +}); + +describe('ResponseExtension JSONPath', async () => { beforeEach(() => db.init(models.types(), {inMemoryOnly: true}, true)); it('renders basic response "body", query', async () => { @@ -26,28 +51,6 @@ describe('ResponseExtension', async () => { } }); - it('fails on no responses', async () => { - const request = await models.request.create({parentId: 'foo'}); - - try { - await templating.render(`{% response "body", "${request._id}", "$.foo" %}`); - fail('JSON should have failed to parse'); - } catch (err) { - expect(err.message).toContain('No responses for request'); - } - }); - - it('fails on no request', async () => { - await models.response.create({parentId: 'req_test', body: '{"foo": "bar"}'}); - - try { - await templating.render(`{% response "body", "req_test", "$.foo" %}`); - fail('JSON should have failed to parse'); - } catch (err) { - expect(err.message).toContain('Could not find request req_test'); - } - }); - it('fails on invalid query', async () => { const request = await models.request.create({parentId: 'foo'}); await models.response.create({parentId: request._id, body: '{"foo": "bar"}'}); @@ -84,3 +87,76 @@ describe('ResponseExtension', async () => { } }); }); + +describe('ResponseExtension XPath', async () => { + beforeEach(() => db.init(models.types(), {inMemoryOnly: true}, true)); + + it('renders basic response "body", query', async () => { + const request = await models.request.create({parentId: 'foo'}); + await models.response.create({ + parentId: request._id, + body: 'Hello World!' + }); + + const result = await templating.render(`{% response "body", "${request._id}", "/foo/bar" %}`); + + expect(result).toBe('Hello World!'); + }); + + it('no results on invalid XML', async () => { + const request = await models.request.create({parentId: 'foo'}); + await models.response.create({parentId: request._id, body: ''}); + + try { + await templating.render(`{% response "body", "${request._id}", "/foo" %}`); + fail('should have failed'); + } catch (err) { + expect(err.message).toContain('Returned no results: /foo'); + } + }); + + it('fails on invalid query', async () => { + const request = await models.request.create({parentId: 'foo'}); + await models.response.create({ + parentId: request._id, + body: 'Hello World!' + }); + + try { + await templating.render(`{% response "body", "${request._id}", "//" %}`); + fail('should have failed'); + } catch (err) { + expect(err.message).toContain('Invalid XPath query: //'); + } + }); + + it('fails on no results', async () => { + const request = await models.request.create({parentId: 'foo'}); + await models.response.create({ + parentId: request._id, + body: 'Hello World!' + }); + + try { + await templating.render(`{% response "body", "${request._id}", "/missing" %}`); + fail('should have failed'); + } catch (err) { + expect(err.message).toContain('Returned no results: /missing'); + } + }); + + it('fails on more than 1 result', async () => { + const request = await models.request.create({parentId: 'foo'}); + await models.response.create({ + parentId: request._id, + body: 'Hello World!And again!' + }); + + try { + await templating.render(`{% response "body", "${request._id}", "/foo/*" %}`); + fail('should have failed'); + } catch (err) { + expect(err.message).toContain('Returned more than one result: /foo/*'); + } + }); +}); diff --git a/app/templating/extensions/response-extension.js b/app/templating/extensions/response-extension.js index 9811b6450..f31776d1f 100644 --- a/app/templating/extensions/response-extension.js +++ b/app/templating/extensions/response-extension.js @@ -5,19 +5,14 @@ import * as models from '../../models'; import BaseExtension from './base/base-extension'; -const TAG_NAME = 'response'; -const TAG_NAME_SHORT = 'res'; - -const FIELD_BODY = ['body', 'b']; - export default class ResponseExtension extends BaseExtension { constructor () { super(); - this.tags = [TAG_NAME, TAG_NAME_SHORT]; + this.tags = ['response']; } async run (context, field, id, query) { - if (!FIELD_BODY.includes(field)) { + if (field !== 'body') { throw new Error(`Invalid response field ${field}`); } @@ -70,13 +65,10 @@ export default class ResponseExtension extends BaseExtension { } matchXPath (bodyStr, query) { - let dom; let results; - try { - dom = new DOMParser().parseFromString(bodyStr); - } catch (err) { - throw new Error(`Invalid XML: ${err.message}`); - } + + // This will never throw + const dom = new DOMParser().parseFromString(bodyStr); try { results = xpath.select(query, dom); diff --git a/app/ui/components/templating/tag-editor.js b/app/ui/components/templating/tag-editor.js index 2d6246861..50f6bc5c9 100644 --- a/app/ui/components/templating/tag-editor.js +++ b/app/ui/components/templating/tag-editor.js @@ -83,7 +83,7 @@ class TagEditor extends PureComponent { const {error, value, preview, tags, selectValue} = this.state; const isFound = !!tags.find(v => value === `{% ${v.name} %}`); const isFlexible = value.indexOf('{% base64') === 0; - const isOther = !isFound || isFlexible; + const isCustom = !isFound && !isFlexible; return (
@@ -91,7 +91,7 @@ class TagEditor extends PureComponent {
- {isOther ? ( + {(!isFound || isFlexible) ? (