diff --git a/.babelrc b/.babelrc index 3fb471b..550e60a 100644 --- a/.babelrc +++ b/.babelrc @@ -1,7 +1,7 @@ { "presets": ["es2015", "stage-2"], "plugins": ["transform-runtime"], - "ignore": "test/**", + "only": ["scripts/**", "src/**", "test/helpers/**"], "env": { "test": { "plugins": ["istanbul"] diff --git a/package.json b/package.json index 1c91266..d994dd4 100644 --- a/package.json +++ b/package.json @@ -34,8 +34,8 @@ "start:dev": "nodemon --exec babel-node src/index.js", "test": "npm run lint && npm run test:coverage", "test:coverage": "cross-env NODE_ENV=test nyc npm run test:only", - "test:only": "cross-env VCR_MODE=cache ava", - "test:record": "rimraf test/fixtures && npm run test:only -- --serial", + "test:only": "cross-env VCR_MODE=playback ava", + "test:record": "cross-env VCR_MODE=record ava", "test:watch": "npm run test:only -- --watch", "update-schema": "npm run -s print-schema:json > schema.json" }, @@ -64,7 +64,6 @@ "license": "MIT", "dependencies": { "babel-runtime": "^6.18.0", - "chalk": "^1.1.3", "compression": "^1.6.2", "dashify": "^0.2.2", "dataloader": "^1.2.0", diff --git a/scripts/print-schema.js b/scripts/print-schema.js index 53144e7..e98d22c 100644 --- a/scripts/print-schema.js +++ b/scripts/print-schema.js @@ -1,14 +1,12 @@ import { graphql, introspectionQuery, printSchema } from 'graphql' import schema from '../src/schema' -if (require.main === module) { - if (process.argv[2] === '--json') { - graphql(schema, introspectionQuery).then(result => { - console.log(JSON.stringify(result, null, 2)) - }).catch(err => { - console.error(err) - }) - } else { - console.log(printSchema(schema)) - } +if (process.argv[2] === '--json') { + graphql(schema, introspectionQuery).then(result => { + console.log(JSON.stringify(result, null, 2)) + }).catch(err => { + console.error(err) + }) +} else { + console.log(printSchema(schema)) } diff --git a/src/api.js b/src/api.js index b3a2262..52d2bf3 100644 --- a/src/api.js +++ b/src/api.js @@ -1,7 +1,6 @@ import request from 'request' import retry from 'retry' import qs from 'qs' -import chalk from 'chalk' import ExtendableError from 'es6-error' import RateLimit from './rate-limit' import pkg from '../package.json' @@ -164,6 +163,9 @@ export default class MusicBrainz { } getLookupURL (entity, id, params) { + if (id == null) { + return this.getBrowseURL(entity, params) + } return this.getURL(`${entity}/${id}`, params) } @@ -190,19 +192,3 @@ export default class MusicBrainz { return this.get(url) } } - -if (require.main === module) { - const client = new MusicBrainz() - const fn = (id) => { - return client.lookup('artist', id).then(artist => { - console.log(chalk.green(`Done: ${id} ✔ ${artist.name}`)) - }).catch(err => { - console.log(chalk.red(`Error: ${id} ✘ ${err}`)) - }) - } - fn('f1106b17-dcbb-45f6-b938-199ccfab50cc') - fn('a74b1b7f-71a5-4011-9441-d0b5e4122711') - fn('9b5ae4cc-15ae-4f0b-8a4e-8c44e42ba52a') - fn('26f77379-968b-4435-b486-fc9acb4590d3') - fn('8538e728-ca0b-4321-b7e5-cff6565dd4c0') -} diff --git a/src/queries/browse.js b/src/queries/browse.js index 06bb8d5..3110358 100644 --- a/src/queries/browse.js +++ b/src/queries/browse.js @@ -3,7 +3,6 @@ import { forwardConnectionArgs } from 'graphql-relay' import { resolveBrowse } from '../resolvers' import { MBID, - URLString, AreaConnection, ArtistConnection, EventConnection, @@ -12,10 +11,9 @@ import { RecordingConnection, ReleaseConnection, ReleaseGroupConnection, - URLConnection, WorkConnection } from '../types' -import { toWords } from '../types/helpers' +import { toWords, releaseGroupType, releaseStatus } from '../types/helpers' const area = { type: MBID, @@ -115,22 +113,19 @@ entity.`, release, but is not included in the credits for the release itself.` }, recording, - releaseGroup + releaseGroup, + type: releaseGroupType, + status: releaseStatus }), releaseGroups: createBrowseField(ReleaseGroupConnection, { artist, collection, - release + release, + type: releaseGroupType }), works: createBrowseField(WorkConnection, { artist, collection - }), - urls: createBrowseField(URLConnection, { - resource: { - type: URLString, - description: 'The web address for which to browse URL entities.' - } }) } }) diff --git a/src/queries/lookup.js b/src/queries/lookup.js index 07d542b..cf5085e 100644 --- a/src/queries/lookup.js +++ b/src/queries/lookup.js @@ -7,21 +7,23 @@ import { Event, Instrument, Label, + MBID, Place, Recording, Release, ReleaseGroup, Series, URL, + URLString, Work } from '../types' -function createLookupField (entity) { +function createLookupField (entity, args) { const typeName = toWords(entity.name) return { type: entity, description: `Look up a specific ${typeName} by its MBID.`, - args: { mbid }, + args: { mbid, ...args }, resolve: resolveLookup } } @@ -40,7 +42,18 @@ export const LookupQuery = new GraphQLObjectType({ release: createLookupField(Release), releaseGroup: createLookupField(ReleaseGroup), series: createLookupField(Series), - url: createLookupField(URL), + url: createLookupField(URL, { + mbid: { + ...mbid, + // Remove the non-null requirement that is usually on the `mbid` field + // so that URLs can be looked up by `resource`. + type: MBID + }, + resource: { + type: URLString, + description: 'The web address of the URL entity to look up.' + } + }), work: createLookupField(Work) } }) diff --git a/src/rate-limit.js b/src/rate-limit.js index 92c31ac..9f07e41 100644 --- a/src/rate-limit.js +++ b/src/rate-limit.js @@ -17,7 +17,6 @@ export default class RateLimit { this.periodCapacity = this.limit this.timer = null this.pendingFlush = false - this.paused = false this.prevTaskID = null } @@ -27,20 +26,6 @@ export default class RateLimit { return id } - pause () { - clearTimeout(this.timer) - this.paused = true - } - - unpause () { - this.paused = false - this.flush() - } - - clear () { - this.queues.length = 0 - } - enqueue (fn, args, priority = this.defaultPriority) { priority = Math.max(0, priority) return new Promise((resolve, reject) => { @@ -76,9 +61,6 @@ export default class RateLimit { } flush () { - if (this.paused) { - return - } if (this.numPending < this.concurrency && this.periodCapacity > 0) { const task = this.dequeue() if (task) { @@ -118,37 +100,3 @@ export default class RateLimit { } } } - -if (require.main === module) { - const t0 = Date.now() - const logTime = (...args) => { - const t = Date.now() - console.log(`[t=${t - t0}]`, ...args) - } - - const limiter = new RateLimit({ - limit: 3, - period: 3000, - concurrency: 5 - }) - - const fn = (i) => { - return new Promise((resolve) => { - setTimeout(() => { - logTime(`Finished task ${i}`) - resolve(i) - }, 7000) - }) - } - - limiter.enqueue(fn, [1]) - limiter.enqueue(fn, [2]) - limiter.enqueue(fn, [3]) - limiter.enqueue(fn, [4], 2) - limiter.enqueue(fn, [5], 10) - limiter.enqueue(fn, [6]) - limiter.enqueue(fn, [7]) - limiter.enqueue(fn, [8]) - limiter.enqueue(fn, [9]) - limiter.enqueue(fn, [10]) -} diff --git a/src/resolvers.js b/src/resolvers.js index 2c86270..69d72fc 100644 --- a/src/resolvers.js +++ b/src/resolvers.js @@ -63,9 +63,12 @@ export function includeSubqueries (params, info, fragments = info.fragments) { return params } -export function resolveLookup (root, { mbid }, { loaders }, info) { +export function resolveLookup (root, { mbid, ...params }, { loaders }, info) { + if (!mbid && !params.resource) { + throw new Error('Lookups by a field other than MBID must provide: resource') + } const entityType = toDashed(info.fieldName) - let params = includeSubqueries({}, info) + params = includeSubqueries(params, info) params = includeRelationships(params, info) return loaders.lookup.load([entityType, mbid, params]) } diff --git a/src/types/alias.js b/src/types/alias.js index a6abb61..61ade82 100644 --- a/src/types/alias.js +++ b/src/types/alias.js @@ -1,8 +1,8 @@ import { GraphQLObjectType, - GraphQLString, GraphQLBoolean } from 'graphql/type' +import { Locale } from './scalars' import { name, sortName, fieldWithID } from './helpers' export default new GraphQLObjectType({ @@ -17,7 +17,7 @@ entity will be given as a result – even if the actual name wouldn’t be.`, }, sortName, locale: { - type: GraphQLString, + type: Locale, description: `The locale (language and/or country) in which the alias is used.` }, diff --git a/src/types/helpers.js b/src/types/helpers.js index 67d06ae..e242e9f 100644 --- a/src/types/helpers.js +++ b/src/types/helpers.js @@ -202,6 +202,16 @@ export const artistCredit = { resolve: createSubqueryResolver() } +export const releaseGroupType = { + type: new GraphQLList(ReleaseGroupType), + description: 'Filter by one or more release group types.' +} + +export const releaseStatus = { + type: new GraphQLList(ReleaseStatus), + description: 'Filter by one or more release statuses.' +} + export const artists = linkedQuery(ArtistConnection) export const events = linkedQuery(EventConnection) export const labels = linkedQuery(LabelConnection) @@ -209,22 +219,13 @@ export const places = linkedQuery(PlaceConnection) export const recordings = linkedQuery(RecordingConnection) export const releases = linkedQuery(ReleaseConnection, { args: { - type: { - type: new GraphQLList(ReleaseGroupType), - description: 'Filter by one or more release group types.' - }, - status: { - type: new GraphQLList(ReleaseStatus), - description: 'Filter by one or more release statuses.' - } + type: releaseGroupType, + status: releaseStatus } }) export const releaseGroups = linkedQuery(ReleaseGroupConnection, { args: { - type: { - type: new GraphQLList(ReleaseGroupType), - description: 'Filter by one or more release group types.' - } + type: releaseGroupType } }) export const tags = linkedQuery(TagConnection, { diff --git a/src/types/release.js b/src/types/release.js index 011f1db..9e30d5c 100644 --- a/src/types/release.js +++ b/src/types/release.js @@ -1,7 +1,7 @@ import { GraphQLObjectType, GraphQLString, GraphQLList } from 'graphql/type' import Node from './node' import Entity from './entity' -import { DateType } from './scalars' +import { ASIN, DateType } from './scalars' import { ReleaseStatus } from './enums' import ReleaseEvent from './release-event' import { @@ -52,6 +52,11 @@ distribution mechanism.` type: GraphQLString, description: 'The country in which the release was issued.' }, + asin: { + type: ASIN, + description: `The [Amazon Standard Identification Number](https://musicbrainz.org/doc/ASIN) +of the release.` + }, barcode: { type: GraphQLString, description: `The [barcode](https://en.wikipedia.org/wiki/Barcode), if the diff --git a/src/types/scalars.js b/src/types/scalars.js index 0e3b4e2..f77b4a6 100644 --- a/src/types/scalars.js +++ b/src/types/scalars.js @@ -1,7 +1,24 @@ import { Kind } from 'graphql/language' import { GraphQLScalarType } from 'graphql/type' +function createScalar (config) { + return new GraphQLScalarType({ + serialize: value => value, + parseValue: value => value, + parseLiteral (ast) { + if (ast.kind === Kind.STRING) { + return ast.value + } + return null + }, + ...config + }) +} + const uuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/ +const locale = /^([a-z]{2})(_[A-Z]{2})?(\.[A-Z0-9-]+)?$/ +// Be extremely lenient; just prevent major input errors. +const url = /^\w+:\/\/[\w-]+\.\w+/ function validateMBID (value) { if (typeof value === 'string' && uuid.test(value)) { @@ -17,34 +34,38 @@ function validatePositive (value) { throw new TypeError(`Expected positive value: ${value}`) } -export const DateType = new GraphQLScalarType({ +function validateLocale (value) { + if (typeof value === 'string' && locale.test(value)) { + return value + } + throw new TypeError(`Malformed locale: ${value}`) +} + +function validateURL (value) { + if (typeof value === 'string' && url.test(value)) { + return value + } + throw new TypeError(`Malformed URL: ${value}`) +} + +export const ASIN = createScalar({ + name: 'ASIN', + description: `An [Amazon Standard Identification Number](https://musicbrainz.org/doc/ASIN) +(ASIN) is a 10-character alphanumeric unique identifier assigned by Amazon.com +and its partners for product identification within the Amazon organization.` +}) + +export const DateType = createScalar({ name: 'Date', - description: - 'Year, month (optional), and day (optional) in YYYY-MM-DD format.', - serialize: value => value, - parseValue: value => value, - parseLiteral (ast) { - if (ast.kind === Kind.STRING) { - return ast.value - } - return null - } + description: 'Year, month (optional), and day (optional) in YYYY-MM-DD format.' }) -export const Degrees = new GraphQLScalarType({ +export const Degrees = createScalar({ name: 'Degrees', - description: 'Decimal degrees, used for latitude and longitude.', - serialize: value => value, - parseValue: value => value, - parseLiteral (ast) { - if (ast.kind === Kind.STRING) { - return ast.value - } - return null - } + description: 'Decimal degrees, used for latitude and longitude.' }) -export const Duration = new GraphQLScalarType({ +export const Duration = createScalar({ name: 'Duration', description: 'A length of time, in milliseconds.', serialize: validatePositive, @@ -57,91 +78,41 @@ export const Duration = new GraphQLScalarType({ } }) -export const IPI = new GraphQLScalarType({ +export const IPI = createScalar({ name: 'IPI', description: `An [IPI](https://musicbrainz.org/doc/IPI) (interested party information) code is an identifying number assigned by the CISAC database for -musical rights management.`, - serialize: value => value, - parseValue: value => value, - parseLiteral (ast) { - if (ast.kind === Kind.STRING) { - return ast.value - } - return null - } +musical rights management.` }) -export const ISNI = new GraphQLScalarType({ +export const ISNI = createScalar({ name: 'ISNI', description: `The [International Standard Name Identifier](https://musicbrainz.org/doc/ISNI) (ISNI) is an ISO standard for uniquely identifying the public identities of -contributors to media content.`, - serialize: value => value, - parseValue: value => value, - parseLiteral (ast) { - if (ast.kind === Kind.STRING) { - return ast.value - } - return null - } +contributors to media content.` }) -export const ISWC = new GraphQLScalarType({ +export const ISWC = createScalar({ name: 'ISWC', description: `The [International Standard Musical Work Code](https://musicbrainz.org/doc/ISWC) (ISWC) is an ISO standard similar to ISBNs for identifying musical works / -compositions.`, - serialize: value => value, - parseValue: value => value, - parseLiteral (ast) { - if (ast.kind === Kind.STRING) { - return ast.value - } - return null - } +compositions.` }) -export const Locale = new GraphQLScalarType({ +export const Locale = createScalar({ name: 'Locale', description: 'Language code, optionally with country and encoding.', - serialize: value => value, - parseValue: value => value, + serialize: validateLocale, + parseValue: validateLocale, parseLiteral (ast) { if (ast.kind === Kind.STRING) { - return ast.value + return validateLocale(ast.value) } return null } }) -export const Time = new GraphQLScalarType({ - name: 'Time', - description: 'A time of day, in 24-hour hh:mm notation.', - serialize: value => value, - parseValue: value => value, - parseLiteral (ast) { - if (ast.kind === Kind.STRING) { - return ast.value - } - return null - } -}) - -export const URLString = new GraphQLScalarType({ - name: 'URLString', - description: 'A web address.', - serialize: value => value, - parseValue: value => value, - parseLiteral (ast) { - if (ast.kind === Kind.STRING) { - return ast.value - } - return null - } -}) - -export const MBID = new GraphQLScalarType({ +export const MBID = createScalar({ name: 'MBID', description: `The MBID scalar represents MusicBrainz identifiers, which are 36-character UUIDs.`, @@ -154,3 +125,21 @@ export const MBID = new GraphQLScalarType({ return null } }) + +export const Time = createScalar({ + name: 'Time', + description: 'A time of day, in 24-hour hh:mm notation.' +}) + +export const URLString = createScalar({ + name: 'URLString', + description: 'A web address.', + serialize: validateURL, + parseValue: validateURL, + parseLiteral (ast) { + if (ast.kind === Kind.STRING) { + return validateURL(ast.value) + } + return null + } +}) diff --git a/test/api.js b/test/api.js index ac646cf..4917257 100644 --- a/test/api.js +++ b/test/api.js @@ -1,15 +1,6 @@ -import path from 'path' import test from 'ava' -import sepia from 'sepia' -import MusicBrainz, { MusicBrainzError } from '../src/api' - -sepia.fixtureDir(path.join(__dirname, 'fixtures')) - -let client - -test.before(t => { - client = new MusicBrainz() -}) +import { MusicBrainzError } from '../src/api' +import client from './helpers/client' test('getLookupURL() generates a lookup URL', t => { t.is(client.getLookupURL('artist', 'c8da2e40-bd28-4d4e-813a-bd2f51958ba8', { @@ -37,9 +28,8 @@ test('lookup() sends a lookup query', t => { }) test('rejects the promise when the API returns an error', t => { - t.throws( - client.lookup('artist', '5b11f4ce-a62d-471e-81fc-a69a8278c7da', { - inc: ['foobar'] - }), MusicBrainzError - ) + const req = client.lookup('artist', '5b11f4ce-a62d-471e-81fc-a69a8278c7da', { + inc: ['foobar'] + }) + return t.throws(req, MusicBrainzError) }) diff --git a/test/fixtures/05fcd912e8786fff4dca854a7fa44c81.headers b/test/fixtures/05fcd912e8786fff4dca854a7fa44c81.headers index 666a732..0b5601e 100644 --- a/test/fixtures/05fcd912e8786fff4dca854a7fa44c81.headers +++ b/test/fixtures/05fcd912e8786fff4dca854a7fa44c81.headers @@ -1,26 +1,26 @@ { "statusCode": 200, "headers": { - "date": "Thu, 08 Dec 2016 22:32:00 GMT", + "date": "Fri, 09 Dec 2016 21:53:05 GMT", "content-type": "application/json; charset=UTF-8", "transfer-encoding": "chunked", "connection": "keep-alive", "keep-alive": "timeout=15", "vary": "Accept-Encoding", "x-ratelimit-limit": "700", - "x-ratelimit-remaining": "303", - "x-ratelimit-reset": "1481236321", + "x-ratelimit-remaining": "365", + "x-ratelimit-reset": "1481320386", "last-modified": "Wed, 09 Nov 2016 23:43:24 GMT", "server": "Jetty(9.3.10.v20160621)", "access-control-allow-origin": "*", "content-encoding": "gzip" }, "url": "http://musicbrainz.org:80/ws/2/recording?query=Burn%20the%20Witch&fmt=json", - "time": 596, + "time": 508, "request": { "method": "GET", "headers": { - "User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", "host": "musicbrainz.org", "accept-encoding": "gzip, deflate", "accept": "application/json" diff --git a/test/fixtures/096e5b32efb65749a3f9ccaba145c6d9 b/test/fixtures/096e5b32efb65749a3f9ccaba145c6d9 new file mode 100644 index 0000000..a681859 Binary files /dev/null and b/test/fixtures/096e5b32efb65749a3f9ccaba145c6d9 differ diff --git a/test/fixtures/096e5b32efb65749a3f9ccaba145c6d9.headers b/test/fixtures/096e5b32efb65749a3f9ccaba145c6d9.headers new file mode 100644 index 0000000..88a10b4 --- /dev/null +++ b/test/fixtures/096e5b32efb65749a3f9ccaba145c6d9.headers @@ -0,0 +1,29 @@ +{ + "statusCode": 200, + "headers": { + "date": "Sat, 10 Dec 2016 02:52:35 GMT", + "content-type": "application/json; charset=utf-8", + "transfer-encoding": "chunked", + "connection": "keep-alive", + "keep-alive": "timeout=15", + "vary": "Accept-Encoding", + "x-ratelimit-limit": "700", + "x-ratelimit-remaining": "352", + "x-ratelimit-reset": "1481338356", + "server": "Plack::Handler::Starlet", + "etag": "W/\"6e4fd0ce8e71cdb68d2f23d878327605\"", + "access-control-allow-origin": "*", + "content-encoding": "gzip" + }, + "url": "http://musicbrainz.org:80/ws/2/release/d5cdb7fd-c7e9-460a-9549-8a369655cc52?fmt=json", + "time": 486, + "request": { + "method": "GET", + "headers": { + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", + "host": "musicbrainz.org", + "accept-encoding": "gzip, deflate", + "accept": "application/json" + } + } +} \ No newline at end of file diff --git a/test/fixtures/157ce6484de07a7e2ee93b54e8244e27 b/test/fixtures/157ce6484de07a7e2ee93b54e8244e27 index a5e5de0..9e1df2d 100644 Binary files a/test/fixtures/157ce6484de07a7e2ee93b54e8244e27 and b/test/fixtures/157ce6484de07a7e2ee93b54e8244e27 differ diff --git a/test/fixtures/157ce6484de07a7e2ee93b54e8244e27.headers b/test/fixtures/157ce6484de07a7e2ee93b54e8244e27.headers index 57781b2..b807e4e 100644 --- a/test/fixtures/157ce6484de07a7e2ee93b54e8244e27.headers +++ b/test/fixtures/157ce6484de07a7e2ee93b54e8244e27.headers @@ -1,26 +1,26 @@ { "statusCode": 200, "headers": { - "date": "Thu, 08 Dec 2016 22:32:02 GMT", + "date": "Fri, 09 Dec 2016 21:53:05 GMT", "content-type": "application/json; charset=UTF-8", "transfer-encoding": "chunked", "connection": "keep-alive", "keep-alive": "timeout=15", "vary": "Accept-Encoding", "x-ratelimit-limit": "700", - "x-ratelimit-remaining": "334", - "x-ratelimit-reset": "1481236323", - "last-modified": "Thu, 08 Dec 2016 22:03:30 GMT", + "x-ratelimit-remaining": "363", + "x-ratelimit-reset": "1481320386", + "last-modified": "Fri, 09 Dec 2016 21:37:57 GMT", "server": "Jetty(9.3.10.v20160621)", "access-control-allow-origin": "*", "content-encoding": "gzip" }, "url": "http://musicbrainz.org:80/ws/2/label?limit=1&query=Apple%20Records&fmt=json", - "time": 1539, + "time": 582, "request": { "method": "GET", "headers": { - "User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", "host": "musicbrainz.org", "accept-encoding": "gzip, deflate", "accept": "application/json" diff --git a/test/fixtures/215ca91efacd4b7a1e7800813c8382e0.headers b/test/fixtures/215ca91efacd4b7a1e7800813c8382e0.headers index 87bdaa8..1b8baac 100644 --- a/test/fixtures/215ca91efacd4b7a1e7800813c8382e0.headers +++ b/test/fixtures/215ca91efacd4b7a1e7800813c8382e0.headers @@ -1,20 +1,20 @@ { "statusCode": 400, "headers": { - "date": "Fri, 09 Dec 2016 00:06:41 GMT", + "date": "Fri, 09 Dec 2016 21:53:05 GMT", "content-type": "application/json; charset=utf-8", "content-length": "72", "connection": "keep-alive", "keep-alive": "timeout=15", "x-ratelimit-limit": "700", - "x-ratelimit-remaining": "575", - "x-ratelimit-reset": "1481242002", + "x-ratelimit-remaining": "429", + "x-ratelimit-reset": "1481320386", "server": "Plack::Handler::Starlet", "etag": "\"d54d2bc5c412c1bb3c02bfc91d13a900\"", "access-control-allow-origin": "*" }, "url": "http://musicbrainz.org:80/ws/2/artist/5b11f4ce-a62d-471e-81fc-a69a8278c7da?inc=foobar&fmt=json", - "time": 613, + "time": 396, "request": { "method": "GET", "headers": { diff --git a/test/fixtures/3a7c3d2d0ac8cb3923c301ccbe320fd9 b/test/fixtures/3a7c3d2d0ac8cb3923c301ccbe320fd9 new file mode 100644 index 0000000..3686119 --- /dev/null +++ b/test/fixtures/3a7c3d2d0ac8cb3923c301ccbe320fd9 @@ -0,0 +1 @@ +{"resource":"http://www.nirvana.com/","id":"4347ffe2-82ec-4059-9520-6a1a3f73a304"} \ No newline at end of file diff --git a/test/fixtures/3a7c3d2d0ac8cb3923c301ccbe320fd9.headers b/test/fixtures/3a7c3d2d0ac8cb3923c301ccbe320fd9.headers new file mode 100644 index 0000000..92a3472 --- /dev/null +++ b/test/fixtures/3a7c3d2d0ac8cb3923c301ccbe320fd9.headers @@ -0,0 +1,27 @@ +{ + "statusCode": 200, + "headers": { + "date": "Sat, 10 Dec 2016 00:43:25 GMT", + "content-type": "application/json; charset=utf-8", + "content-length": "82", + "connection": "keep-alive", + "keep-alive": "timeout=15", + "x-ratelimit-limit": "700", + "x-ratelimit-remaining": "542", + "x-ratelimit-reset": "1481330606", + "server": "Plack::Handler::Starlet", + "etag": "\"d2b2ef09f302f15cd08587ad1e02d9ef\"", + "access-control-allow-origin": "*" + }, + "url": "http://musicbrainz.org:80/ws/2/url?resource=http%3A%2F%2Fwww.nirvana.com%2F&fmt=json", + "time": 486, + "request": { + "method": "GET", + "headers": { + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", + "host": "musicbrainz.org", + "accept-encoding": "gzip, deflate", + "accept": "application/json" + } + } +} \ No newline at end of file diff --git a/test/fixtures/3d3398816ac3ccbffdd2c4893406f982 b/test/fixtures/3d3398816ac3ccbffdd2c4893406f982 new file mode 100644 index 0000000..7af28d6 Binary files /dev/null and b/test/fixtures/3d3398816ac3ccbffdd2c4893406f982 differ diff --git a/test/fixtures/3d3398816ac3ccbffdd2c4893406f982.headers b/test/fixtures/3d3398816ac3ccbffdd2c4893406f982.headers new file mode 100644 index 0000000..211d193 --- /dev/null +++ b/test/fixtures/3d3398816ac3ccbffdd2c4893406f982.headers @@ -0,0 +1,29 @@ +{ + "statusCode": 200, + "headers": { + "date": "Sat, 10 Dec 2016 02:31:10 GMT", + "content-type": "application/json; charset=utf-8", + "transfer-encoding": "chunked", + "connection": "keep-alive", + "keep-alive": "timeout=15", + "vary": "Accept-Encoding", + "x-ratelimit-limit": "700", + "x-ratelimit-remaining": "381", + "x-ratelimit-reset": "1481337071", + "server": "Plack::Handler::Starlet", + "etag": "W/\"76d4b01f2f2f2713907e9d82646b801a\"", + "access-control-allow-origin": "*", + "content-encoding": "gzip" + }, + "url": "http://musicbrainz.org:80/ws/2/release?artist=5b11f4ce-a62d-471e-81fc-a69a8278c7da&type=ep&status=bootleg&fmt=json", + "time": 590, + "request": { + "method": "GET", + "headers": { + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", + "host": "musicbrainz.org", + "accept-encoding": "gzip, deflate", + "accept": "application/json" + } + } +} \ No newline at end of file diff --git a/test/fixtures/456168a862ec0ca28127f067e3f166e7 b/test/fixtures/456168a862ec0ca28127f067e3f166e7 index 6bde522..52102fc 100644 Binary files a/test/fixtures/456168a862ec0ca28127f067e3f166e7 and b/test/fixtures/456168a862ec0ca28127f067e3f166e7 differ diff --git a/test/fixtures/456168a862ec0ca28127f067e3f166e7.headers b/test/fixtures/456168a862ec0ca28127f067e3f166e7.headers index 50171de..eaef6b6 100644 --- a/test/fixtures/456168a862ec0ca28127f067e3f166e7.headers +++ b/test/fixtures/456168a862ec0ca28127f067e3f166e7.headers @@ -1,26 +1,26 @@ { "statusCode": 200, "headers": { - "date": "Thu, 08 Dec 2016 22:31:58 GMT", + "date": "Fri, 09 Dec 2016 21:53:05 GMT", "content-type": "application/json; charset=utf-8", "transfer-encoding": "chunked", "connection": "keep-alive", "keep-alive": "timeout=15", "vary": "Accept-Encoding", "x-ratelimit-limit": "700", - "x-ratelimit-remaining": "180", - "x-ratelimit-reset": "1481236319", + "x-ratelimit-remaining": "368", + "x-ratelimit-reset": "1481320386", "server": "Plack::Handler::Starlet", - "etag": "W/\"15092bd7b55df20c4f8fd072b82a0f1f\"", + "etag": "W/\"05d3a423b0b8ea0f99c184f8131c7cac\"", "access-control-allow-origin": "*", "content-encoding": "gzip" }, "url": "http://musicbrainz.org:80/ws/2/artist/c8da2e40-bd28-4d4e-813a-bd2f51958ba8?fmt=json", - "time": 426, + "time": 419, "request": { "method": "GET", "headers": { - "User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", "host": "musicbrainz.org", "accept-encoding": "gzip, deflate", "accept": "application/json" diff --git a/test/fixtures/49a2bac852ad6aca096d15a60f5ad23a b/test/fixtures/49a2bac852ad6aca096d15a60f5ad23a new file mode 100644 index 0000000..823b1df Binary files /dev/null and b/test/fixtures/49a2bac852ad6aca096d15a60f5ad23a differ diff --git a/test/fixtures/49a2bac852ad6aca096d15a60f5ad23a.headers b/test/fixtures/49a2bac852ad6aca096d15a60f5ad23a.headers new file mode 100644 index 0000000..e71c57b --- /dev/null +++ b/test/fixtures/49a2bac852ad6aca096d15a60f5ad23a.headers @@ -0,0 +1,29 @@ +{ + "statusCode": 200, + "headers": { + "date": "Fri, 09 Dec 2016 21:53:05 GMT", + "content-type": "application/json; charset=utf-8", + "transfer-encoding": "chunked", + "connection": "keep-alive", + "keep-alive": "timeout=15", + "vary": "Accept-Encoding", + "x-ratelimit-limit": "700", + "x-ratelimit-remaining": "369", + "x-ratelimit-reset": "1481320386", + "server": "Plack::Handler::Starlet", + "etag": "W/\"617be9e745c8ab9b5097353b14655232\"", + "access-control-allow-origin": "*", + "content-encoding": "gzip" + }, + "url": "http://musicbrainz.org:80/ws/2/artist/65314b12-0e08-43fa-ba33-baaa7b874c15?fmt=json", + "time": 416, + "request": { + "method": "GET", + "headers": { + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", + "host": "musicbrainz.org", + "accept-encoding": "gzip, deflate", + "accept": "application/json" + } + } +} \ No newline at end of file diff --git a/test/fixtures/4b2d503f6b8f97b06e3ec6a3341f6904 b/test/fixtures/4b2d503f6b8f97b06e3ec6a3341f6904 new file mode 100644 index 0000000..076d79f Binary files /dev/null and b/test/fixtures/4b2d503f6b8f97b06e3ec6a3341f6904 differ diff --git a/test/fixtures/4b2d503f6b8f97b06e3ec6a3341f6904.headers b/test/fixtures/4b2d503f6b8f97b06e3ec6a3341f6904.headers new file mode 100644 index 0000000..41eec5f --- /dev/null +++ b/test/fixtures/4b2d503f6b8f97b06e3ec6a3341f6904.headers @@ -0,0 +1,29 @@ +{ + "statusCode": 200, + "headers": { + "date": "Fri, 09 Dec 2016 23:32:25 GMT", + "content-type": "application/json; charset=utf-8", + "transfer-encoding": "chunked", + "connection": "keep-alive", + "keep-alive": "timeout=15", + "vary": "Accept-Encoding", + "x-ratelimit-limit": "700", + "x-ratelimit-remaining": "352", + "x-ratelimit-reset": "1481326345", + "server": "Plack::Handler::Starlet", + "etag": "W/\"cd4a6370a1597ab7cb7ed51617049d2f\"", + "access-control-allow-origin": "*", + "content-encoding": "gzip" + }, + "url": "http://musicbrainz.org:80/ws/2/area/489ce91b-6658-3307-9877-795b68554c98?fmt=json", + "time": 416, + "request": { + "method": "GET", + "headers": { + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", + "host": "musicbrainz.org", + "accept-encoding": "gzip, deflate", + "accept": "application/json" + } + } +} \ No newline at end of file diff --git a/test/fixtures/6044ddc15443664659ef91c3c73c0776 b/test/fixtures/6044ddc15443664659ef91c3c73c0776 index 48eca17..c776412 100644 Binary files a/test/fixtures/6044ddc15443664659ef91c3c73c0776 and b/test/fixtures/6044ddc15443664659ef91c3c73c0776 differ diff --git a/test/fixtures/6044ddc15443664659ef91c3c73c0776.headers b/test/fixtures/6044ddc15443664659ef91c3c73c0776.headers index 8d177cd..e431efe 100644 --- a/test/fixtures/6044ddc15443664659ef91c3c73c0776.headers +++ b/test/fixtures/6044ddc15443664659ef91c3c73c0776.headers @@ -1,26 +1,26 @@ { "statusCode": 200, "headers": { - "date": "Thu, 08 Dec 2016 22:32:06 GMT", + "date": "Fri, 09 Dec 2016 21:53:18 GMT", "content-type": "application/json; charset=utf-8", "transfer-encoding": "chunked", "connection": "keep-alive", "keep-alive": "timeout=15", "vary": "Accept-Encoding", "x-ratelimit-limit": "700", - "x-ratelimit-remaining": "289", - "x-ratelimit-reset": "1481236327", + "x-ratelimit-remaining": "225", + "x-ratelimit-reset": "1481320398", "server": "Plack::Handler::Starlet", - "etag": "W/\"6a12c1ded7c7c8d9315107669601ed70\"", + "etag": "W/\"5626413881801f644e96284425f962ef\"", "access-control-allow-origin": "*", "content-encoding": "gzip" }, "url": "http://musicbrainz.org:80/ws/2/artist/300c4c73-33ac-4255-9d57-4e32627f5e13?inc=artist-rels&fmt=json", - "time": 556, + "time": 496, "request": { "method": "GET", "headers": { - "User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", "host": "musicbrainz.org", "accept-encoding": "gzip, deflate", "accept": "application/json" diff --git a/test/fixtures/69d9c8738fe3ea4883276fd8fc9979ce b/test/fixtures/69d9c8738fe3ea4883276fd8fc9979ce index 71a1ef1..32d0ddc 100644 Binary files a/test/fixtures/69d9c8738fe3ea4883276fd8fc9979ce and b/test/fixtures/69d9c8738fe3ea4883276fd8fc9979ce differ diff --git a/test/fixtures/69d9c8738fe3ea4883276fd8fc9979ce.headers b/test/fixtures/69d9c8738fe3ea4883276fd8fc9979ce.headers index 2b3032a..e70da24 100644 --- a/test/fixtures/69d9c8738fe3ea4883276fd8fc9979ce.headers +++ b/test/fixtures/69d9c8738fe3ea4883276fd8fc9979ce.headers @@ -1,26 +1,26 @@ { "statusCode": 200, "headers": { - "date": "Thu, 08 Dec 2016 22:32:06 GMT", + "date": "Fri, 09 Dec 2016 21:53:18 GMT", "content-type": "application/json; charset=utf-8", "transfer-encoding": "chunked", "connection": "keep-alive", "keep-alive": "timeout=15", "vary": "Accept-Encoding", "x-ratelimit-limit": "700", - "x-ratelimit-remaining": "287", - "x-ratelimit-reset": "1481236327", + "x-ratelimit-remaining": "228", + "x-ratelimit-reset": "1481320398", "server": "Plack::Handler::Starlet", - "etag": "W/\"cfec247269cfa3680afeab36d412221c\"", + "etag": "W/\"079599c4dc85b7d5376d1ff936519512\"", "access-control-allow-origin": "*", "content-encoding": "gzip" }, "url": "http://musicbrainz.org:80/ws/2/artist/0d4ab0f9-bbda-4ab1-ae2c-f772ffcfbea9?inc=artist-rels&fmt=json", - "time": 517, + "time": 430, "request": { "method": "GET", "headers": { - "User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", "host": "musicbrainz.org", "accept-encoding": "gzip, deflate", "accept": "application/json" diff --git a/test/fixtures/7aa73613ca81c364adb26ad95bebe930 b/test/fixtures/7aa73613ca81c364adb26ad95bebe930 new file mode 100644 index 0000000..87eac50 Binary files /dev/null and b/test/fixtures/7aa73613ca81c364adb26ad95bebe930 differ diff --git a/test/fixtures/7aa73613ca81c364adb26ad95bebe930.headers b/test/fixtures/7aa73613ca81c364adb26ad95bebe930.headers new file mode 100644 index 0000000..659b50f --- /dev/null +++ b/test/fixtures/7aa73613ca81c364adb26ad95bebe930.headers @@ -0,0 +1,29 @@ +{ + "statusCode": 200, + "headers": { + "date": "Fri, 09 Dec 2016 23:50:40 GMT", + "content-type": "application/json; charset=utf-8", + "transfer-encoding": "chunked", + "connection": "keep-alive", + "keep-alive": "timeout=15", + "vary": "Accept-Encoding", + "x-ratelimit-limit": "700", + "x-ratelimit-remaining": "543", + "x-ratelimit-reset": "1481327442", + "server": "Plack::Handler::Starlet", + "etag": "W/\"80d5da0c3f297592e23e0bc3f0beea82\"", + "access-control-allow-origin": "*", + "content-encoding": "gzip" + }, + "url": "http://musicbrainz.org:80/ws/2/artist/f99b7d67-4e63-4678-aa66-4c6ac0f7d24a?inc=aliases&fmt=json", + "time": 539, + "request": { + "method": "GET", + "headers": { + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", + "host": "musicbrainz.org", + "accept-encoding": "gzip, deflate", + "accept": "application/json" + } + } +} \ No newline at end of file diff --git a/test/fixtures/87438b239df73ddc020aee9ec9d84905 b/test/fixtures/87438b239df73ddc020aee9ec9d84905 index 6c2f78a..ddc397e 100644 --- a/test/fixtures/87438b239df73ddc020aee9ec9d84905 +++ b/test/fixtures/87438b239df73ddc020aee9ec9d84905 @@ -1 +1 @@ -{"primary-type":"Album","disambiguation":"","title":"Lures","secondary-types":[],"id":"e37d2740-4503-4e3f-ab6d-e622a25e964d","secondary-type-ids":[],"first-release-date":"2014-10-07","primary-type-id":"f529b476-6e62-324f-b0aa-1f3e33d313fc"} \ No newline at end of file +{"primary-type":"Album","primary-type-id":"f529b476-6e62-324f-b0aa-1f3e33d313fc","title":"Lures","first-release-date":"2014-10-07","secondary-type-ids":[],"disambiguation":"","id":"e37d2740-4503-4e3f-ab6d-e622a25e964d","secondary-types":[]} \ No newline at end of file diff --git a/test/fixtures/87438b239df73ddc020aee9ec9d84905.headers b/test/fixtures/87438b239df73ddc020aee9ec9d84905.headers index 06f9551..65bdb40 100644 --- a/test/fixtures/87438b239df73ddc020aee9ec9d84905.headers +++ b/test/fixtures/87438b239df73ddc020aee9ec9d84905.headers @@ -1,24 +1,24 @@ { "statusCode": 200, "headers": { - "date": "Thu, 08 Dec 2016 22:32:00 GMT", + "date": "Fri, 09 Dec 2016 21:53:05 GMT", "content-type": "application/json; charset=utf-8", "content-length": "240", "connection": "keep-alive", "keep-alive": "timeout=15", "x-ratelimit-limit": "700", - "x-ratelimit-remaining": "504", - "x-ratelimit-reset": "1481236321", + "x-ratelimit-remaining": "372", + "x-ratelimit-reset": "1481320386", "server": "Plack::Handler::Starlet", - "etag": "\"89bacb0f43473ab326be8f6ba1f42afd\"", + "etag": "\"3dba57e694e0ee8ca9730d90a1601bfb\"", "access-control-allow-origin": "*" }, "url": "http://musicbrainz.org:80/ws/2/release-group/e37d2740-4503-4e3f-ab6d-e622a25e964d?fmt=json", - "time": 588, + "time": 424, "request": { "method": "GET", "headers": { - "User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", "host": "musicbrainz.org", "accept-encoding": "gzip, deflate", "accept": "application/json" diff --git a/test/fixtures/876353ef38c82797eaed49c94c919179 b/test/fixtures/876353ef38c82797eaed49c94c919179 new file mode 100644 index 0000000..50f5d6d --- /dev/null +++ b/test/fixtures/876353ef38c82797eaed49c94c919179 @@ -0,0 +1 @@ +{"id":"ef7d0814-da6a-32f5-a600-ff81cffd1aed","language":"mul","type":"Song","title":"Song of the French Partisan","attributes":[],"disambiguation":"","iswcs":["T-900.755.682-3"],"type-id":"f061270a-2fd6-32f1-a641-f0f8676d14e6"} \ No newline at end of file diff --git a/test/fixtures/876353ef38c82797eaed49c94c919179.headers b/test/fixtures/876353ef38c82797eaed49c94c919179.headers new file mode 100644 index 0000000..62a5943 --- /dev/null +++ b/test/fixtures/876353ef38c82797eaed49c94c919179.headers @@ -0,0 +1,27 @@ +{ + "statusCode": 200, + "headers": { + "date": "Fri, 09 Dec 2016 23:59:46 GMT", + "content-type": "application/json; charset=utf-8", + "content-length": "227", + "connection": "keep-alive", + "keep-alive": "timeout=15", + "x-ratelimit-limit": "700", + "x-ratelimit-remaining": "399", + "x-ratelimit-reset": "1481327987", + "server": "Plack::Handler::Starlet", + "etag": "\"8cfcefbad616638c208f7d6f28321cac\"", + "access-control-allow-origin": "*" + }, + "url": "http://musicbrainz.org:80/ws/2/work/ef7d0814-da6a-32f5-a600-ff81cffd1aed?fmt=json", + "time": 416, + "request": { + "method": "GET", + "headers": { + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", + "host": "musicbrainz.org", + "accept-encoding": "gzip, deflate", + "accept": "application/json" + } + } +} \ No newline at end of file diff --git a/test/fixtures/914da6a513e527c9351bffbc8879dfc2 b/test/fixtures/914da6a513e527c9351bffbc8879dfc2 new file mode 100644 index 0000000..53cbaaf Binary files /dev/null and b/test/fixtures/914da6a513e527c9351bffbc8879dfc2 differ diff --git a/test/fixtures/914da6a513e527c9351bffbc8879dfc2.headers b/test/fixtures/914da6a513e527c9351bffbc8879dfc2.headers new file mode 100644 index 0000000..237dca6 --- /dev/null +++ b/test/fixtures/914da6a513e527c9351bffbc8879dfc2.headers @@ -0,0 +1,29 @@ +{ + "statusCode": 200, + "headers": { + "date": "Fri, 09 Dec 2016 21:53:11 GMT", + "content-type": "application/json; charset=UTF-8", + "transfer-encoding": "chunked", + "connection": "keep-alive", + "keep-alive": "timeout=15", + "vary": "Accept-Encoding", + "x-ratelimit-limit": "700", + "x-ratelimit-remaining": "560", + "x-ratelimit-reset": "1481320392", + "last-modified": "Fri, 09 Dec 2016 21:01:38 GMT", + "server": "Jetty(9.3.10.v20160621)", + "access-control-allow-origin": "*", + "content-encoding": "gzip" + }, + "url": "http://musicbrainz.org:80/ws/2/artist?limit=1&query=Leonard%20Cohen&fmt=json", + "time": 419, + "request": { + "method": "GET", + "headers": { + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", + "host": "musicbrainz.org", + "accept-encoding": "gzip, deflate", + "accept": "application/json" + } + } +} \ No newline at end of file diff --git a/test/fixtures/9247bb00fc5e2e0dcf1fcd269df8b94e b/test/fixtures/9247bb00fc5e2e0dcf1fcd269df8b94e index 8a3c6f9..83131c6 100644 Binary files a/test/fixtures/9247bb00fc5e2e0dcf1fcd269df8b94e and b/test/fixtures/9247bb00fc5e2e0dcf1fcd269df8b94e differ diff --git a/test/fixtures/9247bb00fc5e2e0dcf1fcd269df8b94e.headers b/test/fixtures/9247bb00fc5e2e0dcf1fcd269df8b94e.headers index c1f62d0..6bc67d8 100644 --- a/test/fixtures/9247bb00fc5e2e0dcf1fcd269df8b94e.headers +++ b/test/fixtures/9247bb00fc5e2e0dcf1fcd269df8b94e.headers @@ -1,26 +1,26 @@ { "statusCode": 200, "headers": { - "date": "Thu, 08 Dec 2016 22:32:05 GMT", + "date": "Fri, 09 Dec 2016 21:53:16 GMT", "content-type": "application/json; charset=utf-8", "transfer-encoding": "chunked", "connection": "keep-alive", "keep-alive": "timeout=15", "vary": "Accept-Encoding", "x-ratelimit-limit": "700", - "x-ratelimit-remaining": "697", - "x-ratelimit-reset": "1481236327", + "x-ratelimit-remaining": "104", + "x-ratelimit-reset": "1481320396", "server": "Plack::Handler::Starlet", - "etag": "W/\"9020613941ca4d7631fab0e7d51d077f\"", + "etag": "W/\"17516f4a3648cd4259751af5341b0d1b\"", "access-control-allow-origin": "*", "content-encoding": "gzip" }, "url": "http://musicbrainz.org:80/ws/2/release?label=cf7fc5cf-e011-4ef4-b511-cd0188537910&limit=1&fmt=json", - "time": 390, + "time": 420, "request": { "method": "GET", "headers": { - "User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", "host": "musicbrainz.org", "accept-encoding": "gzip, deflate", "accept": "application/json" diff --git a/test/fixtures/97ec62634d0a8953ab3ba2ffce984a83 b/test/fixtures/97ec62634d0a8953ab3ba2ffce984a83 index edbc263..4c8fb88 100644 Binary files a/test/fixtures/97ec62634d0a8953ab3ba2ffce984a83 and b/test/fixtures/97ec62634d0a8953ab3ba2ffce984a83 differ diff --git a/test/fixtures/97ec62634d0a8953ab3ba2ffce984a83.headers b/test/fixtures/97ec62634d0a8953ab3ba2ffce984a83.headers index cfa792b..af1865f 100644 --- a/test/fixtures/97ec62634d0a8953ab3ba2ffce984a83.headers +++ b/test/fixtures/97ec62634d0a8953ab3ba2ffce984a83.headers @@ -1,26 +1,26 @@ { "statusCode": 200, "headers": { - "date": "Thu, 08 Dec 2016 22:32:11 GMT", + "date": "Fri, 09 Dec 2016 21:53:22 GMT", "content-type": "application/json; charset=utf-8", "transfer-encoding": "chunked", "connection": "keep-alive", "keep-alive": "timeout=15", "vary": "Accept-Encoding", "x-ratelimit-limit": "700", - "x-ratelimit-remaining": "254", - "x-ratelimit-reset": "1481236331", + "x-ratelimit-remaining": "260", + "x-ratelimit-reset": "1481320402", "server": "Plack::Handler::Starlet", - "etag": "W/\"285b663debaf6f383194dcb82b6655e1\"", + "etag": "W/\"a2a6b542d767ee02cb3e2a0ec5f79525\"", "access-control-allow-origin": "*", "content-encoding": "gzip" }, "url": "http://musicbrainz.org:80/ws/2/artist/ba550d0e-adac-4864-b88b-407cab5e76af?inc=artist-rels&fmt=json", - "time": 677, + "time": 548, "request": { "method": "GET", "headers": { - "User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", "host": "musicbrainz.org", "accept-encoding": "gzip, deflate", "accept": "application/json" diff --git a/test/fixtures/a0ed4659bace0bc088ef218af3ecfc10 b/test/fixtures/a0ed4659bace0bc088ef218af3ecfc10 new file mode 100644 index 0000000..00c3600 Binary files /dev/null and b/test/fixtures/a0ed4659bace0bc088ef218af3ecfc10 differ diff --git a/test/fixtures/a0ed4659bace0bc088ef218af3ecfc10.headers b/test/fixtures/a0ed4659bace0bc088ef218af3ecfc10.headers new file mode 100644 index 0000000..66de879 --- /dev/null +++ b/test/fixtures/a0ed4659bace0bc088ef218af3ecfc10.headers @@ -0,0 +1,29 @@ +{ + "statusCode": 200, + "headers": { + "date": "Fri, 09 Dec 2016 21:53:11 GMT", + "content-type": "application/json; charset=utf-8", + "transfer-encoding": "chunked", + "connection": "keep-alive", + "keep-alive": "timeout=15", + "vary": "Accept-Encoding", + "x-ratelimit-limit": "700", + "x-ratelimit-remaining": "555", + "x-ratelimit-reset": "1481320392", + "server": "Plack::Handler::Starlet", + "etag": "W/\"9a9c2cdbc92df7efa25d42bd9169b9a8\"", + "access-control-allow-origin": "*", + "content-encoding": "gzip" + }, + "url": "http://musicbrainz.org:80/ws/2/artist?area=3f504d54-c40c-487d-bc16-c1990eac887f&fmt=json", + "time": 1072, + "request": { + "method": "GET", + "headers": { + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", + "host": "musicbrainz.org", + "accept-encoding": "gzip, deflate", + "accept": "application/json" + } + } +} \ No newline at end of file diff --git a/test/fixtures/a81703ff2de3c55fdf82ff4d0a1f5052 b/test/fixtures/a81703ff2de3c55fdf82ff4d0a1f5052 index f887f94..69c31ad 100644 Binary files a/test/fixtures/a81703ff2de3c55fdf82ff4d0a1f5052 and b/test/fixtures/a81703ff2de3c55fdf82ff4d0a1f5052 differ diff --git a/test/fixtures/a81703ff2de3c55fdf82ff4d0a1f5052.headers b/test/fixtures/a81703ff2de3c55fdf82ff4d0a1f5052.headers index e643e66..ef0a1af 100644 --- a/test/fixtures/a81703ff2de3c55fdf82ff4d0a1f5052.headers +++ b/test/fixtures/a81703ff2de3c55fdf82ff4d0a1f5052.headers @@ -1,26 +1,26 @@ { "statusCode": 200, "headers": { - "date": "Thu, 08 Dec 2016 22:32:01 GMT", + "date": "Fri, 09 Dec 2016 21:53:11 GMT", "content-type": "application/json; charset=utf-8", "transfer-encoding": "chunked", "connection": "keep-alive", "keep-alive": "timeout=15", "vary": "Accept-Encoding", "x-ratelimit-limit": "700", - "x-ratelimit-remaining": "147", - "x-ratelimit-reset": "1481236321", + "x-ratelimit-remaining": "559", + "x-ratelimit-reset": "1481320392", "server": "Plack::Handler::Starlet", - "etag": "W/\"2dd0bb83c0e5e4f352ffbf3a1272050d\"", + "etag": "W/\"d4f25526cc965da41321e414529517ef\"", "access-control-allow-origin": "*", "content-encoding": "gzip" }, "url": "http://musicbrainz.org:80/ws/2/release-group?artist=c8da2e40-bd28-4d4e-813a-bd2f51958ba8&inc=artist-credits&fmt=json", - "time": 439, + "time": 416, "request": { "method": "GET", "headers": { - "User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", "host": "musicbrainz.org", "accept-encoding": "gzip, deflate", "accept": "application/json" diff --git a/test/fixtures/b1df6f5637b0de25ce9f54874c8ecffc b/test/fixtures/b1df6f5637b0de25ce9f54874c8ecffc index cc077d0..4db3b60 100644 Binary files a/test/fixtures/b1df6f5637b0de25ce9f54874c8ecffc and b/test/fixtures/b1df6f5637b0de25ce9f54874c8ecffc differ diff --git a/test/fixtures/b1df6f5637b0de25ce9f54874c8ecffc.headers b/test/fixtures/b1df6f5637b0de25ce9f54874c8ecffc.headers index 28dae79..870ae58 100644 --- a/test/fixtures/b1df6f5637b0de25ce9f54874c8ecffc.headers +++ b/test/fixtures/b1df6f5637b0de25ce9f54874c8ecffc.headers @@ -1,26 +1,26 @@ { "statusCode": 200, "headers": { - "date": "Thu, 08 Dec 2016 22:32:10 GMT", + "date": "Fri, 09 Dec 2016 21:53:22 GMT", "content-type": "application/json; charset=utf-8", "transfer-encoding": "chunked", "connection": "keep-alive", "keep-alive": "timeout=15", "vary": "Accept-Encoding", "x-ratelimit-limit": "700", - "x-ratelimit-remaining": "255", - "x-ratelimit-reset": "1481236331", + "x-ratelimit-remaining": "263", + "x-ratelimit-reset": "1481320402", "server": "Plack::Handler::Starlet", - "etag": "W/\"dbec5286f8302667b6edff5be3352490\"", + "etag": "W/\"6594e99cea0327cd0491b879ebeb6baf\"", "access-control-allow-origin": "*", "content-encoding": "gzip" }, "url": "http://musicbrainz.org:80/ws/2/artist/49a51491-650e-44b3-8085-2f07ac2986dd?inc=artist-rels&fmt=json", - "time": 672, + "time": 419, "request": { "method": "GET", "headers": { - "User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", "host": "musicbrainz.org", "accept-encoding": "gzip, deflate", "accept": "application/json" diff --git a/test/fixtures/c907a9892b9dacd1c8f6a85cf9b95fb9 b/test/fixtures/c907a9892b9dacd1c8f6a85cf9b95fb9 index c8cd156..6d2c45f 100644 Binary files a/test/fixtures/c907a9892b9dacd1c8f6a85cf9b95fb9 and b/test/fixtures/c907a9892b9dacd1c8f6a85cf9b95fb9 differ diff --git a/test/fixtures/c907a9892b9dacd1c8f6a85cf9b95fb9.headers b/test/fixtures/c907a9892b9dacd1c8f6a85cf9b95fb9.headers index 301576e..90eb5c9 100644 --- a/test/fixtures/c907a9892b9dacd1c8f6a85cf9b95fb9.headers +++ b/test/fixtures/c907a9892b9dacd1c8f6a85cf9b95fb9.headers @@ -1,26 +1,26 @@ { "statusCode": 200, "headers": { - "date": "Thu, 08 Dec 2016 22:32:06 GMT", + "date": "Fri, 09 Dec 2016 21:53:17 GMT", "content-type": "application/json; charset=utf-8", "transfer-encoding": "chunked", "connection": "keep-alive", "keep-alive": "timeout=15", "vary": "Accept-Encoding", "x-ratelimit-limit": "700", - "x-ratelimit-remaining": "570", - "x-ratelimit-reset": "1481236327", + "x-ratelimit-remaining": "607", + "x-ratelimit-reset": "1481320398", "server": "Plack::Handler::Starlet", - "etag": "W/\"00e70096bc0434f732f47e3050094637\"", + "etag": "W/\"86e889bbf99d0bd3b567fa8888299b53\"", "access-control-allow-origin": "*", "content-encoding": "gzip" }, "url": "http://musicbrainz.org:80/ws/2/artist?release=2ac3cbf2-f0d0-3678-af5f-b62dcb051bc0&inc=artist-rels&fmt=json", - "time": 841, + "time": 1132, "request": { "method": "GET", "headers": { - "User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", "host": "musicbrainz.org", "accept-encoding": "gzip, deflate", "accept": "application/json" diff --git a/test/fixtures/d1a0073e6dcac919d8fdf8be12bfcbec b/test/fixtures/d1a0073e6dcac919d8fdf8be12bfcbec index cbb7c8a..18d614c 100644 Binary files a/test/fixtures/d1a0073e6dcac919d8fdf8be12bfcbec and b/test/fixtures/d1a0073e6dcac919d8fdf8be12bfcbec differ diff --git a/test/fixtures/d1a0073e6dcac919d8fdf8be12bfcbec.headers b/test/fixtures/d1a0073e6dcac919d8fdf8be12bfcbec.headers index 4603681..379751d 100644 --- a/test/fixtures/d1a0073e6dcac919d8fdf8be12bfcbec.headers +++ b/test/fixtures/d1a0073e6dcac919d8fdf8be12bfcbec.headers @@ -1,26 +1,26 @@ { "statusCode": 200, "headers": { - "date": "Thu, 08 Dec 2016 22:32:11 GMT", + "date": "Fri, 09 Dec 2016 21:53:22 GMT", "content-type": "application/json; charset=utf-8", "transfer-encoding": "chunked", "connection": "keep-alive", "keep-alive": "timeout=15", "vary": "Accept-Encoding", "x-ratelimit-limit": "700", - "x-ratelimit-remaining": "253", - "x-ratelimit-reset": "1481236331", + "x-ratelimit-remaining": "258", + "x-ratelimit-reset": "1481320402", "server": "Plack::Handler::Starlet", - "etag": "W/\"262816d2e746629059388bf96eb1241d\"", + "etag": "W/\"8b0d167a80f1f60f6b0ccdb1254ea172\"", "access-control-allow-origin": "*", "content-encoding": "gzip" }, "url": "http://musicbrainz.org:80/ws/2/artist/4d5447d7-c61c-4120-ba1b-d7f471d385b9?inc=artist-rels&fmt=json", - "time": 676, + "time": 508, "request": { "method": "GET", "headers": { - "User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", "host": "musicbrainz.org", "accept-encoding": "gzip, deflate", "accept": "application/json" diff --git a/test/fixtures/f2a7af3e3a39e31ee0d9d74b5820ebff b/test/fixtures/f2a7af3e3a39e31ee0d9d74b5820ebff index 3c88946..8eaf2f6 100644 Binary files a/test/fixtures/f2a7af3e3a39e31ee0d9d74b5820ebff and b/test/fixtures/f2a7af3e3a39e31ee0d9d74b5820ebff differ diff --git a/test/fixtures/f2a7af3e3a39e31ee0d9d74b5820ebff.headers b/test/fixtures/f2a7af3e3a39e31ee0d9d74b5820ebff.headers index b1dbbee..1743d81 100644 --- a/test/fixtures/f2a7af3e3a39e31ee0d9d74b5820ebff.headers +++ b/test/fixtures/f2a7af3e3a39e31ee0d9d74b5820ebff.headers @@ -1,26 +1,26 @@ { "statusCode": 200, "headers": { - "date": "Thu, 08 Dec 2016 22:32:06 GMT", + "date": "Fri, 09 Dec 2016 21:53:18 GMT", "content-type": "application/json; charset=utf-8", "transfer-encoding": "chunked", "connection": "keep-alive", "keep-alive": "timeout=15", "vary": "Accept-Encoding", "x-ratelimit-limit": "700", - "x-ratelimit-remaining": "288", - "x-ratelimit-reset": "1481236327", + "x-ratelimit-remaining": "220", + "x-ratelimit-reset": "1481320398", "server": "Plack::Handler::Starlet", - "etag": "W/\"7c937ac3dcff44777fa9d4c32d65b803\"", + "etag": "W/\"5da167e635ba53580f8c82e6958f2ec9\"", "access-control-allow-origin": "*", "content-encoding": "gzip" }, "url": "http://musicbrainz.org:80/ws/2/artist/42a8f507-8412-4611-854f-926571049fa0?inc=artist-rels&fmt=json", - "time": 558, + "time": 488, "request": { "method": "GET", "headers": { - "User-Agent": "graphbrainz/3.1.0 ( https://github.com/exogen/graphbrainz )", + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", "host": "musicbrainz.org", "accept-encoding": "gzip, deflate", "accept": "application/json" diff --git a/test/fixtures/f5cc4554214e4421714ea8f4650632b5 b/test/fixtures/f5cc4554214e4421714ea8f4650632b5 new file mode 100644 index 0000000..162829b Binary files /dev/null and b/test/fixtures/f5cc4554214e4421714ea8f4650632b5 differ diff --git a/test/fixtures/f5cc4554214e4421714ea8f4650632b5.headers b/test/fixtures/f5cc4554214e4421714ea8f4650632b5.headers new file mode 100644 index 0000000..516208f --- /dev/null +++ b/test/fixtures/f5cc4554214e4421714ea8f4650632b5.headers @@ -0,0 +1,29 @@ +{ + "statusCode": 200, + "headers": { + "date": "Fri, 09 Dec 2016 22:08:27 GMT", + "content-type": "application/json; charset=utf-8", + "transfer-encoding": "chunked", + "connection": "keep-alive", + "keep-alive": "timeout=15", + "vary": "Accept-Encoding", + "x-ratelimit-limit": "700", + "x-ratelimit-remaining": "287", + "x-ratelimit-reset": "1481321304", + "server": "Plack::Handler::Starlet", + "etag": "W/\"4466cd809101f3b9c834437d95f317ba\"", + "access-control-allow-origin": "*", + "content-encoding": "gzip" + }, + "url": "http://musicbrainz.org:80/ws/2/artist/65314b12-0e08-43fa-ba33-baaa7b874c15?inc=artist-rels%2Brecording-rels%2Brelease-rels&fmt=json", + "time": 3639, + "request": { + "method": "GET", + "headers": { + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", + "host": "musicbrainz.org", + "accept-encoding": "gzip, deflate", + "accept": "application/json" + } + } +} \ No newline at end of file diff --git a/test/fixtures/fa82576d5b7a7fc3ae596f5543219b2d b/test/fixtures/fa82576d5b7a7fc3ae596f5543219b2d new file mode 100644 index 0000000..b48f942 Binary files /dev/null and b/test/fixtures/fa82576d5b7a7fc3ae596f5543219b2d differ diff --git a/test/fixtures/fa82576d5b7a7fc3ae596f5543219b2d.headers b/test/fixtures/fa82576d5b7a7fc3ae596f5543219b2d.headers new file mode 100644 index 0000000..0f246fc --- /dev/null +++ b/test/fixtures/fa82576d5b7a7fc3ae596f5543219b2d.headers @@ -0,0 +1,29 @@ +{ + "statusCode": 200, + "headers": { + "date": "Sat, 10 Dec 2016 02:24:17 GMT", + "content-type": "application/json; charset=utf-8", + "transfer-encoding": "chunked", + "connection": "keep-alive", + "keep-alive": "timeout=15", + "vary": "Accept-Encoding", + "x-ratelimit-limit": "700", + "x-ratelimit-remaining": "472", + "x-ratelimit-reset": "1481336658", + "server": "Plack::Handler::Starlet", + "etag": "W/\"b99b4284b3ed400d70ad6d104e56cbb2\"", + "access-control-allow-origin": "*", + "content-encoding": "gzip" + }, + "url": "http://musicbrainz.org:80/ws/2/release-group?artist=5b11f4ce-a62d-471e-81fc-a69a8278c7da&type=ep&fmt=json", + "time": 463, + "request": { + "method": "GET", + "headers": { + "User-Agent": "graphbrainz/3.1.1 ( https://github.com/exogen/graphbrainz )", + "host": "musicbrainz.org", + "accept-encoding": "gzip, deflate", + "accept": "application/json" + } + } +} \ No newline at end of file diff --git a/test/helpers/client.js b/test/helpers/client.js new file mode 100644 index 0000000..962017a --- /dev/null +++ b/test/helpers/client.js @@ -0,0 +1,11 @@ +import path from 'path' +import sepia from 'sepia' +import MusicBrainz from '../../src/api' + +sepia.fixtureDir(path.join(__dirname, '..', 'fixtures')) + +const options = /^(playback|cache)$/.test(process.env.VCR_MODE) + ? { limit: Infinity, period: 0 } + : {} + +export default new MusicBrainz(options) diff --git a/test/helpers/context.js b/test/helpers/context.js new file mode 100644 index 0000000..c60cf17 --- /dev/null +++ b/test/helpers/context.js @@ -0,0 +1,7 @@ +import createLoaders from '../../src/loaders' +import client from './client' + +export default { + client, + loaders: createLoaders(client) +} diff --git a/test/schema.js b/test/schema.js index 69f1c7f..fdd74b3 100644 --- a/test/schema.js +++ b/test/schema.js @@ -1,25 +1,25 @@ -import path from 'path' import test from 'ava' -import sepia from 'sepia' import { graphql } from 'graphql' -import MusicBrainz from '../src/api' import schema from '../src/schema' -import createLoaders from '../src/loaders' +import context from './helpers/context' -sepia.fixtureDir(path.join(__dirname, 'fixtures')) +function testData (t, query, handler) { + return graphql(schema, query, null, context).then(result => { + t.is(result.errors, undefined) + return handler(t, result.data) + }) +} -let client -let loaders -let context +function testError (t, query, handler) { + return graphql(schema, query, null, context).then(result => { + t.truthy(result.errors) + t.true(result.errors.length > 0) + return handler(t, result.errors) + }) +} -test.before(t => { - client = new MusicBrainz() - loaders = createLoaders(client) - context = { client, loaders } -}) - -test('schema has a node field', t => { - const query = ` +test('schema has a node field', testData, + ` { node(id: "UmVsZWFzZUdyb3VwOmUzN2QyNzQwLTQ1MDMtNGUzZi1hYjZkLWU2MjJhMjVlOTY0ZA==") { __typename @@ -28,21 +28,18 @@ test('schema has a node field', t => { } } } - ` - return graphql(schema, query, null, context).then(result => { - t.deepEqual(result, { - data: { - node: { - __typename: 'ReleaseGroup', - mbid: 'e37d2740-4503-4e3f-ab6d-e622a25e964d' - } + `, (t, data) => { + t.deepEqual(data, { + node: { + __typename: 'ReleaseGroup', + mbid: 'e37d2740-4503-4e3f-ab6d-e622a25e964d' } }) - }) -}) + } +) -test('schema has a lookup query', t => { - const query = ` +test('schema has a lookup query', testData, + ` { lookup { artist (mbid: "c8da2e40-bd28-4d4e-813a-bd2f51958ba8") { @@ -52,24 +49,20 @@ test('schema has a lookup query', t => { } } } - ` - return graphql(schema, query, null, context).then(result => { - t.deepEqual(result, { - data: { - lookup: { - artist: { - mbid: 'c8da2e40-bd28-4d4e-813a-bd2f51958ba8', - name: 'Lures', - type: 'Group' - } + `, (t, data) => { + t.deepEqual(data, { + lookup: { + artist: { + mbid: 'c8da2e40-bd28-4d4e-813a-bd2f51958ba8', + name: 'Lures', + type: 'Group' } } }) }) -}) -test('schema has a search query', t => { - const query = ` +test('schema has a search query', testData, + ` { search { recordings (query: "Burn the Witch") { @@ -84,17 +77,15 @@ test('schema has a search query', t => { } } } - ` - return graphql(schema, query, null, context).then(result => { - const { recordings } = result.data.search + `, (t, data) => { + const { recordings } = data.search t.true(recordings.totalCount > 0) t.true(recordings.edges.length === 25) recordings.edges.forEach(edge => t.true(edge.score > 0)) }) -}) -test('schema has a browse query', t => { - const query = ` +test('schema has a browse query', testData, + ` { browse { releaseGroups (artist: "c8da2e40-bd28-4d4e-813a-bd2f51958ba8") { @@ -115,17 +106,15 @@ test('schema has a browse query', t => { } } } - ` - return graphql(schema, query, null, context).then(result => { - const { releaseGroups } = result.data.browse + `, (t, data) => { + const { releaseGroups } = data.browse t.true(releaseGroups.totalCount > 0) t.true(releaseGroups.edges.length > 0) releaseGroups.edges.forEach(edge => t.truthy(edge.node.title)) }) -}) -test('supports deeply nested queries', t => { - const query = ` +test('supports deeply nested queries', testData, + ` query AppleRecordsMarriages { search { labels(query: "Apple Records", first: 1) { @@ -193,10 +182,284 @@ test('supports deeply nested queries', t => { } } } - ` - return graphql(schema, query, null, context).then(result => { - const { labels } = result.data.search + `, (t, data) => { + const { labels } = data.search t.true(labels.edges.length > 0) t.is(labels.edges[0].node.releases.edges.length, 1) }) -}) + +test('throws an error if given a malformed MBID', testError, + ` + { + lookup { + artist(mbid: "ABC123") { + name + } + } + } + `, (t, errors) => { + const err = errors[0] + t.true(err instanceof TypeError) + t.is(err.message, 'Malformed MBID: ABC123') + }) + +test('Artist beginArea/endArea pulls from begin_area/end_area for lookup queries', testData, + ` + { + lookup { + artist(mbid: "65314b12-0e08-43fa-ba33-baaa7b874c15") { + beginArea { + name + } + endArea { + name + } + } + } + } + `, (t, data) => { + const { artist } = data.lookup + t.is(artist.beginArea.name, 'Westmount') + t.is(artist.endArea.name, 'Los Angeles') + }) + +test('Artist beginArea/endArea pull from begin_area/end_area for browse queries', testData, + ` + { + browse { + artists(area: "3f504d54-c40c-487d-bc16-c1990eac887f") { + edges { + node { + beginArea { + name + } + endArea { + name + } + } + } + } + } + } + `, (t, data) => { + const artists = data.browse.artists.edges.map(edge => edge.node) + t.true(artists.length > 1) + t.true(artists.some(artist => artist.beginArea)) + t.true(artists.some(artist => artist.endArea)) + }) + +test('Artist beginArea/endArea pulls from begin-area/end-area for search queries', testData, + ` + { + search { + artists(query: "Leonard Cohen", first: 1) { + edges { + node { + beginArea { + name + } + endArea { + name + } + } + } + } + } + } + `, (t, data) => { + const artists = data.search.artists.edges.map(edge => edge.node) + t.true(artists.length === 1) + t.is(artists[0].beginArea.name, 'Westmount') + t.is(artists[0].endArea.name, 'Los Angeles') + }) + +test('relationships filter by type', testData, + ` + { + lookup { + artist(mbid: "65314b12-0e08-43fa-ba33-baaa7b874c15") { + relationships { + artists(first: 5) { + edges { + node { + target { + __typename + } + targetType + } + } + } + recordings(first: 5) { + edges { + node { + target { + __typename + } + targetType + } + } + } + releases(first: 5) { + edges { + node { + target { + __typename + } + targetType + } + } + } + } + } + } + } + `, (t, data) => { + const { relationships } = data.lookup.artist + t.is(relationships.artists.edges.length, 5) + relationships.artists.edges.forEach(edge => { + t.is(edge.node.targetType, 'artist') + t.is(edge.node.target.__typename, 'Artist') + }) + t.is(relationships.recordings.edges.length, 5) + relationships.recordings.edges.forEach(edge => { + t.is(edge.node.targetType, 'recording') + t.is(edge.node.target.__typename, 'Recording') + }) + t.is(relationships.releases.edges.length, 5) + relationships.releases.edges.forEach(edge => { + t.is(edge.node.targetType, 'release') + t.is(edge.node.target.__typename, 'Release') + }) + }) + +test('Area maps iso-3166-1-codes to isoCodes', testData, + ` + { + lookup { + area(mbid: "489ce91b-6658-3307-9877-795b68554c98") { + name + isoCodes + } + } + } + `, (t, data) => { + t.deepEqual(data.lookup.area.isoCodes, ['US']) + }) + +test('Alias locales use the Locale scalar', testData, + ` + { + lookup { + artist(mbid: "f99b7d67-4e63-4678-aa66-4c6ac0f7d24a") { + aliases { + name + locale + } + } + } + } + `, (t, data) => { + const { aliases } = data.lookup.artist + t.is(aliases.find(alias => alias.locale === 'en').name, 'PSY') + t.is(aliases.find(alias => alias.locale === 'ko').name, '싸이') + }) + +test('Work ISWCs use the ISWC scalar', testData, + ` + { + lookup { + work(mbid: "ef7d0814-da6a-32f5-a600-ff81cffd1aed") { + title + iswcs + } + } + } + `, (t, data) => { + const { work } = data.lookup + t.is(work.title, 'Song of the French Partisan') + t.deepEqual(work.iswcs, ['T-900.755.682-3']) + }) + +test('URLs may be looked up by resource', testData, + ` + { + lookup { + url(resource: "http://www.nirvana.com/") { + mbid + resource + } + } + } + `, (t, data) => { + const { url } = data.lookup + t.is(url.mbid, '4347ffe2-82ec-4059-9520-6a1a3f73a304') + t.is(url.resource, 'http://www.nirvana.com/') + }) + +test('throws an error if given a malformed URLString', testError, + ` + { + lookup { + url(resource: "http:foo") { + mbid + resource + } + } + } + `, (t, errors) => { + const err = errors[0] + t.true(err instanceof TypeError) + t.is(err.message, 'Malformed URL: http:foo') + }) + +test('Release groups can be browsed by type', testData, + ` + { + browse { + releaseGroups(artist: "5b11f4ce-a62d-471e-81fc-a69a8278c7da", type: EP) { + edges { + node { + primaryType + } + } + } + } + } + `, (t, data) => { + const releaseGroups = data.browse.releaseGroups.edges.map(edge => edge.node) + t.is(releaseGroups.length, 8) + releaseGroups.forEach(releaseGroup => t.is(releaseGroup.primaryType, 'EP')) + }) + +test('Releases can be browsed by type and status', testData, + ` + { + browse { + releases(artist: "5b11f4ce-a62d-471e-81fc-a69a8278c7da", type: EP, status: BOOTLEG) { + edges { + node { + status + } + } + } + } + } + `, (t, data) => { + const releases = data.browse.releases.edges.map(edge => edge.node) + t.is(releases.length, 6) + releases.forEach(release => t.is(release.status, 'BOOTLEG')) + }) + +test('Releases have an ASIN field', testData, + ` + { + lookup { + release(mbid: "d5cdb7fd-c7e9-460a-9549-8a369655cc52") { + asin + } + } + } + `, (t, data) => { + const { release } = data.lookup + t.is(release.asin, 'B01KN6XDS6') + }) diff --git a/yarn.lock b/yarn.lock index 8e3cdd1..0ea4fa0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -32,8 +32,8 @@ ajv-keywords@^1.0.0: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.2.0.tgz#676c4f087bfe1e8b12dca6fda2f3c74f417b099c" ajv@^4.7.0: - version "4.9.1" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.9.1.tgz#08e1b0a5fddc8b844d28ca7b03510e78812ee3a0" + version "4.9.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.9.2.tgz#3f7dcda95b0c34bceb2d69945117d146219f1a2c" dependencies: co "^4.6.0" json-stable-stringify "^1.0.1" @@ -322,27 +322,27 @@ babel-cli@^6.18.0: optionalDependencies: chokidar "^1.0.0" -babel-code-frame@^6.16.0: - version "6.16.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.16.0.tgz#f90e60da0862909d3ce098733b5d3987c97cb8de" +babel-code-frame@^6.16.0, babel-code-frame@^6.20.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.20.0.tgz#b968f839090f9a8bc6d41938fb96cb84f7387b26" dependencies: chalk "^1.1.0" esutils "^2.0.2" js-tokens "^2.0.0" babel-core@^6.17.0, babel-core@^6.18.0: - version "6.18.2" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.18.2.tgz#d8bb14dd6986fa4f3566a26ceda3964fa0e04e5b" + version "6.20.0" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.20.0.tgz#ab0d7176d9dea434e66badadaf92237865eab1ec" dependencies: - babel-code-frame "^6.16.0" - babel-generator "^6.18.0" + babel-code-frame "^6.20.0" + babel-generator "^6.20.0" babel-helpers "^6.16.0" babel-messages "^6.8.0" babel-register "^6.18.0" - babel-runtime "^6.9.1" + babel-runtime "^6.20.0" babel-template "^6.16.0" - babel-traverse "^6.18.0" - babel-types "^6.18.0" + babel-traverse "^6.20.0" + babel-types "^6.20.0" babylon "^6.11.0" convert-source-map "^1.1.0" debug "^2.1.1" @@ -364,13 +364,13 @@ babel-eslint@^7.1.1: babylon "^6.13.0" lodash.pickby "^4.6.0" -babel-generator@^6.1.0, babel-generator@^6.18.0: - version "6.19.0" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.19.0.tgz#9b2f244204777a3d6810ec127c673c87b349fac5" +babel-generator@^6.1.0, babel-generator@^6.18.0, babel-generator@^6.20.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.20.0.tgz#fee63614e0449390103b3097f3f6a118016c6766" dependencies: babel-messages "^6.8.0" - babel-runtime "^6.9.0" - babel-types "^6.19.0" + babel-runtime "^6.20.0" + babel-types "^6.20.0" detect-indent "^4.0.0" jsesc "^1.3.0" lodash "^4.2.0" @@ -467,14 +467,14 @@ babel-helper-regex@^6.8.0: lodash "^4.2.0" babel-helper-remap-async-to-generator@^6.16.0, babel-helper-remap-async-to-generator@^6.16.2: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.18.0.tgz#336cdf3cab650bb191b02fc16a3708e7be7f9ce5" + version "6.20.3" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.20.3.tgz#9dd3b396f13e35ef63e538098500adc24c63c4e7" dependencies: babel-helper-function-name "^6.18.0" - babel-runtime "^6.0.0" + babel-runtime "^6.20.0" babel-template "^6.16.0" - babel-traverse "^6.18.0" - babel-types "^6.18.0" + babel-traverse "^6.20.0" + babel-types "^6.20.0" babel-helper-replace-supers@^6.18.0, babel-helper-replace-supers@^6.8.0: version "6.18.0" @@ -567,8 +567,8 @@ babel-plugin-syntax-object-rest-spread@^6.8.0: resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" babel-plugin-syntax-trailing-function-commas@^6.3.13: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.13.0.tgz#2b84b7d53dd744f94ff1fad7669406274b23f541" + version "6.20.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.20.0.tgz#442835e19179f45b87e92d477d70b9f1f18b5c4f" babel-plugin-transform-async-generator-functions@^6.17.0: version "6.17.0" @@ -619,13 +619,13 @@ babel-plugin-transform-es2015-block-scoped-functions@^6.3.13: babel-runtime "^6.0.0" babel-plugin-transform-es2015-block-scoping@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.18.0.tgz#3bfdcfec318d46df22525cdea88f1978813653af" + version "6.20.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.20.0.tgz#5d8f3e83b1a1ae1064e64a9e5bb83108d8e73be3" dependencies: - babel-runtime "^6.9.0" + babel-runtime "^6.20.0" babel-template "^6.15.0" - babel-traverse "^6.18.0" - babel-types "^6.18.0" + babel-traverse "^6.20.0" + babel-types "^6.20.0" lodash "^4.2.0" babel-plugin-transform-es2015-classes@^6.18.0: @@ -784,19 +784,17 @@ babel-plugin-transform-exponentiation-operator@^6.3.13: babel-runtime "^6.0.0" babel-plugin-transform-object-rest-spread@^6.16.0: - version "6.19.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.19.0.tgz#f6ac428ee3cb4c6aa00943ed1422ce813603b34c" + version "6.20.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.20.2.tgz#e816c55bba77b14c16365d87e2ae48c8fd18fc2e" dependencies: babel-plugin-syntax-object-rest-spread "^6.8.0" - babel-runtime "^6.0.0" + babel-runtime "^6.20.0" babel-plugin-transform-regenerator@^6.16.0: - version "6.16.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.16.1.tgz#a75de6b048a14154aae14b0122756c5bed392f59" + version "6.20.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.20.0.tgz#a546cd2aa1c9889929d5c427a31303847847ab75" dependencies: - babel-runtime "^6.9.0" - babel-types "^6.16.0" - private "~0.1.5" + regenerator-transform "0.9.8" babel-plugin-transform-runtime@^6.15.0: version "6.15.0" @@ -812,12 +810,12 @@ babel-plugin-transform-strict-mode@^6.18.0: babel-types "^6.18.0" babel-polyfill@^6.16.0: - version "6.16.0" - resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.16.0.tgz#2d45021df87e26a374b6d4d1a9c65964d17f2422" + version "6.20.0" + resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.20.0.tgz#de4a371006139e20990aac0be367d398331204e7" dependencies: - babel-runtime "^6.9.1" + babel-runtime "^6.20.0" core-js "^2.4.0" - regenerator-runtime "^0.9.5" + regenerator-runtime "^0.10.0" babel-preset-es2015-node4@^2.1.0: version "2.1.0" @@ -892,12 +890,12 @@ babel-register@^6.18.0: mkdirp "^0.5.1" source-map-support "^0.4.2" -babel-runtime@^6.0.0, babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.9.0, babel-runtime@^6.9.1: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.18.0.tgz#0f4177ffd98492ef13b9f823e9994a02584c9078" +babel-runtime@^6.0.0, babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.20.0, babel-runtime@^6.9.0, babel-runtime@^6.9.1: + version "6.20.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.20.0.tgz#87300bdcf4cd770f09bf0048c64204e17806d16f" dependencies: core-js "^2.4.0" - regenerator-runtime "^0.9.5" + regenerator-runtime "^0.10.0" babel-template@^6.14.0, babel-template@^6.15.0, babel-template@^6.16.0, babel-template@^6.7.0, babel-template@^6.8.0: version "6.16.0" @@ -909,25 +907,25 @@ babel-template@^6.14.0, babel-template@^6.15.0, babel-template@^6.16.0, babel-te babylon "^6.11.0" lodash "^4.2.0" -babel-traverse@^6.15.0, babel-traverse@^6.16.0, babel-traverse@^6.18.0: - version "6.19.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.19.0.tgz#68363fb821e26247d52a519a84b2ceab8df4f55a" +babel-traverse@^6.15.0, babel-traverse@^6.16.0, babel-traverse@^6.18.0, babel-traverse@^6.20.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.20.0.tgz#5378d1a743e3d856e6a52289994100bbdfd9872a" dependencies: - babel-code-frame "^6.16.0" + babel-code-frame "^6.20.0" babel-messages "^6.8.0" - babel-runtime "^6.9.0" - babel-types "^6.19.0" + babel-runtime "^6.20.0" + babel-types "^6.20.0" babylon "^6.11.0" debug "^2.2.0" globals "^9.0.0" invariant "^2.2.0" lodash "^4.2.0" -babel-types@^6.13.0, babel-types@^6.15.0, babel-types@^6.16.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.7.2, babel-types@^6.8.0, babel-types@^6.9.0: - version "6.19.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.19.0.tgz#8db2972dbed01f1192a8b602ba1e1e4c516240b9" +babel-types@^6.13.0, babel-types@^6.15.0, babel-types@^6.16.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.20.0, babel-types@^6.7.2, babel-types@^6.8.0, babel-types@^6.9.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.20.0.tgz#3869ecb98459533b37df809886b3f7f3b08d2baa" dependencies: - babel-runtime "^6.9.1" + babel-runtime "^6.20.0" esutils "^2.0.2" lodash "^4.2.0" to-fast-properties "^1.0.1" @@ -1359,20 +1357,6 @@ cross-env@^3.1.3: dependencies: cross-spawn "^3.0.1" -cross-spawn-async@^2.0.0: - version "2.2.5" - resolved "https://registry.yarnpkg.com/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz#845ff0c0834a3ded9d160daca6d390906bb288cc" - dependencies: - lru-cache "^4.0.0" - which "^1.2.8" - -cross-spawn@2.0.x: - version "2.0.1" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-2.0.1.tgz#ab6fd893a099759d9b85220e3a64397de946b0f6" - dependencies: - cross-spawn-async "^2.0.0" - spawn-sync "1.0.13" - cross-spawn@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" @@ -1387,6 +1371,14 @@ cross-spawn@^4, cross-spawn@^4.0.0: lru-cache "^4.0.1" which "^1.2.9" +cross-spawn@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.0.1.tgz#a3bbb302db2297cbea3c04edf36941f4613aa399" + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + cryptiles@2.x.x: version "2.0.5" resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" @@ -1955,7 +1947,7 @@ finalhandler@0.5.0: find-cache-dir@^0.1.1: version "0.1.1" - resolved "http://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" dependencies: commondir "^1.0.1" mkdirp "^0.5.1" @@ -2762,8 +2754,8 @@ jsx-ast-utils@^1.3.3: object-assign "^4.1.0" kind-of@^3.0.2: - version "3.0.4" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.0.4.tgz#7b8ecf18a4e17f8269d73b501c9f232c96887a74" + version "3.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.1.0.tgz#475d698a5e49ff5e53d14e3e732429dc8bf4cf47" dependencies: is-buffer "^1.0.2" @@ -2956,7 +2948,7 @@ lowercase-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" -lru-cache@^4.0.0, lru-cache@^4.0.1: +lru-cache@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e" dependencies: @@ -3570,10 +3562,11 @@ power-assert-util-string-width@^1.1.1: eastasianwidth "^0.1.1" pre-commit@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/pre-commit/-/pre-commit-1.1.3.tgz#6d5ed90740472072958c711a15f676aa2c231377" + version "1.2.0" + resolved "https://registry.yarnpkg.com/pre-commit/-/pre-commit-1.2.0.tgz#16a1a218861c778d1a1498719c9763717913d5b8" dependencies: - cross-spawn "2.0.x" + cross-spawn "^5.0.1" + spawn-sync "^1.0.15" which "1.2.x" prelude-ls@~1.1.2: @@ -3602,7 +3595,7 @@ pretty-ms@^2.0.0: parse-ms "^1.0.0" plur "^1.0.0" -private@^0.1.6, private@~0.1.5: +private@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/private/-/private-0.1.6.tgz#55c6a976d0f9bafb9924851350fe47b9b5fbb7c1" @@ -3771,13 +3764,21 @@ regenerate@^1.2.1: version "1.3.2" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260" -regenerator-runtime@^0.9.5: - version "0.9.6" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.9.6.tgz#d33eb95d0d2001a4be39659707c51b0cb71ce029" +regenerator-runtime@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.1.tgz#257f41961ce44558b18f7814af48c17559f9faeb" + +regenerator-transform@0.9.8: + version "0.9.8" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.9.8.tgz#0f88bb2bc03932ddb7b6b7312e68078f01026d6c" + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" regex-cache@^0.4.2: version "0.4.3" - resolved "http://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145" dependencies: is-equal-shallow "^0.1.3" is-primitive "^2.0.0" @@ -4049,6 +4050,16 @@ setprototypeof@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.2.tgz#81a552141ec104b88e89ce383103ad5c66564d08" +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + shelljs@^0.7.5: version "0.7.5" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.5.tgz#2eef7a50a21e1ccf37da00df767ec69e30ad0675" @@ -4121,9 +4132,9 @@ source-map@^0.5.0, source-map@^0.5.3, source-map@~0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" -spawn-sync@1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/spawn-sync/-/spawn-sync-1.0.13.tgz#904091b9ad48a0f3afb0e84752154c01e82fd8d8" +spawn-sync@^1.0.15: + version "1.0.15" + resolved "https://registry.yarnpkg.com/spawn-sync/-/spawn-sync-1.0.15.tgz#b00799557eb7fb0c8376c29d44e8a1ea67e57476" dependencies: concat-stream "^1.4.7" os-shim "^0.1.2" @@ -4692,7 +4703,7 @@ which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" -which@1.2.x, which@^1.2.4, which@^1.2.8, which@^1.2.9: +which@1.2.x, which@^1.2.4, which@^1.2.9: version "1.2.12" resolved "https://registry.yarnpkg.com/which/-/which-1.2.12.tgz#de67b5e450269f194909ef23ece4ebe416fa1192" dependencies: