Rewrite [dynamicxml] tests, and fix issue with attribute filters (#3298)
This fixes queries with an attribute filter in the middle, such as //book[@id='bk102']/title. Close #3089
This commit is contained in:
125
services/dynamic/dynamic-response-fixtures.js
Normal file
125
services/dynamic/dynamic-response-fixtures.js
Normal file
@@ -0,0 +1,125 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = {
|
||||
exampleXml: `<?xml version="1.0"?>
|
||||
<catalog>
|
||||
<book id="bk101">
|
||||
<author>Gambardella, Matthew</author>
|
||||
<title>XML Developer's Guide</title>
|
||||
<genre>Computer</genre>
|
||||
<price>44.95</price>
|
||||
<publish_date>2000-10-01</publish_date>
|
||||
<description>An in-depth look at creating applications
|
||||
with XML.</description>
|
||||
</book>
|
||||
<book id="bk102">
|
||||
<author>Ralls, Kim</author>
|
||||
<title>Midnight Rain</title>
|
||||
<genre>Fantasy</genre>
|
||||
<price>5.95</price>
|
||||
<publish_date>2000-12-16</publish_date>
|
||||
<description>A former architect battles corporate zombies,
|
||||
an evil sorceress, and her own childhood to become queen
|
||||
of the world.</description>
|
||||
</book>
|
||||
<book id="bk103">
|
||||
<author>Corets, Eva</author>
|
||||
<title>Maeve Ascendant</title>
|
||||
<genre>Fantasy</genre>
|
||||
<price>5.95</price>
|
||||
<publish_date>2000-11-17</publish_date>
|
||||
<description>After the collapse of a nanotechnology
|
||||
society in England, the young survivors lay the
|
||||
foundation for a new society.</description>
|
||||
</book>
|
||||
<book id="bk104">
|
||||
<author>Corets, Eva</author>
|
||||
<title>Oberon's Legacy</title>
|
||||
<genre>Fantasy</genre>
|
||||
<price>5.95</price>
|
||||
<publish_date>2001-03-10</publish_date>
|
||||
<description>In post-apocalypse England, the mysterious
|
||||
agent known only as Oberon helps to create a new life
|
||||
for the inhabitants of London. Sequel to Maeve
|
||||
Ascendant.</description>
|
||||
</book>
|
||||
<book id="bk105">
|
||||
<author>Corets, Eva</author>
|
||||
<title>The Sundered Grail</title>
|
||||
<genre>Fantasy</genre>
|
||||
<price>5.95</price>
|
||||
<publish_date>2001-09-10</publish_date>
|
||||
<description>The two daughters of Maeve, half-sisters,
|
||||
battle one another for control of England. Sequel to
|
||||
Oberon's Legacy.</description>
|
||||
</book>
|
||||
<book id="bk106">
|
||||
<author>Randall, Cynthia</author>
|
||||
<title>Lover Birds</title>
|
||||
<genre>Romance</genre>
|
||||
<price>4.95</price>
|
||||
<publish_date>2000-09-02</publish_date>
|
||||
<description>When Carla meets Paul at an ornithology
|
||||
conference, tempers fly as feathers get ruffled.</description>
|
||||
</book>
|
||||
<book id="bk107">
|
||||
<author>Thurman, Paula</author>
|
||||
<title>Splish Splash</title>
|
||||
<genre>Romance</genre>
|
||||
<price>4.95</price>
|
||||
<publish_date>2000-11-02</publish_date>
|
||||
<description>A deep sea diver finds true love twenty
|
||||
thousand leagues beneath the sea.</description>
|
||||
</book>
|
||||
<book id="bk108">
|
||||
<author>Knorr, Stefan</author>
|
||||
<title>Creepy Crawlies</title>
|
||||
<genre>Horror</genre>
|
||||
<price>4.95</price>
|
||||
<publish_date>2000-12-06</publish_date>
|
||||
<description>An anthology of horror stories about roaches,
|
||||
centipedes, scorpions and other insects.</description>
|
||||
</book>
|
||||
<book id="bk109">
|
||||
<author>Kress, Peter</author>
|
||||
<title>Paradox Lost</title>
|
||||
<genre>Science Fiction</genre>
|
||||
<price>6.95</price>
|
||||
<publish_date>2000-11-02</publish_date>
|
||||
<description>After an inadvertant trip through a Heisenberg
|
||||
Uncertainty Device, James Salway discovers the problems
|
||||
of being quantum.</description>
|
||||
</book>
|
||||
<book id="bk110">
|
||||
<author>O'Brien, Tim</author>
|
||||
<title>Microsoft .NET: The Programming Bible</title>
|
||||
<genre>Computer</genre>
|
||||
<price>36.95</price>
|
||||
<publish_date>2000-12-09</publish_date>
|
||||
<description>Microsoft's .NET initiative is explored in
|
||||
detail in this deep programmer's reference.</description>
|
||||
</book>
|
||||
<book id="bk111">
|
||||
<author>O'Brien, Tim</author>
|
||||
<title>MSXML3: A Comprehensive Guide</title>
|
||||
<genre>Computer</genre>
|
||||
<price>36.95</price>
|
||||
<publish_date>2000-12-01</publish_date>
|
||||
<description>The Microsoft MSXML3 parser is covered in
|
||||
detail, with attention to XML DOM interfaces, XSLT processing,
|
||||
SAX and more.</description>
|
||||
</book>
|
||||
<book id="bk112">
|
||||
<author>Galos, Mike</author>
|
||||
<title>Visual Studio 7: A Comprehensive Guide</title>
|
||||
<genre>Computer</genre>
|
||||
<price>49.95</price>
|
||||
<publish_date>2001-04-16</publish_date>
|
||||
<description>Microsoft Visual Studio 7 is explored in depth,
|
||||
looking at how Visual Basic, Visual C++, C#, and ASP+ are
|
||||
integrated into a comprehensive development
|
||||
environment.</description>
|
||||
</book>
|
||||
</catalog>
|
||||
`,
|
||||
}
|
||||
@@ -28,7 +28,10 @@ module.exports = class DynamicXml extends BaseService {
|
||||
}
|
||||
|
||||
async handle(namedParams, { url, query: pathExpression, prefix, suffix }) {
|
||||
const pathIsAttr = pathExpression.includes('@')
|
||||
// e.g. //book[2]/@id
|
||||
const pathIsAttr = (
|
||||
pathExpression.split('/').slice(-1)[0] || ''
|
||||
).startsWith('@')
|
||||
|
||||
const { buffer } = await this._request({
|
||||
url,
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
'use strict'
|
||||
|
||||
const Joi = require('joi')
|
||||
const { expect } = require('chai')
|
||||
const { isSemver } = require('../test-validators')
|
||||
const queryString = require('query-string')
|
||||
const t = (module.exports = require('../tester').createServiceTester())
|
||||
const { exampleXml } = require('./dynamic-response-fixtures')
|
||||
|
||||
const exampleUrl = 'https://example.test/example.xml'
|
||||
const withExampleXml = nock =>
|
||||
nock('https://example.test')
|
||||
.get('/example.xml')
|
||||
.reply(200, exampleXml)
|
||||
|
||||
t.create('No URL specified')
|
||||
.get('.json?query=//name&label=Package Name')
|
||||
@@ -14,9 +19,7 @@ t.create('No URL specified')
|
||||
})
|
||||
|
||||
t.create('No query specified')
|
||||
.get(
|
||||
'.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&label=Package Name'
|
||||
)
|
||||
.get('.json?url=https://example.test/example.xml&label=Package Name')
|
||||
.expectBadge({
|
||||
label: 'Package Name',
|
||||
message: 'invalid query parameter: query',
|
||||
@@ -25,76 +28,95 @@ t.create('No query specified')
|
||||
|
||||
t.create('XML from url')
|
||||
.get(
|
||||
'.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/addon/name'
|
||||
`.json?${queryString.stringify({
|
||||
url: exampleUrl,
|
||||
query: "//book[@id='bk102']/title",
|
||||
})}`
|
||||
)
|
||||
.intercept(withExampleXml)
|
||||
.expectBadge({
|
||||
label: 'custom badge',
|
||||
message: 'IndieGala Helper',
|
||||
message: 'Midnight Rain',
|
||||
color: 'blue',
|
||||
})
|
||||
|
||||
t.create('XML from uri (support uri query parameter)')
|
||||
t.create('uri query parameter alias')
|
||||
.get(
|
||||
'.json?uri=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/addon/name'
|
||||
`.json?${queryString.stringify({
|
||||
uri: exampleUrl,
|
||||
query: "//book[@id='bk102']/title",
|
||||
})}`
|
||||
)
|
||||
.intercept(withExampleXml)
|
||||
.expectBadge({
|
||||
label: 'custom badge',
|
||||
message: 'IndieGala Helper',
|
||||
message: 'Midnight Rain',
|
||||
color: 'blue',
|
||||
})
|
||||
|
||||
t.create('XML from url (attribute)')
|
||||
t.create('attribute')
|
||||
.get(
|
||||
'.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/addon/reviews/@num'
|
||||
`.json?${queryString.stringify({
|
||||
url: exampleUrl,
|
||||
query: '//book[2]/@id',
|
||||
})}`
|
||||
)
|
||||
.intercept(withExampleXml)
|
||||
.expectBadge({
|
||||
label: 'custom badge',
|
||||
message: Joi.string().regex(/^\d+$/),
|
||||
message: 'bk102',
|
||||
})
|
||||
|
||||
t.create('XML from url | multiple results')
|
||||
t.create('multiple results')
|
||||
.get(
|
||||
'.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/addon/compatible_applications/application/name'
|
||||
`.json?${queryString.stringify({
|
||||
url: exampleUrl,
|
||||
query: '//book/title',
|
||||
})}`
|
||||
)
|
||||
.intercept(withExampleXml)
|
||||
.expectBadge({
|
||||
label: 'custom badge',
|
||||
message: Joi.string().regex(
|
||||
/^Firefox( for Android)?,\sFirefox( for Android)?$/
|
||||
),
|
||||
message:
|
||||
"XML Developer's Guide, Midnight Rain, Maeve Ascendant, Oberon's Legacy, The Sundered Grail, Lover Birds, Splish Splash, Creepy Crawlies, Paradox Lost, Microsoft .NET: The Programming Bible, MSXML3: A Comprehensive Guide, Visual Studio 7: A Comprehensive Guide",
|
||||
})
|
||||
|
||||
t.create('XML from url | caching with new query params')
|
||||
t.create('prefix and suffix')
|
||||
.get(
|
||||
'.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/addon/version'
|
||||
`.json?${queryString.stringify({
|
||||
url: exampleUrl,
|
||||
query: "//book[@id='bk102']/title",
|
||||
prefix: 'title is ',
|
||||
suffix: ', innit',
|
||||
})}`
|
||||
)
|
||||
.intercept(withExampleXml)
|
||||
.expectBadge({
|
||||
label: 'custom badge',
|
||||
message: isSemver,
|
||||
message: 'title is Midnight Rain, innit',
|
||||
})
|
||||
|
||||
t.create('XML from url | with prefix & suffix & label')
|
||||
t.create('query doesnt exist')
|
||||
.get(
|
||||
'.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=//version&prefix=v&suffix= dev&label=IndieGala Helper'
|
||||
)
|
||||
.expectBadge({
|
||||
label: 'IndieGala Helper',
|
||||
message: Joi.string().regex(/^v\d+(\.\d+)?(\.\d+)?\sdev$/),
|
||||
})
|
||||
|
||||
t.create('XML from url | query doesnt exist')
|
||||
.get(
|
||||
'.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/does/not/exist'
|
||||
`.json?${queryString.stringify({
|
||||
url: exampleUrl,
|
||||
query: '//does/not/exist',
|
||||
})}`
|
||||
)
|
||||
.intercept(withExampleXml)
|
||||
.expectBadge({
|
||||
label: 'custom badge',
|
||||
message: 'no result',
|
||||
color: 'lightgrey',
|
||||
})
|
||||
|
||||
t.create('XML from url | query doesnt exist (attribute)')
|
||||
t.create('query doesnt exist (attribute)')
|
||||
.get(
|
||||
'.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/does/not/@exist'
|
||||
`.json?${queryString.stringify({
|
||||
url: exampleUrl,
|
||||
query: '//does/not/@exist',
|
||||
})}`
|
||||
)
|
||||
.intercept(withExampleXml)
|
||||
.expectBadge({
|
||||
label: 'custom badge',
|
||||
message: 'no result',
|
||||
@@ -111,46 +133,18 @@ t.create('XML from url | invalid url')
|
||||
color: 'red',
|
||||
})
|
||||
|
||||
t.create('XML from url | user color overrides default')
|
||||
t.create('request should set Accept header')
|
||||
.get(
|
||||
'.json?url=https://services.addons.mozilla.org/en-US/firefox/api/1.5/addon/707078&query=/addon/name&color=10ADED'
|
||||
`.json?${queryString.stringify({
|
||||
url: exampleUrl,
|
||||
query: "//book[@id='bk102']/title",
|
||||
})}`
|
||||
)
|
||||
.expectBadge({
|
||||
label: 'custom badge',
|
||||
message: 'IndieGala Helper',
|
||||
color: '#10aded',
|
||||
})
|
||||
|
||||
t.create('XML from url | error color overrides default')
|
||||
.get(
|
||||
'.json?url=https://github.com/badges/shields/raw/master/notafile.xml&query=//version'
|
||||
)
|
||||
.expectBadge({
|
||||
label: 'custom badge',
|
||||
message: 'resource not found',
|
||||
color: 'red',
|
||||
})
|
||||
|
||||
t.create('XML from url | error color overrides user specified')
|
||||
.get('.json?query=//version&color=10ADED')
|
||||
.expectBadge({
|
||||
label: 'custom badge',
|
||||
message: 'invalid query parameter: url',
|
||||
color: 'red',
|
||||
})
|
||||
|
||||
let headers
|
||||
t.create('XML from url | request should set Accept header')
|
||||
.get('.json?url=https://xml-test/api.xml&query=/name')
|
||||
.intercept(nock =>
|
||||
nock('https://xml-test')
|
||||
.get('/api.xml')
|
||||
.reply(200, function(uri, requestBody) {
|
||||
headers = this.req.headers
|
||||
return '<?xml version="1.0" encoding="utf-8" ?><name>dynamic xml</name>'
|
||||
})
|
||||
nock('https://example.test', {
|
||||
reqheaders: { accept: 'application/xml, text/xml' },
|
||||
})
|
||||
.get('/example.xml')
|
||||
.reply(200, exampleXml)
|
||||
)
|
||||
.expectBadge({ label: 'custom badge', message: 'dynamic xml' })
|
||||
.after(() => {
|
||||
expect(headers).to.have.property('accept', 'application/xml, text/xml')
|
||||
})
|
||||
.expectBadge({ label: 'custom badge', message: 'Midnight Rain' })
|
||||
|
||||
Reference in New Issue
Block a user