From 65f66642dd0e98189b522ef1b97644e0ed031c19 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Tue, 8 Oct 2019 15:48:43 -0500 Subject: [PATCH] fix type errors in [DynamicXml] service (#4041) * fix: type errors in DynamicXml service * tests: add more tests for DynamicXml * tests: another DynamicXml service test --- services/dynamic/dynamic-xml.service.js | 45 ++++++++++++++++++------- services/dynamic/dynamic-xml.spec.js | 31 +++++++++++++++++ services/dynamic/dynamic-xml.tester.js | 30 +++++++++++++++++ 3 files changed, 94 insertions(+), 12 deletions(-) create mode 100644 services/dynamic/dynamic-xml.spec.js diff --git a/services/dynamic/dynamic-xml.service.js b/services/dynamic/dynamic-xml.service.js index d39ad95a36..94c271fbd2 100644 --- a/services/dynamic/dynamic-xml.service.js +++ b/services/dynamic/dynamic-xml.service.js @@ -27,18 +27,11 @@ module.exports = class DynamicXml extends BaseService { } } - async handle(namedParams, { url, query: pathExpression, prefix, suffix }) { + transform({ pathExpression, buffer }) { // e.g. //book[2]/@id const pathIsAttr = ( pathExpression.split('/').slice(-1)[0] || '' ).startsWith('@') - - const { buffer } = await this._request({ - url, - options: { headers: { Accept: 'application/xml, text/xml' } }, - errorMessages, - }) - const parsed = new DOMParser().parseFromString(buffer) let values @@ -47,14 +40,42 @@ module.exports = class DynamicXml extends BaseService { } catch (e) { throw new InvalidParameter({ prettyMessage: e.message }) } - values = values.map((node, i) => - pathIsAttr ? node.value : node.firstChild.data - ) + + if (!Array.isArray(values)) { + throw new InvalidResponse({ + prettyMessage: 'unsupported query', + }) + } + + values = values.reduce((accum, node) => { + if (pathIsAttr) { + accum.push(node.value) + } else if (node.firstChild) { + accum.push(node.firstChild.data) + } + + return accum + }, []) if (!values.length) { throw new InvalidResponse({ prettyMessage: 'no result' }) } - return renderDynamicBadge({ value: values, prefix, suffix }) + return { values } + } + + async handle(_namedParams, { url, query: pathExpression, prefix, suffix }) { + const { buffer } = await this._request({ + url, + options: { headers: { Accept: 'application/xml, text/xml' } }, + errorMessages, + }) + + const { values: value } = this.transform({ + pathExpression, + buffer, + }) + + return renderDynamicBadge({ value, prefix, suffix }) } } diff --git a/services/dynamic/dynamic-xml.spec.js b/services/dynamic/dynamic-xml.spec.js new file mode 100644 index 0000000000..87a458f4da --- /dev/null +++ b/services/dynamic/dynamic-xml.spec.js @@ -0,0 +1,31 @@ +'use strict' + +const { expect } = require('chai') +const sinon = require('sinon') +const xpath = require('xpath') +const { exampleXml } = require('./dynamic-response-fixtures') +const DynamicXml = require('./dynamic-xml.service') +const { InvalidResponse } = require('..') + +describe('DynamicXml', function() { + describe('transform()', function() { + beforeEach(function() { + sinon.stub(xpath, 'select').returns(undefined) + }) + + afterEach(function() { + sinon.restore() + }) + + it('throws InvalidResponse on unsupported query', function() { + expect(() => + DynamicXml.prototype.transform({ + pathExpression: '//book/title', + buffer: exampleXml, + }) + ) + .to.throw(InvalidResponse) + .with.property('prettyMessage', 'unsupported query') + }) + }) +}) diff --git a/services/dynamic/dynamic-xml.tester.js b/services/dynamic/dynamic-xml.tester.js index d560bff159..166981450b 100644 --- a/services/dynamic/dynamic-xml.tester.js +++ b/services/dynamic/dynamic-xml.tester.js @@ -176,3 +176,33 @@ t.create('request should set Accept header') .reply(200, exampleXml) ) .expectBadge({ label: 'custom badge', message: 'Midnight Rain' }) + +// https://github.com/badges/shields/issues/3814 +t.create('no result') + .get( + `.json?${queryString.stringify({ + url: exampleUrl, + query: '//book[1]/title/text()', + })}` + ) + .intercept(withExampleXml) + .expectBadge({ + label: 'custom badge', + message: 'no result', + color: 'lightgrey', + }) + +// https://github.com/badges/shields/issues/4017 +t.create('unsupported query') + .get( + `.json?${queryString.stringify({ + url: exampleUrl, + query: 'string(//book[1]/title)', + })}` + ) + .intercept(withExampleXml) + .expectBadge({ + label: 'custom badge', + message: 'unsupported query', + color: 'lightgrey', + })