diff --git a/packages/core/src/plugins/stream/BandcampPlugin.test.ts b/packages/core/src/plugins/stream/BandcampPlugin.test.ts index 06e59a1c8e..021759f789 100644 --- a/packages/core/src/plugins/stream/BandcampPlugin.test.ts +++ b/packages/core/src/plugins/stream/BandcampPlugin.test.ts @@ -1,4 +1,5 @@ import { BandcampPlugin } from '.'; +import fn = jest.fn; import { Bandcamp } from '../../rest'; import spyOn = jest.spyOn; import { BandcampSearchResult } from '../../rest/Bandcamp'; @@ -15,9 +16,23 @@ describe('Bandcamp plugin tests', () => { artist: 'Artist Name', track: 'Track Name' }; - const trackQuery = 'Track Name'; + const searchTerm = 'Search term for Bandcamp'; + // some of the search result attributes are irrelevant for this test case + const irrelevantSearchResultAttributes = { + url: 'not relevant for this test', + imageUrl: 'not relevant for this test', + tags: [] + }; const bandcampSearch = spyOn(Bandcamp, 'search'); + beforeEach(() => { + spyOn(plugin, 'createSearchTerm') + .mockImplementation(fn(() => searchTerm)); + // 'accept all' matcher + spyOn(plugin, 'createTrackMatcher') + .mockImplementation(fn(query => () => true)); + }); + afterEach(() => { bandcampSearch.mockReset(); }); @@ -27,9 +42,7 @@ describe('Bandcamp plugin tests', () => { type: 'track', artist: 'Artist Name', name: 'Track Name', - url: 'URL', - imageUrl: 'image URL', - tags: [] + ...irrelevantSearchResultAttributes }; bandcampSearch.mockResolvedValueOnce([]) .mockResolvedValueOnce([]) @@ -41,11 +54,11 @@ describe('Bandcamp plugin tests', () => { .resolves.toEqual([matchingSearchResult]); expect(bandcampSearch).toHaveBeenCalledTimes(5); - expect(bandcampSearch).toHaveBeenNthCalledWith(1, trackQuery, 0); - expect(bandcampSearch).toHaveBeenNthCalledWith(2, trackQuery, 1); - expect(bandcampSearch).toHaveBeenNthCalledWith(3, trackQuery, 2); - expect(bandcampSearch).toHaveBeenNthCalledWith(4, trackQuery, 3); - expect(bandcampSearch).toHaveBeenNthCalledWith(5, trackQuery, 4); + expect(bandcampSearch).toHaveBeenNthCalledWith(1, searchTerm, 0); + expect(bandcampSearch).toHaveBeenNthCalledWith(2, searchTerm, 1); + expect(bandcampSearch).toHaveBeenNthCalledWith(3, searchTerm, 2); + expect(bandcampSearch).toHaveBeenNthCalledWith(4, searchTerm, 3); + expect(bandcampSearch).toHaveBeenNthCalledWith(5, searchTerm, 4); }); test('doesn\'t find tracks', async () => { @@ -57,4 +70,64 @@ describe('Bandcamp plugin tests', () => { expect(bandcampSearch).toHaveBeenCalledTimes(5); }); }); + + test('creates search term', () => { + const streamQuery = { + artist: 'Artist Name', + track: 'Track Name' + }; + const searchTerm = plugin.createSearchTerm(streamQuery); + expect(searchTerm).toBe('Artist Name Track Name'); + }); + + test('creates track matcher', () => { + // some of the search result attributes are irrelevant for this test case + const irrelevantSearchResultAttributes = { + url: 'irrelevant for this test', + imageUrl: 'irrelevant for this test', + tags: [] + }; + const streamQuery = { + artist: 'Artist Name', + track: 'Track Name', + ...irrelevantSearchResultAttributes + }; + const matcher = plugin.createTrackMatcher(streamQuery); + const matchingResult: BandcampSearchResult = { + type: 'track', + artist: 'Artist Name', + name: 'Track Name', + ...irrelevantSearchResultAttributes + }; + const searchResults: BandcampSearchResult[] = [ + matchingResult, // first match + { + type: 'album', // the 'album' type shouldn't match + artist: 'irrelevant for this entry', + name: 'irrelevant for this entry', + ...irrelevantSearchResultAttributes + }, + { + type: 'artist', // the 'artist' type shouldn't match + artist: 'irrelevant for this entry', + name: 'irrelevant for this entry', + ...irrelevantSearchResultAttributes + }, + { + type: 'track', + artist: 'Wrong Artist', // artist shouldn't match + name: 'irrelevant for this entry', + ...irrelevantSearchResultAttributes + }, + { + type: 'track', + artist: 'Artist Name', + name: 'Wrong Title', // track name shouldn't match + ...irrelevantSearchResultAttributes + }, + matchingResult // second match + ]; + const tracks = searchResults.filter(matcher); + expect(tracks).toEqual([matchingResult, matchingResult]); + }); }); diff --git a/packages/core/src/plugins/stream/BandcampPlugin.ts b/packages/core/src/plugins/stream/BandcampPlugin.ts index 6e52e4bc3b..651e188796 100644 --- a/packages/core/src/plugins/stream/BandcampPlugin.ts +++ b/packages/core/src/plugins/stream/BandcampPlugin.ts @@ -18,12 +18,11 @@ class BandcampPlugin extends StreamProviderPlugin { const limit = 5; let tracks: BandcampSearchResult[]; + const searchTerm: string = this.createSearchTerm(query); + const isMatchingTrack = this.createTrackMatcher(query); for (let page = 0; page < limit; page++) { - const searchResults = await Bandcamp.search(query.track, page); - tracks = searchResults.filter(item => - item.type === 'track' && - item.artist.toLowerCase() === query.artist.toLowerCase() - ); + const searchResults = await Bandcamp.search(searchTerm, page); + tracks = searchResults.filter(isMatchingTrack); if (tracks.length > 0) { break; } @@ -31,6 +30,19 @@ class BandcampPlugin extends StreamProviderPlugin { return tracks; } + createSearchTerm(query: StreamQuery): string { + return `${query.artist} ${query.track}`; + } + + createTrackMatcher(query: StreamQuery): (item: BandcampSearchResult) => boolean { + const lowerCaseTrack: string = query.track.toLowerCase(); + const lowerCaseArtist: string = query.artist.toLowerCase(); + return (searchResult) => + searchResult.type === 'track' && + searchResult.artist.toLowerCase() === lowerCaseArtist && + searchResult.name.toLowerCase() === lowerCaseTrack; + } + resultToStream(result: BandcampSearchResult, stream: string, duration: number): StreamData { return { source: this.sourceName,