diff --git a/docs/schema.md b/docs/schema.md index 1072417..8723359 100644 --- a/docs/schema.md +++ b/docs/schema.md @@ -363,6 +363,10 @@ type BrowseQuery { # The MBID of a release to which the entity is linked. release: MBID + + # The [International Standard Recording Code](https://musicbrainz.org/doc/ISRC) + # (ISRC) of the recording. + isrc: ISRC ): RecordingConnection # Browse release entities linked to the given arguments. @@ -400,6 +404,10 @@ type BrowseQuery { # Filter by one or more release statuses. status: [ReleaseStatus] + + # A [disc ID](https://musicbrainz.org/doc/Disc_ID) + # associated with the release. + discID: DiscID ): ReleaseConnection # Browse release group entities linked to the given arguments. @@ -430,6 +438,10 @@ type BrowseQuery { # The MBID of a collection in which the entity is found. collection: MBID + + # The [International Standard Musical Work Code](https://musicbrainz.org/doc/ISWC) + # (ISWC) of the work. + iswc: ISWC ): WorkConnection } @@ -448,6 +460,21 @@ scalar Date # Decimal degrees, used for latitude and longitude. scalar Degrees +# [Disc ID](https://musicbrainz.org/doc/Disc_ID) is the code +# number which MusicBrainz uses to link a physical CD to a [release](https://musicbrainz.org/doc/Release) +# listing. +# +# A release may have any number of disc IDs, and a disc ID may be linked to +# multiple releases. This is because disc ID calculation involves a hash of the +# frame offsets of the CD tracks. +# +# Different pressing of a CD often have slightly different frame offsets, and +# hence different disc IDs. +# +# Conversely, two different CDs may happen to have exactly the same set of frame +# offsets and hence the same disc ID. +scalar DiscID + # An entity in the MusicBrainz schema. interface Entity { # The MBID of the entity. @@ -605,6 +632,23 @@ scalar IPI # contributors to media content. scalar ISNI +# The [International Standard Recording Code](https://musicbrainz.org/doc/ISRC) +# (ISRC) is an identification system for audio and music video recordings. It is +# standarized by the [IFPI](http://www.ifpi.org/) in ISO 3901:2001 and used by +# IFPI members to assign a unique identifier to every distinct sound recording +# they release. An ISRC identifies a particular [sound recording](https://musicbrainz.org/doc/Recording), +# not the song itself. Therefore, different recordings, edits, remixes and +# remasters of the same song will each be assigned their own ISRC. However, note +# that same recording should carry the same ISRC in all countries/territories. +# Songs are identified by analogous [International Standard Musical Work Codes](https://musicbrainz.org/doc/ISWC) +# (ISWCs). +scalar ISRC + +# The [International Standard Musical Work Code](https://musicbrainz.org/doc/ISWC) +# (ISWC) is an ISO standard similar to ISBNs for identifying musical works / +# compositions. +scalar ISWC + # [Labels](https://musicbrainz.org/doc/Label) represent mostly # (but not only) imprints. To a lesser extent, a label entity may be created to # represent a record company. @@ -952,6 +996,10 @@ type Recording implements Node, Entity { # The main credited artist(s). artistCredits: [ArtistCredit] + # A list of [International Standard Recording Codes](https://musicbrainz.org/doc/ISRC) + # (ISRCs) for this recording. + isrcs: [ISRC] + # An approximation to the length of the recording, calculated # from the lengths of the tracks using it. length: Int diff --git a/docs/types.md b/docs/types.md index f21ece9..da9f59d 100644 --- a/docs/types.md +++ b/docs/types.md @@ -65,9 +65,12 @@ You may also be interested in reading the [schema in GraphQL syntax](schema.md).
  • [Boolean](#boolean)
  • [Date](#date)
  • [Degrees](#degrees)
  • +
  • [DiscID](#discid)
  • [ID](#id)
  • [IPI](#ipi)
  • [ISNI](#isni)
  • +
  • [ISRC](#isrc)
  • +
  • [ISWC](#iswc)
  • [Int](#int)
  • [Locale](#locale)
  • [MBID](#mbid)
  • @@ -1024,6 +1027,12 @@ entity. MBID The MBID of a release to which the entity is linked. + + isrc + ISRC + The International Standard Recording Code +(ISRC) of the recording. + releases ReleaseConnection @@ -1092,6 +1101,12 @@ release, but is not included in the credits for the release itself. [ReleaseStatus] Filter by one or more release statuses. + + discID + DiscID + A disc ID +associated with the release. + releaseGroups ReleaseGroupConnection @@ -1156,6 +1171,12 @@ release, but is not included in the credits for the release itself. MBID The MBID of a collection in which the entity is found. + + iswc + ISWC + The International Standard Musical Work Code +(ISWC) of the work. + ### Coordinates @@ -2305,6 +2326,14 @@ and will be removed in a major release in the future. Use the equivalent The main credited artist(s). + + isrcs + [ISRC] + + A list of International Standard Recording Codes +(ISRCs) for this recording. + + length Int @@ -4715,6 +4744,22 @@ Year, month (optional), and day (optional) in YYYY-MM-DD format. Decimal degrees, used for latitude and longitude. +### DiscID + +[Disc ID](https://musicbrainz.org/doc/Disc_ID) is the code +number which MusicBrainz uses to link a physical CD to a [release](https://musicbrainz.org/doc/Release) +listing. + +A release may have any number of disc IDs, and a disc ID may be linked to +multiple releases. This is because disc ID calculation involves a hash of the +frame offsets of the CD tracks. + +Different pressing of a CD often have slightly different frame offsets, and +hence different disc IDs. + +Conversely, two different CDs may happen to have exactly the same set of frame +offsets and hence the same disc ID. + ### ID The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. @@ -4731,6 +4776,25 @@ 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. +### ISRC + +The [International Standard Recording Code](https://musicbrainz.org/doc/ISRC) +(ISRC) is an identification system for audio and music video recordings. It is +standarized by the [IFPI](http://www.ifpi.org/) in ISO 3901:2001 and used by +IFPI members to assign a unique identifier to every distinct sound recording +they release. An ISRC identifies a particular [sound recording](https://musicbrainz.org/doc/Recording), +not the song itself. Therefore, different recordings, edits, remixes and +remasters of the same song will each be assigned their own ISRC. However, note +that same recording should carry the same ISRC in all countries/territories. +Songs are identified by analogous [International Standard Musical Work Codes](https://musicbrainz.org/doc/ISWC) +(ISWCs). + +### ISWC + +The [International Standard Musical Work Code](https://musicbrainz.org/doc/ISWC) +(ISWC) is an ISO standard similar to ISBNs for identifying musical works / +compositions. + ### Int The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. diff --git a/schema.json b/schema.json index 114347e..c6e6ac2 100644 --- a/schema.json +++ b/schema.json @@ -2031,6 +2031,22 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "isrcs", + "description": "A list of [International Standard Recording Codes](https://musicbrainz.org/doc/ISRC)\n(ISRCs) for this recording.", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ISRC", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "length", "description": "An approximation to the length of the recording, calculated\nfrom the lengths of the tracks using it.", @@ -2258,6 +2274,16 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "SCALAR", + "name": "ISRC", + "description": "The [International Standard Recording Code](https://musicbrainz.org/doc/ISRC)\n(ISRC) is an identification system for audio and music video recordings. It is\nstandarized by the [IFPI](http://www.ifpi.org/) in ISO 3901:2001 and used by\nIFPI members to assign a unique identifier to every distinct sound recording\nthey release. An ISRC identifies a particular [sound recording](https://musicbrainz.org/doc/Recording),\nnot the song itself. Therefore, different recordings, edits, remixes and\nremasters of the same song will each be assigned their own ISRC. However, note\nthat same recording should carry the same ISRC in all countries/territories.\nSongs are identified by analogous [International Standard Musical Work Codes](https://musicbrainz.org/doc/ISWC)\n(ISWCs).", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "ENUM", "name": "ReleaseGroupType", @@ -7103,6 +7129,16 @@ "ofType": null }, "defaultValue": null + }, + { + "name": "isrc", + "description": "The [International Standard Recording Code](https://musicbrainz.org/doc/ISRC)\n(ISRC) of the recording.", + "type": { + "kind": "SCALAR", + "name": "ISRC", + "ofType": null + }, + "defaultValue": null } ], "type": { @@ -7244,6 +7280,16 @@ } }, "defaultValue": null + }, + { + "name": "discID", + "description": "A [disc ID](https://musicbrainz.org/doc/Disc_ID)\nassociated with the release.", + "type": { + "kind": "SCALAR", + "name": "DiscID", + "ofType": null + }, + "defaultValue": null } ], "type": { @@ -7374,6 +7420,16 @@ "ofType": null }, "defaultValue": null + }, + { + "name": "iswc", + "description": "The [International Standard Musical Work Code](https://musicbrainz.org/doc/ISWC)\n(ISWC) of the work.", + "type": { + "kind": "SCALAR", + "name": "ISWC", + "ofType": null + }, + "defaultValue": null } ], "type": { @@ -7496,6 +7552,26 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "SCALAR", + "name": "DiscID", + "description": "[Disc ID](https://musicbrainz.org/doc/Disc_ID) is the code\nnumber which MusicBrainz uses to link a physical CD to a [release](https://musicbrainz.org/doc/Release)\nlisting.\n\nA release may have any number of disc IDs, and a disc ID may be linked to\nmultiple releases. This is because disc ID calculation involves a hash of the\nframe offsets of the CD tracks.\n\nDifferent pressing of a CD often have slightly different frame offsets, and\nhence different disc IDs.\n\nConversely, two different CDs may happen to have exactly the same set of frame\noffsets and hence the same disc ID.", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "ISWC", + "description": "The [International Standard Musical Work Code](https://musicbrainz.org/doc/ISWC)\n(ISWC) is an ISO standard similar to ISBNs for identifying musical works /\ncompositions.", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "SearchQuery", diff --git a/src/loaders.js b/src/loaders.js index 0277ced..c74c4ca 100644 --- a/src/loaders.js +++ b/src/loaders.js @@ -28,6 +28,22 @@ export default function createLoaders (client) { // is elsewhere in the code. entity._type = entityType entity._inc = params.inc + if (entityType === 'discid' && entity.releases) { + entity.releases.forEach(release => { + release._type = 'release' + release._inc = params.inc + }) + } else if (entityType === 'isrc' && entity.recordings) { + entity.recordings.forEach(recording => { + recording._type = 'recording' + recording._inc = params.inc + }) + } else if (entityType === 'iswc' && entity.works) { + entity.works.forEach(work => { + work._type = 'work' + work._inc = params.inc + }) + } } return entity }) diff --git a/src/queries/browse.js b/src/queries/browse.js index 3110358..85ff3cb 100644 --- a/src/queries/browse.js +++ b/src/queries/browse.js @@ -6,6 +6,9 @@ import { AreaConnection, ArtistConnection, EventConnection, + DiscID, + ISRC, + ISWC, LabelConnection, PlaceConnection, RecordingConnection, @@ -93,7 +96,12 @@ entity.`, recordings: createBrowseField(RecordingConnection, { artist, collection, - release + release, + isrc: { + type: ISRC, + description: `The [International Standard Recording Code](https://musicbrainz.org/doc/ISRC) +(ISRC) of the recording.` + } }), releases: createBrowseField(ReleaseConnection, { area, @@ -115,7 +123,12 @@ release, but is not included in the credits for the release itself.` recording, releaseGroup, type: releaseGroupType, - status: releaseStatus + status: releaseStatus, + discID: { + type: DiscID, + description: `A [disc ID](https://musicbrainz.org/doc/Disc_ID) +associated with the release.` + } }), releaseGroups: createBrowseField(ReleaseGroupConnection, { artist, @@ -125,7 +138,12 @@ release, but is not included in the credits for the release itself.` }), works: createBrowseField(WorkConnection, { artist, - collection + collection, + iswc: { + type: ISWC, + description: `The [International Standard Musical Work Code](https://musicbrainz.org/doc/ISWC) +(ISWC) of the work.` + } }) } }) diff --git a/src/resolvers.js b/src/resolvers.js index 4968ee6..f75cfba 100644 --- a/src/resolvers.js +++ b/src/resolvers.js @@ -41,6 +41,7 @@ export function includeSubqueries (params, info, fragments = info.fragments) { aliases: 'aliases', artistCredit: 'artist-credits', artistCredits: 'artist-credits', + isrcs: 'isrcs', tags: 'tags' } let fields = getFields(info, fragments) @@ -79,6 +80,9 @@ export function resolveBrowse (root, { after, type = [], status = [], + discID, + isrc, + iswc, ...args }, { loaders }, info) { const pluralName = toDashed(info.fieldName) @@ -95,13 +99,23 @@ export function resolveBrowse (root, { const formatParam = value => value.toLowerCase().replace(/ /g, '') params.type = params.type.map(formatParam) params.status = params.status.map(formatParam) - return loaders.browse.load([singularName, params]).then(list => { + let request + if (discID) { + request = loaders.lookup.load(['discid', discID, params]) + } else if (isrc) { + request = loaders.lookup.load(['isrc', isrc, params]) + } else if (iswc) { + request = loaders.lookup.load(['iswc', iswc, params]) + } else { + request = loaders.browse.load([singularName, params]) + } + return request.then(list => { // Grab the list, offet, and count from the response and use them to build // a Relay connection object. const { [pluralName]: arraySlice, - [`${singularName}-offset`]: sliceStart, - [`${singularName}-count`]: arrayLength + [`${singularName}-offset`]: sliceStart = 0, + [`${singularName}-count`]: arrayLength = arraySlice.length } = list const meta = { sliceStart, arrayLength } return { diff --git a/src/types/index.js b/src/types/index.js index afeb92f..d6e9ca4 100644 --- a/src/types/index.js +++ b/src/types/index.js @@ -1,4 +1,4 @@ -export { MBID, DateType, IPI, URLString } from './scalars' +export { DateType, DiscID, IPI, ISRC, ISWC, MBID, URLString } from './scalars' export { ReleaseGroupType, ReleaseStatus } from './enums' export { default as Node } from './node' export { default as Entity, EntityConnection } from './entity' diff --git a/src/types/recording.js b/src/types/recording.js index 47119fc..a6fa506 100644 --- a/src/types/recording.js +++ b/src/types/recording.js @@ -1,6 +1,12 @@ -import { GraphQLObjectType, GraphQLInt, GraphQLBoolean } from 'graphql/type' +import { + GraphQLObjectType, + GraphQLList, + GraphQLInt, + GraphQLBoolean +} from 'graphql/type' import Node from './node' import Entity from './entity' +import { ISRC } from './scalars' import { id, mbid, @@ -39,6 +45,11 @@ or mixing.`, aliases, artistCredit, artistCredits, + isrcs: { + type: new GraphQLList(ISRC), + description: `A list of [International Standard Recording Codes](https://musicbrainz.org/doc/ISRC) +(ISRCs) for this recording.` + }, length: { type: GraphQLInt, description: `An approximation to the length of the recording, calculated diff --git a/src/types/scalars.js b/src/types/scalars.js index 1f1934f..676eb49 100644 --- a/src/types/scalars.js +++ b/src/types/scalars.js @@ -65,6 +65,23 @@ export const Degrees = createScalar({ description: 'Decimal degrees, used for latitude and longitude.' }) +export const DiscID = createScalar({ + name: 'DiscID', + description: `[Disc ID](https://musicbrainz.org/doc/Disc_ID) is the code +number which MusicBrainz uses to link a physical CD to a [release](https://musicbrainz.org/doc/Release) +listing. + +A release may have any number of disc IDs, and a disc ID may be linked to +multiple releases. This is because disc ID calculation involves a hash of the +frame offsets of the CD tracks. + +Different pressing of a CD often have slightly different frame offsets, and +hence different disc IDs. + +Conversely, two different CDs may happen to have exactly the same set of frame +offsets and hence the same disc ID.` +}) + export const Duration = createScalar({ name: 'Duration', description: 'A length of time, in milliseconds.', @@ -92,6 +109,20 @@ export const ISNI = createScalar({ contributors to media content.` }) +export const ISRC = createScalar({ + name: 'ISRC', + description: `The [International Standard Recording Code](https://musicbrainz.org/doc/ISRC) +(ISRC) is an identification system for audio and music video recordings. It is +standarized by the [IFPI](http://www.ifpi.org/) in ISO 3901:2001 and used by +IFPI members to assign a unique identifier to every distinct sound recording +they release. An ISRC identifies a particular [sound recording](https://musicbrainz.org/doc/Recording), +not the song itself. Therefore, different recordings, edits, remixes and +remasters of the same song will each be assigned their own ISRC. However, note +that same recording should carry the same ISRC in all countries/territories. +Songs are identified by analogous [International Standard Musical Work Codes](https://musicbrainz.org/doc/ISWC) +(ISWCs).` +}) + export const ISWC = createScalar({ name: 'ISWC', description: `The [International Standard Musical Work Code](https://musicbrainz.org/doc/ISWC) diff --git a/test/fixtures/7fccf49f79de855cc3b56a8501c9c858 b/test/fixtures/7fccf49f79de855cc3b56a8501c9c858 new file mode 100644 index 0000000..2bbc7be --- /dev/null +++ b/test/fixtures/7fccf49f79de855cc3b56a8501c9c858 @@ -0,0 +1 @@ +{"isrc":"USSUB0200002","recordings":[{"length":168293,"disambiguation":"","id":"b2e623ea-378b-4479-bb75-fa202aacbfc9","video":false,"title":"About a Girl","isrcs":["USSUB0200002","USUG10200084"]}]} \ No newline at end of file diff --git a/test/fixtures/7fccf49f79de855cc3b56a8501c9c858.headers b/test/fixtures/7fccf49f79de855cc3b56a8501c9c858.headers new file mode 100644 index 0000000..0b6937c --- /dev/null +++ b/test/fixtures/7fccf49f79de855cc3b56a8501c9c858.headers @@ -0,0 +1,27 @@ +{ + "statusCode": 200, + "headers": { + "date": "Sun, 11 Dec 2016 20:55:38 GMT", + "content-type": "application/json; charset=utf-8", + "content-length": "197", + "connection": "keep-alive", + "keep-alive": "timeout=15", + "x-ratelimit-limit": "700", + "x-ratelimit-remaining": "181", + "x-ratelimit-reset": "1481489738", + "server": "Plack::Handler::Starlet", + "etag": "\"a025a168fc0d9a2e49b1a5078e300152\"", + "access-control-allow-origin": "*" + }, + "url": "http://musicbrainz.org:80/ws/2/isrc/USSUB0200002?inc=isrcs&fmt=json", + "time": 403, + "request": { + "method": "GET", + "headers": { + "User-Agent": "graphbrainz/4.1.0 ( 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/8a853c2a895ba99685924721d8db37d7 b/test/fixtures/8a853c2a895ba99685924721d8db37d7 new file mode 100644 index 0000000..d890344 Binary files /dev/null and b/test/fixtures/8a853c2a895ba99685924721d8db37d7 differ diff --git a/test/fixtures/8a853c2a895ba99685924721d8db37d7.headers b/test/fixtures/8a853c2a895ba99685924721d8db37d7.headers new file mode 100644 index 0000000..3e47a43 --- /dev/null +++ b/test/fixtures/8a853c2a895ba99685924721d8db37d7.headers @@ -0,0 +1,29 @@ +{ + "statusCode": 200, + "headers": { + "date": "Sun, 11 Dec 2016 20:55:38 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": "177", + "x-ratelimit-reset": "1481489738", + "server": "Plack::Handler::Starlet", + "etag": "W/\"c8f35ec6a4e8478ac6c17f79ef348cf3\"", + "access-control-allow-origin": "*", + "content-encoding": "gzip" + }, + "url": "http://musicbrainz.org:80/ws/2/iswc/T-900.755.682-3?fmt=json", + "time": 397, + "request": { + "method": "GET", + "headers": { + "User-Agent": "graphbrainz/4.1.0 ( 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/9553c1d36a4fbf312310fbc656807dbd b/test/fixtures/9553c1d36a4fbf312310fbc656807dbd new file mode 100644 index 0000000..92b5244 Binary files /dev/null and b/test/fixtures/9553c1d36a4fbf312310fbc656807dbd differ diff --git a/test/fixtures/9553c1d36a4fbf312310fbc656807dbd.headers b/test/fixtures/9553c1d36a4fbf312310fbc656807dbd.headers new file mode 100644 index 0000000..e201bad --- /dev/null +++ b/test/fixtures/9553c1d36a4fbf312310fbc656807dbd.headers @@ -0,0 +1,29 @@ +{ + "statusCode": 200, + "headers": { + "date": "Sun, 11 Dec 2016 20:55:38 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": "178", + "x-ratelimit-reset": "1481489738", + "server": "Plack::Handler::Starlet", + "etag": "W/\"8ee2a57a26dbd226aa04be7142f855b9\"", + "access-control-allow-origin": "*", + "content-encoding": "gzip" + }, + "url": "http://musicbrainz.org:80/ws/2/discid/XzPS7vW.HPHsYemQh0HBUGr8vuU-?fmt=json", + "time": 428, + "request": { + "method": "GET", + "headers": { + "User-Agent": "graphbrainz/4.1.0 ( 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/schema.js b/test/schema.js index 3fb855c..521d569 100644 --- a/test/schema.js +++ b/test/schema.js @@ -514,3 +514,68 @@ test('artistCredits is an alias for artistCredit', testData, ` ]) t.deepEqual(releaseGroup.artistCredits, releaseGroup.artistCredit) }) + +test('Recordings can be browsed by isrc', testData, ` + { + browse { + recordings(isrc: "USSUB0200002") { + totalCount + edges { + node { + title + isrcs + } + } + } + } + } +`, (t, data) => { + const recordings = data.browse.recordings.edges.map(edge => edge.node) + t.is(data.browse.recordings.totalCount, 1) + t.deepEqual(recordings, [ + { title: 'About a Girl', isrcs: ['USSUB0200002', 'USUG10200084'] } + ]) +}) + +test('Releases can be browsed by discID', testData, ` + { + browse { + releases(discID: "XzPS7vW.HPHsYemQh0HBUGr8vuU-") { + totalCount + edges { + node { + mbid + title + } + } + } + } + } +`, (t, data) => { + const releases = data.browse.releases.edges.map(edge => edge.node) + t.true(data.browse.releases.totalCount >= 2) + t.true(releases.some(release => release.mbid === '5a6e5ad7-c2bd-3484-a20e-121bf981c883')) + t.true(releases.some(release => release.mbid === '96f6f90e-d831-4f37-bf72-ce2982e459fb')) +}) + +test('Works can be browsed by iswc', testData, ` + { + browse { + works(iswc: "T-900.755.682-3") { + totalCount + edges { + node { + title + iswcs + } + } + } + } + } +`, (t, data) => { + const works = data.browse.works.edges.map(edge => edge.node) + t.is(data.browse.works.totalCount, 1) + t.deepEqual(works, [ + { title: 'Song of the French Partisan', iswcs: ['T-900.755.682-3'] } + ]) +})