diff --git a/backend/package.json b/backend/package.json
index ae1d756f..38447c2a 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -50,7 +50,15 @@
"!src/app.js",
"!src/constants/*.js",
"!src/config/*.js"
- ]
+ ],
+ "coverageThreshold": {
+ "global": {
+ "branches": 100,
+ "functions": 100,
+ "lines": 100,
+ "statements": 100
+ }
+ }
},
"standard": {
"parser": "babel-eslint",
diff --git a/backend/src/app.js b/backend/src/app.js
index 9327fef0..5f95b176 100644
--- a/backend/src/app.js
+++ b/backend/src/app.js
@@ -22,7 +22,7 @@ app.use(morgan('combined', { stream: logger.stream }))
const server = http.createServer(app)
const socketio = io(server, { pingTimeout: 30000 })
-const broadcastToAll = (key, message) => Broadcaster.toAllGeneric(socketio, key, message)
+const broadcastToAll = (key, message) => Broadcaster.toAll(socketio, key, message)
const broadcastMopidyStateChange = (online) => Broadcaster.toAllMopidy(socketio, { online })
const allowSocketConnections = (mopidy) => {
Scheduler.scheduleAutoPlayback({ stop: () => mopidy.playback.stop() })
diff --git a/backend/src/constants/message.js b/backend/src/constants/message.js
index 2d5f8d95..4804a8dd 100644
--- a/backend/src/constants/message.js
+++ b/backend/src/constants/message.js
@@ -2,6 +2,7 @@ export default {
GENERIC: 'message',
MOPIDY: 'mopidy',
SEARCH: 'search',
+ IMAGE: 'image',
INCOMING_CORE: 'INCOMING MOPIDY [CORE]',
INCOMING_CLIENT: 'INCOMING CLIENT',
INCOMING_MOPIDY: 'INCOMING MOPIDY',
diff --git a/backend/src/handlers/mopidy/image-cache/index.js b/backend/src/handlers/mopidy/image-cache/index.js
index 58036d16..9752f438 100644
--- a/backend/src/handlers/mopidy/image-cache/index.js
+++ b/backend/src/handlers/mopidy/image-cache/index.js
@@ -13,30 +13,20 @@ const expiresDate = (imgs) => {
return new Date(today.getTime() + (day * 30))
}
-const addToCacheHandler = (encodedKey) => {
- const handler = (data) => {
- const uri = encodedKey.split('#')[1]
-
- return Image.create({
- expireAt: expiresDate(data[uri]),
- uri: encodedKey,
- data
- })
- }
- return handler
-}
+const storeImage = (uri, data) => Image.create({ expireAt: expiresDate(data[uri]), uri, data })
+const addToCacheHandler = (uri) => (data) => storeImage(uri, data)
const ImageCache = {
check: (key, data) => new Promise((resolve) => {
if (!isImageKey(key)) return resolve({ image: false })
- const encodedKey = `${key}#${data[0][0]}`
+ const uri = data[0][0]
- fetchFromCache(encodedKey).then((response) => {
+ fetchFromCache(uri).then((response) => {
if (response) {
- logger.info('Using cache', { key: encodedKey })
+ logger.info('FOUND CACHED IMAGE', { key: uri })
return resolve({ image: response.data })
} else {
- return resolve({ addToCache: addToCacheHandler(encodedKey) })
+ return resolve({ addToCache: addToCacheHandler(uri) })
}
})
})
diff --git a/backend/src/handlers/mopidy/image-cache/index.spec.js b/backend/src/handlers/mopidy/image-cache/index.spec.js
index 98a3fc11..bb858a7b 100644
--- a/backend/src/handlers/mopidy/image-cache/index.spec.js
+++ b/backend/src/handlers/mopidy/image-cache/index.spec.js
@@ -54,7 +54,7 @@ describe('ImageCache', () => {
ImageCache.check('mopidy::library.getImages', [['uri123']])
.then((result) => {
expect(result).toEqual({ image: 'cached123' })
- expect(logger.info).toHaveBeenCalledWith('Using cache', { key: 'mopidy::library.getImages#uri123' })
+ expect(logger.info).toHaveBeenCalledWith('FOUND CACHED IMAGE', { key: 'uri123' })
done()
})
})
diff --git a/backend/src/handlers/mopidy/index.js b/backend/src/handlers/mopidy/index.js
index c42e0655..f29dc0a4 100644
--- a/backend/src/handlers/mopidy/index.js
+++ b/backend/src/handlers/mopidy/index.js
@@ -20,10 +20,6 @@ const isValidTrack = (key, data) => {
return Spotify.validateTrack(data.uri)
}
-const sendToClient = (bcast, ws, payload, data) => {
- bcast.to(ws, payload, data)
-}
-
const logEvent = (headers, params, response, context) => {
EventLogger({ encoded_key: headers.encoded_key }, params, response, context)
}
@@ -39,7 +35,7 @@ const MopidyHandler = (payload, ws, bcast, mopidy) => {
payload.encoded_key, data
).then((obj) => {
if (obj.image) {
- sendToClient(bcast, ws, payload, obj.image)
+ bcast.to(ws, payload, obj.image, MessageType.IMAGE)
} else {
const apiCall = StrToFunction(mopidy, key)
logEvent(payload, data, null, MessageType.OUTGOING_MOPIDY)
@@ -51,7 +47,7 @@ const MopidyHandler = (payload, ws, bcast, mopidy) => {
if (obj.addToCache) obj.addToCache(response)
}
- sendToClient(bcast, ws, payload, response)
+ bcast.to(ws, payload, response)
}
(data ? apiCall(data) : apiCall())
@@ -61,7 +57,7 @@ const MopidyHandler = (payload, ws, bcast, mopidy) => {
})
}).catch((err) => {
payload.encoded_key = Mopidy.VALIDATION_ERROR
- sendToClient(bcast, ws, payload, err.message)
+ bcast.to(ws, payload, err.message)
})
}
diff --git a/backend/src/handlers/mopidy/index.spec.js b/backend/src/handlers/mopidy/index.spec.js
index c1a8b743..748a7bbe 100644
--- a/backend/src/handlers/mopidy/index.spec.js
+++ b/backend/src/handlers/mopidy/index.spec.js
@@ -202,7 +202,7 @@ describe('MopidyHandler', () => {
const mopidy = 'mopidy'
const payload = { encoded_key: 'mopidy::library.getImages', data: [['12345zsdf23456']] }
const trackMock = jest.fn().mockResolvedValue()
- const cacheMock = jest.fn().mockResolvedValue({ image: 'image' })
+ const cacheMock = jest.fn().mockResolvedValue({ image: 'cachedImageData' })
jest.spyOn(Spotify, 'validateTrack').mockImplementation(trackMock)
jest.spyOn(ImageCache, 'check').mockImplementation(cacheMock)
@@ -215,6 +215,7 @@ describe('MopidyHandler', () => {
expect(broadcastMock).toHaveBeenCalledWith(
ws,
{ data: [['12345zsdf23456']], encoded_key: 'mopidy::library.getImages' },
+ 'cachedImageData',
'image'
)
done()
diff --git a/backend/src/utils/broadcaster/index.js b/backend/src/utils/broadcaster/index.js
index 0c1217d5..f39b4877 100644
--- a/backend/src/utils/broadcaster/index.js
+++ b/backend/src/utils/broadcaster/index.js
@@ -19,7 +19,7 @@ const Broadcaster = {
})
},
- toAllGeneric: (socket, key, message) => {
+ toAll: (socket, key, message) => {
const payload = Payload.encodeToJson(key, message)
try {
@@ -37,7 +37,7 @@ const Broadcaster = {
EventLogger({ encoded_key: 'state' }, null, payload, MessageType.OUTGOING_API_ALL)
socket.emit(MessageType.MOPIDY, payload)
} catch (e) {
- logger.error('Broadcaster#toAll', { message: e.message })
+ logger.error('Broadcaster#toAllMopidy', { message: e.message })
}
}
}
diff --git a/backend/src/utils/broadcaster/index.spec.js b/backend/src/utils/broadcaster/index.spec.js
index 14ed505b..12728171 100644
--- a/backend/src/utils/broadcaster/index.spec.js
+++ b/backend/src/utils/broadcaster/index.spec.js
@@ -89,7 +89,7 @@ describe('Broadcaster', () => {
})
})
- describe('#toAllGeneric', () => {
+ describe('#toAll', () => {
it('handles call', () => {
const sendMock = jest.fn()
const socketMock = {
@@ -98,7 +98,7 @@ describe('Broadcaster', () => {
const key = 'mopidy::playback.next'
const message = 'hello mum'
- broadcaster.toAllGeneric(socketMock, key, message)
+ broadcaster.toAll(socketMock, key, message)
expect(sendMock.mock.calls.length).toEqual(1)
expect(sendMock.mock.calls[0][0]).toEqual('message')
expect(sendMock.mock.calls[0][1]).toEqual('{"key":"mopidy::playback.next","data":"hello mum"}')
@@ -116,7 +116,7 @@ describe('Broadcaster', () => {
const key = 'mopidy::playback.next'
const message = 'hello mum'
- broadcaster.toAllGeneric(socketMock, key, message)
+ broadcaster.toAll(socketMock, key, message)
expect(sendMock.mock.calls[0]).toEqual(['message', '{"key":"mopidy::playback.next","data":"hello mum"}'])
expect(logger.error.mock.calls[0][0]).toEqual('Broadcaster#toAll')
expect(logger.error.mock.calls[0][1]).toEqual({ message: 'oops' })
@@ -149,7 +149,7 @@ describe('Broadcaster', () => {
broadcaster.toAllMopidy(socketMock, message)
expect(sendMock.mock.calls[0]).toEqual(['mopidy', '{"online":false}'])
- expect(logger.error.mock.calls[0][0]).toEqual('Broadcaster#toAll')
+ expect(logger.error.mock.calls[0][0]).toEqual('Broadcaster#toAllMopidy')
expect(logger.error.mock.calls[0][1]).toEqual({ message: 'oops' })
})
})
diff --git a/backend/src/utils/track/index.js b/backend/src/utils/track/index.js
index 0a019355..b4e48bdc 100644
--- a/backend/src/utils/track/index.js
+++ b/backend/src/utils/track/index.js
@@ -1,10 +1,25 @@
import Track from 'services/mongodb/models/track'
+import Image from 'services/mongodb/models/image'
import logger from 'config/winston'
export function findTracks (uris) {
return new Promise((resolve, reject) => {
- Track.find({'_id': { $in: uris }})
- .then(tracks => resolve(tracks))
+ Track.find({ _id: { $in: uris } })
+ .then(tracks => {
+ logger.info('FOUND CACHED TRACKS', { keys: uris })
+ return resolve(tracks)
+ })
+ .catch(err => reject(err))
+ })
+}
+
+export function findImages (uris) {
+ return new Promise((resolve, reject) => {
+ Image.find({ uri: { $in: uris } })
+ .then(images => {
+ logger.info('FOUND CACHED IMAGES', { keys: uris })
+ return resolve(images)
+ })
.catch(err => reject(err))
})
}
@@ -30,4 +45,4 @@ export function addTracks (uris, user) {
})
}
-export default { findTracks, addTracks }
+export default { findTracks, findImages, addTracks }
diff --git a/backend/src/utils/track/index.spec.js b/backend/src/utils/track/index.spec.js
index abe1a5b5..11d2d033 100644
--- a/backend/src/utils/track/index.spec.js
+++ b/backend/src/utils/track/index.spec.js
@@ -1,8 +1,10 @@
-import { findTracks, addTracks } from './index'
+import { findTracks, addTracks, findImages } from './index'
import Track from 'services/mongodb/models/track'
+import Image from 'services/mongodb/models/image'
import logger from 'config/winston'
jest.mock('config/winston')
jest.mock('services/mongodb/models/track')
+jest.mock('services/mongodb/models/image')
const userObject = {
_id: '999',
@@ -10,11 +12,11 @@ const userObject = {
}
describe('trackUtils', () => {
- describe('#findTracks', () => {
- afterEach(() => {
- jest.clearAllMocks()
- })
+ afterEach(() => {
+ jest.clearAllMocks()
+ })
+ describe('#findTracks', () => {
it('makes a call to findOne Track document', () => {
expect.assertions(1)
Track.find.mockResolvedValue([{ _id: '123' }])
@@ -36,6 +38,28 @@ describe('trackUtils', () => {
})
})
+ describe('#findImages', () => {
+ it('makes a call to findImages', () => {
+ expect.assertions(1)
+ Image.find.mockResolvedValue([{ _id: '123' }])
+ return findImages('123').then(() => {
+ expect(Image.find).toHaveBeenCalledWith({
+ uri: {
+ $in: '123'
+ }
+ })
+ })
+ })
+
+ it('handles errors', () => {
+ expect.assertions(1)
+ Image.find.mockRejectedValue(new Error('bang'))
+ return findImages('uri123').catch((error) => {
+ expect(error.message).toEqual('bang')
+ })
+ })
+ })
+
describe('#addTrack', () => {
const trackObject = { trackUri: '123' }
const fakeDate = new Date(1222222224332)
diff --git a/backend/src/utils/transformer/index.js b/backend/src/utils/transformer/index.js
index 8b94726b..992fab87 100644
--- a/backend/src/utils/transformer/index.js
+++ b/backend/src/utils/transformer/index.js
@@ -84,9 +84,12 @@ const Transform = {
clearSetTimeout(recommendTimer)
if (data && data.length > 0) return resolve(TransformTrack(data[0].track))
return resolve()
+ case Mopidy.LIBRARY_GET_IMAGES:
+ const uri = Object.keys(data)[0]
+ const image = data[uri][0].uri
+ return resolve({ [uri]: image })
case Mopidy.TRACKLIST_CLEAR:
case Mopidy.CONNECTION_ERROR:
- case Mopidy.LIBRARY_GET_IMAGES:
case Mopidy.MIXER_GET_VOLUME:
case Mopidy.MIXER_SET_VOLUME:
case Mopidy.PLAYBACK_GET_TIME_POSITION:
diff --git a/backend/src/utils/transformer/index.spec.js b/backend/src/utils/transformer/index.spec.js
index d2d75b8e..421fa351 100644
--- a/backend/src/utils/transformer/index.spec.js
+++ b/backend/src/utils/transformer/index.spec.js
@@ -152,9 +152,8 @@ describe('Transformer', () => {
})
describe('event:volumeChanged', () => {
- data = { volume: 99 }
-
it('returns the volume data passed in', () => {
+ data = { volume: 99 }
expect.assertions(1)
return Transformer.mopidyCoreMessage(h('mopidy::event:volumeChanged'), data)
.then(returnData => expect(returnData).toEqual(data.volume))
@@ -162,9 +161,8 @@ describe('Transformer', () => {
})
describe('event:playbackStateChanged', () => {
- data = { new_state: 'playing' }
-
it('returns the playback state data passed in', () => {
+ data = { new_state: 'playing' }
expect.assertions(1)
return Transformer.mopidyCoreMessage(h('mopidy::event:playbackStateChanged'), data)
.then(returnData => expect(returnData).toEqual(data.new_state))
@@ -173,9 +171,15 @@ describe('Transformer', () => {
describe('library.getImages', () => {
it('returns the data passed in', () => {
+ data = {
+ 'spotify123abc': [
+ { uri: 'path/to/img/1' },
+ { uri: 'path/to/img/2' }
+ ]
+ }
expect.assertions(1)
return Transformer.message(h('mopidy::library.getImages'), data)
- .then(returnData => expect(returnData).toEqual(data))
+ .then(returnData => expect(returnData).toEqual({'spotify123abc': 'path/to/img/1'}))
})
})
diff --git a/backend/src/utils/transformer/transformers/mopidy/track/index.js b/backend/src/utils/transformer/transformers/mopidy/track/index.js
index 363d3f0a..ad772cb8 100644
--- a/backend/src/utils/transformer/transformers/mopidy/track/index.js
+++ b/backend/src/utils/transformer/transformers/mopidy/track/index.js
@@ -7,6 +7,10 @@ export default function (json) {
length: json.length || json.duration_ms
}
+ if (json.image) {
+ payload.image = json.image
+ }
+
if (json.album) {
payload.album = {
uri: json.album.uri,
@@ -14,7 +18,7 @@ export default function (json) {
year: json.album.date
}
- if (json.album.images && json.album.images.length > 0) {
+ if (!payload.image && json.album.images && json.album.images.length > 0) {
payload.image = json.album.images[0].url
}
}
diff --git a/backend/src/utils/transformer/transformers/mopidy/track/index.spec.js b/backend/src/utils/transformer/transformers/mopidy/track/index.spec.js
index a0292644..623195b3 100644
--- a/backend/src/utils/transformer/transformers/mopidy/track/index.spec.js
+++ b/backend/src/utils/transformer/transformers/mopidy/track/index.spec.js
@@ -8,11 +8,13 @@ describe('TransformerTrack', () => {
it('transforms the track', () => {
const albumTrack = payload[0]
albumTrack.addedBy = 'duncan'
+ albumTrack.image = 'http://path/to/image'
expect(TransformerTrack(albumTrack)).toEqual({
track: {
uri: 'spotify:track:1yzSSn5Sj1azuo7RgwvDb3',
name: 'No Time for Caution',
+ image: 'http://path/to/image',
year: '2014',
length: 246000,
addedBy: 'duncan',
diff --git a/backend/src/utils/transformer/transformers/mopidy/tracklist/index.js b/backend/src/utils/transformer/transformers/mopidy/tracklist/index.js
index 08da040d..e1c27de8 100644
--- a/backend/src/utils/transformer/transformers/mopidy/tracklist/index.js
+++ b/backend/src/utils/transformer/transformers/mopidy/tracklist/index.js
@@ -1,18 +1,30 @@
import TransformTrack from 'utils/transformer/transformers/mopidy/track'
-import { findTracks } from 'utils/track'
+import { findTracks, findImages } from 'utils/track'
const Tracklist = (json) => {
return new Promise((resolve) => {
const trackUris = json.map(data => data.uri)
+ const imageUris = json.filter(data => data.album).map(data => data.album.uri)
+ const requests = [
+ findTracks(trackUris),
+ findImages(imageUris)
+ ]
- findTracks(trackUris).then(tracks => {
+ Promise.all(requests).then((responses) => {
+ const tracks = responses[0]
+ const images = responses[1]
const decoratedTracks = json.map(data => {
const trackData = tracks.find(track => track._id === data.uri)
+ const imageData = images.find(image => image.uri === (data.album && data.album.uri))
if (trackData) {
data.addedBy = trackData.addedBy.reverse().map(user => user[0])
}
+ if (imageData) {
+ data.image = imageData.data[data.album.uri][0].uri
+ }
+
return TransformTrack(data)
})
diff --git a/backend/src/utils/transformer/transformers/mopidy/tracklist/index.spec.js b/backend/src/utils/transformer/transformers/mopidy/tracklist/index.spec.js
index 90fb3774..091b8b44 100644
--- a/backend/src/utils/transformer/transformers/mopidy/tracklist/index.spec.js
+++ b/backend/src/utils/transformer/transformers/mopidy/tracklist/index.spec.js
@@ -1,6 +1,7 @@
import TransformerTracklist from './index'
import fs from 'fs'
import lolex from 'lolex'
+jest.mock('config/winston')
const firstTrack = {
_id: 'spotify:track:1yzSSn5Sj1azuo7RgwvDb3',
@@ -22,10 +23,22 @@ const secondTrack = {
]],
__v: 0
}
+const firstImage = {
+ _id: '123',
+ uri: 'spotify:album:5OVGwMCexoHavOar6v4al5',
+ data: {
+ 'spotify:album:5OVGwMCexoHavOar6v4al5': [
+ { uri: 'path/to/image/1' },
+ { uri: 'path/to/image/2' }
+ ]
+ }
+}
const mockTrackData = [firstTrack, secondTrack]
+const mockImageData = [firstImage]
jest.mock('utils/track', () => ({
- findTracks: jest.fn().mockImplementation(() => Promise.resolve(mockTrackData))
+ findTracks: jest.fn().mockImplementation(() => Promise.resolve(mockTrackData)),
+ findImages: jest.fn().mockImplementation(() => Promise.resolve(mockImageData))
}))
describe('TransformerTracklist', () => {
@@ -44,8 +57,16 @@ describe('TransformerTracklist', () => {
it('transforms it', () => {
expect.assertions(1)
return TransformerTracklist(payload).then(transformedPayload => {
- expect(transformedPayload).toEqual([{ 'track': { 'addedBy': [{ '_id': '123', 'fullname': 'Big Rainbowhead' }], 'album': { 'name': 'Interstellar: Original Motion Picture Soundtrack (Deluxe Digital Version)', 'uri': 'spotify:album:5OVGwMCexoHavOar6v4al5', 'year': '2014' }, 'artist': { 'name': 'Hans Zimmer', 'uri': 'spotify:artist:0YC192cP3KPCRWx8zr8MfZ' }, 'length': 246000, 'name': 'No Time for Caution', 'uri': 'spotify:track:1yzSSn5Sj1azuo7RgwvDb3', 'year': '2014' } }, { 'track': { 'artist': { 'name': 'Joan Baez', 'uri': 'local:artist:md5:23327ccea5c999183cc88701751f8c73' }, 'composer': { 'name': 'Peter Schickele', 'uri': 'local:artist:md5:af20b04e7ff55f56afec2be1f36afe94' }, 'genre': 'Soundtrack', 'length': 123973, 'name': 'Silent Running', 'uri': 'local:track:Soundtracks/Silent%20Running%20OST/Silent%20Running%20' } }])
+ expect(transformedPayload).toEqual([{ 'track': { 'addedBy': [{ '_id': '123', 'fullname': 'Big Rainbowhead' }], 'album': { 'name': 'Interstellar: Original Motion Picture Soundtrack (Deluxe Digital Version)', 'uri': 'spotify:album:5OVGwMCexoHavOar6v4al5', 'year': '2014' }, 'artist': { 'name': 'Hans Zimmer', 'uri': 'spotify:artist:0YC192cP3KPCRWx8zr8MfZ' }, 'image': 'path/to/image/1', 'length': 246000, 'name': 'No Time for Caution', 'uri': 'spotify:track:1yzSSn5Sj1azuo7RgwvDb3', 'year': '2014' } }, { 'track': { 'artist': { 'name': 'Joan Baez', 'uri': 'local:artist:md5:23327ccea5c999183cc88701751f8c73' }, 'composer': { 'name': 'Peter Schickele', 'uri': 'local:artist:md5:af20b04e7ff55f56afec2be1f36afe94' }, 'genre': 'Soundtrack', 'length': 123973, 'name': 'Silent Running', 'uri': 'local:track:Soundtracks/Silent%20Running%20OST/Silent%20Running%20' } }])
})
})
+
+ it('catches errors', () => {
+ expect.assertions(1)
+ TransformerTracklist('something broke')
+ .catch(err => {
+ expect(err.message).toEqual('json.map is not a function')
+ })
+ })
})
})
diff --git a/frontend/package.json b/frontend/package.json
index 38e53cf0..bb6dce59 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -55,7 +55,15 @@
],
"snapshotSerializers": [
"enzyme-to-json/serializer"
- ]
+ ],
+ "coverageThreshold": {
+ "global": {
+ "branches": 100,
+ "functions": 100,
+ "lines": 100,
+ "statements": 100
+ }
+ }
},
"standard": {
"parser": "babel-eslint",
diff --git a/frontend/src/__mockData__/api/index.js b/frontend/src/__mockData__/api/index.js
index 6ddee72b..fb5d2836 100644
--- a/frontend/src/__mockData__/api/index.js
+++ b/frontend/src/__mockData__/api/index.js
@@ -1,5 +1,5 @@
const api = () => {
- return JSON.parse('[{"track":{"uri":"spotify:track:1yzSSn5Sj1azuo7RgwvDb3","name":"No Time for Caution","length":246000,"start_time":1517488074076,"album":{"uri":"spotify:album:5OVGwMCexoHavOar6v4al5","name":"Interstellar: Original Motion Picture Soundtrack (Deluxe Digital Version)","year":"2014"},"artist":{"uri":"spotify:artist:0YC192cP3KPCRWx8zr8MfZ","name":"Hans Zimmer"},"year":"2014", "addedBy":[{"_id": "123", "fullname": "Big Rainbowhead", "addedAt": "2019-12-17T13:11:37.316Z"}]}},{"track":{"uri":"local:track:Soundtracks/Silent%20Running%20OST/Silent%20Running%20","name":"Silent Running","length":123973,"start_time":1517488674076,"composer":{"uri":"local:artist:md5:af20b04e7ff55f56afec2be1f36afe94","name":"Peter Schickele"},"genre":"Soundtrack","artist":{"uri":"local:artist:md5:23327ccea5c999183cc88701751f8c73","name":"Joan Baez"}}}]')
+ return JSON.parse('[{"track":{"uri":"spotify:track:1yzSSn5Sj1azuo7RgwvDb3","name":"No Time for Caution","length":246000,"start_time":1517488074076,"image":"http://path/to/cool/image.png","album":{"uri":"spotify:album:5OVGwMCexoHavOar6v4al5","name":"Interstellar: Original Motion Picture Soundtrack (Deluxe Digital Version)","year":"2014"},"artist":{"uri":"spotify:artist:0YC192cP3KPCRWx8zr8MfZ","name":"Hans Zimmer"},"year":"2014","addedBy":[{"_id":"123","fullname":"Big Rainbowhead","addedAt":"2019-12-17T13:11:37.316Z"}]}},{"track":{"uri":"spotify:track:1yzSSn5Sj1azuo7Rgwvdunc","name":"Is this sucker going live anytime soon","length":246000,"start_time":1517488074076,"album":{"uri":"spotify:album:5OVGwMCexoHavOar6vdunc","name":"Expectation: Things that may never happen volume 1","year":"2014"},"artist":{"uri":"spotify:artist:0YC192cP3KPCRWx8zrdunc","name":"The chancer"},"year":"2018","addedBy":[{"_id":"666","fullname":"Duncan Robertson","addedAt":"2019-12-17T13:11:37.316Z"}]}},{"track":{"uri":"soundcloud:track:5OVGwMCexoHacompose","name":"Silent Running","length":123973,"start_time":1517488674076,"composer":{"uri":"soundcloud:album:5OVGwMCexoHacompose","name":"Peter Schickele"},"genre":"Soundtrack","artist":{"uri":"soundcloud:artist:5OVGwMCexoHacompose","name":"Joan Baez"}}}]')
}
export default api
diff --git a/frontend/src/actions/index.js b/frontend/src/actions/index.js
index 0246dd22..7c69024e 100644
--- a/frontend/src/actions/index.js
+++ b/frontend/src/actions/index.js
@@ -122,24 +122,17 @@ export const getState = () => {
export const getImage = (uri) => {
return {
- type: Types.SEND,
+ type: Types.IMAGE_REQUEST,
key: MopidyApi.LIBRARY_GET_IMAGES,
params: [[uri]],
uri: uri
}
}
-export const newImage = (uri) => {
- return {
- type: Types.NEW_IMAGE,
- uri
- }
-}
-
-export const resolveImage = (data) => {
+export const resolveImage = (image) => {
return {
type: Types.RESOLVE_IMAGE,
- data
+ image
}
}
diff --git a/frontend/src/actions/index.spec.js b/frontend/src/actions/index.spec.js
index 66803f5d..f1252fbb 100644
--- a/frontend/src/actions/index.spec.js
+++ b/frontend/src/actions/index.spec.js
@@ -131,7 +131,7 @@ describe('actions', () => {
it('should handle getImage', () => {
const uri = 'spotify:track:0c41pMosF5Kqwwegcps8ES'
const expectedAction = {
- type: Types.SEND,
+ type: Types.IMAGE_REQUEST,
key: MopidyApi.LIBRARY_GET_IMAGES,
params: [[uri]],
uri
@@ -139,22 +139,13 @@ describe('actions', () => {
expect(actions.getImage(uri)).toEqual(expectedAction)
})
- it('should handle newImage', () => {
- const uri = 'spotify:track:0c41pMosF5Kqwwegcps8ES'
- const expectedAction = {
- type: Types.NEW_IMAGE,
- uri
- }
- expect(actions.newImage(uri)).toEqual(expectedAction)
- })
-
it('should handle resolveImage', () => {
- const data = 'spotify:track:0c41pMosF5Kqwwegcps8ES'
+ const image = { 'spotify:track:0c41pMosF5Kqwwegcps8ES': 'path/to/image' }
const expectedAction = {
type: Types.RESOLVE_IMAGE,
- data
+ image
}
- expect(actions.resolveImage(data)).toEqual(expectedAction)
+ expect(actions.resolveImage(image)).toEqual(expectedAction)
})
it('should handle getTrackList', () => {
diff --git a/frontend/src/components/current-track/index.spec.js b/frontend/src/components/current-track/index.spec.js
index d60852fb..cb90cffc 100644
--- a/frontend/src/components/current-track/index.spec.js
+++ b/frontend/src/components/current-track/index.spec.js
@@ -44,7 +44,7 @@ describe('CurrentTrack', () => {
describe('composer', () => {
it('renders track', () => {
- track = MockTrackListJson()[1].track
+ track = MockTrackListJson()[2].track
wrapper = shallow(
+
+
+
+ Is this sucker going live anytime soon
+
+
+ The chancer
+
+
+ (
+ 4:06
+ )
+
+
+
+
+
+
+
+
+
+ Is this sucker going live anytime soon
+
+
+ The chancer
+
+
+ (
+ 4:06
+ )
+
+
+
+
+
+
@@ -213,7 +298,51 @@ exports[`Tracklist tracklist but nothing cued up does not mark anything as curre
+
+
+
+ Is this sucker going live anytime soon
+
+
+ The chancer
+
+
+ (
+ 4:06
+ )
+
+
+
+
+
+
- Added:
- 17 Dec 2019 @ 1:11 pm
-
+
+
+
+
+
+
+ 17 Dec 2019 @ 1:11 pm
+
+ -
+ Big Rainbowhead
+
+
+
+
}
disabled={false}
eventsEnabled={true}
@@ -54,6 +70,22 @@ exports[`AddedBy when addedBy information provided and there is play history dis
+
+
+
+
+
+ 17 Dec 2019 @ 1:11 pm
+
+ -
+ Big Rainbowhead2
+
+
+
}
disabled={false}
diff --git a/frontend/src/components/tracklist/added-by/index.js b/frontend/src/components/tracklist/added-by/index.js
index cec075b5..ae6f6962 100644
--- a/frontend/src/components/tracklist/added-by/index.js
+++ b/frontend/src/components/tracklist/added-by/index.js
@@ -3,13 +3,7 @@ import PropTypes from 'prop-types'
import { List, Popup, Icon, Image } from 'semantic-ui-react'
import dateFormat from 'dateformat'
-const firstTime = (user) => {
- if (!user) return 'First time played.'
-
- return Added: {dateFormat(user.addedAt, 'dd mmm yyyy @ h:MM tt')}
-}
-
-const addedByContent = (user, users) => {
+const addedByContent = (users) => {
if (users.length) {
return (
@@ -31,7 +25,7 @@ const addedByContent = (user, users) => {
)
}
- return firstTime(user)
+ return 'First time played.'
}
const userPicture = user => {
@@ -40,14 +34,11 @@ const userPicture = user => {
}
const AddedBy = ({ users = [] }) => {
- const currentUser = users[0]
- const previousUsers = users.slice(0, -1)
-
return (
)
}
diff --git a/frontend/src/components/tracklist/index.js b/frontend/src/components/tracklist/index.js
index a5166743..c9ec3d7e 100644
--- a/frontend/src/components/tracklist/index.js
+++ b/frontend/src/components/tracklist/index.js
@@ -39,8 +39,9 @@ const removeTrack = (uri, cb) => {
const imageChooser = (disabled, track, images, isCurrent, onRemoveTrack, hasBeenPlayed) => {
let image
- if (images && track.album) image = images[track.album.uri]
- if (images && track.composer) image = images[track.composer.uri]
+ if (track.image) image = track.image
+ if (!image && images && track.album) image = images[track.album.uri]
+ if (!image && images && track.composer) image = images[track.composer.uri]
if (!image) image = defaultImage
return trackImage({
diff --git a/frontend/src/components/tracklist/index.spec.js b/frontend/src/components/tracklist/index.spec.js
index 419fd888..23bf19bf 100644
--- a/frontend/src/components/tracklist/index.spec.js
+++ b/frontend/src/components/tracklist/index.spec.js
@@ -61,7 +61,7 @@ describe('Tracklist', () => {
wrapper.find('.item').at(1).find('img').simulate('click')
expect(onRemoveMock.mock.calls.length).toEqual(1)
- expect(onRemoveMock.mock.calls[0][0]).toEqual('local:track:Soundtracks/Silent%20Running%20OST/Silent%20Running%20')
+ expect(onRemoveMock.mock.calls[0][0]).toEqual('spotify:track:1yzSSn5Sj1azuo7Rgwvdunc')
})
})
diff --git a/frontend/src/constants/common.js b/frontend/src/constants/common.js
index 1ac8c08a..8e642c65 100644
--- a/frontend/src/constants/common.js
+++ b/frontend/src/constants/common.js
@@ -7,9 +7,9 @@ export default {
DISCONNECT: 'actionDisconnect',
DISCONNECTED: 'actionDisconnected',
DROP_TYPES: ['__NATIVE_URL__'],
- NEW_IMAGE: 'actionNewImage',
RESOLVE_IMAGE: 'actionResolveImage',
SEND: 'actionSend',
+ IMAGE_REQUEST: 'actionRequestImage',
STORE_TOKEN: 'actionStoreToken',
CLEAR_STORE_TOKEN: 'actionClearStoreToken',
UPDATE_VOLUME: 'actionUpdateVolume',
diff --git a/frontend/src/containers/jukebox-middleware/index.js b/frontend/src/containers/jukebox-middleware/index.js
index 3701884d..d8fcbb45 100644
--- a/frontend/src/containers/jukebox-middleware/index.js
+++ b/frontend/src/containers/jukebox-middleware/index.js
@@ -1,9 +1,7 @@
import io from 'socket.io-client'
import * as actions from 'actions'
-import MopidyApi from 'constants/mopidy-api'
import Constants from 'constants/common'
import SearchConst from 'search/constants'
-import { findImageInCache } from 'utils/images'
import { trackProgressTimer } from 'utils/time'
import onMessageHandler from 'utils/on-message-handler'
import Payload from 'utils/payload'
@@ -15,9 +13,7 @@ const JukeboxMiddleware = (() => {
let progressTimer = null
return store => next => action => {
- const isImageRequest = () => action.key === MopidyApi.LIBRARY_GET_IMAGES
- const imageIsCached = () => findImageInCache(action.uri, store.getState().assets)
- const preStoreImage = () => store.dispatch(actions.newImage(action.uri))
+ const imageIsCached = () => store.getState().assets[action.uri]
const getJWT = () => store.getState().settings.token
const packMessage = () => Payload.encodeToJson(getJWT(store), action.key, action.params)
@@ -34,10 +30,12 @@ const JukeboxMiddleware = (() => {
}
const onClose = _evt => store.dispatch(actions.wsDisconnect())
const onMessage = data => onMessageHandler(store, data, progressTimer)
+ const onImage = data => onMessageHandler(store, data, progressTimer)
const onSearchResults = data => onMessageHandler(store, data, progressTimer)
const onConnect = () => {
if (socket != null) socket.close()
socket = io(url, { transports: ['websocket'] })
+ socket.on('image', onImage)
socket.on('search', onSearchResults)
socket.on('mopidy', mopidyStateChange)
socket.on('message', onMessage)
@@ -57,12 +55,12 @@ const JukeboxMiddleware = (() => {
case Constants.DISCONNECT:
return onDisconnect()
case Constants.SEND:
- if (isImageRequest() && imageIsCached()) return
- if (isImageRequest()) preStoreImage()
-
return socket.emit('message', packMessage())
case SearchConst.SEARCH:
return socket.emit('search', packMessage())
+ case Constants.IMAGE_REQUEST:
+ if (imageIsCached()) return
+ return socket.emit('message', packMessage())
default:
return next(action)
}
diff --git a/frontend/src/containers/jukebox-middleware/index.spec.js b/frontend/src/containers/jukebox-middleware/index.spec.js
index d5f928a9..5f8fbd3d 100644
--- a/frontend/src/containers/jukebox-middleware/index.spec.js
+++ b/frontend/src/containers/jukebox-middleware/index.spec.js
@@ -130,29 +130,31 @@ describe('JukeboxMiddleware', () => {
])
// fetch image not in the cache
- store.clearActions()
+ mockEmit.mockClear()
JukeboxMiddleware(store)(next)({
- type: Constants.SEND,
+ type: Constants.IMAGE_REQUEST,
key: MopidyApi.LIBRARY_GET_IMAGES,
params: 'params',
uri: '12345678'
})
- actions = store.getActions()
- expect(actions).toEqual([{ type: 'actionNewImage', uri: '12345678' }])
+ expect(mockEmit.mock.calls).toEqual([['message', '{"jwt":"token","key":"mopidy::library.getImages","data":"params"}']])
- // fetch image already in the cache
+ // don't fetch image already in the cache
store.clearActions()
+ mockEmit.mockClear()
const imageInStore = mockStore({
- assets: [{ ref: 'imageincache', uri: 'image123' }]
+ assets: { 'imageincache': 'image123' },
+ settings: { token: 'token' }
})
JukeboxMiddleware(imageInStore)(next)({
- type: Constants.SEND,
+ type: Constants.IMAGE_REQUEST,
key: MopidyApi.LIBRARY_GET_IMAGES,
params: 'params',
uri: 'imageincache'
})
actions = store.getActions()
expect(actions).toEqual([])
+ expect(mockEmit.mock.calls).toEqual([])
// send message with params
mockEmit.mockClear()
diff --git a/frontend/src/reducers/assets/index.js b/frontend/src/reducers/assets/index.js
index 0d323dae..0620c6ce 100644
--- a/frontend/src/reducers/assets/index.js
+++ b/frontend/src/reducers/assets/index.js
@@ -1,20 +1,11 @@
import Types from 'constants/common'
-const initalState = []
-const MAX_IMAGES_IN_CACHE = 200
+const initalState = {}
const assets = (state = initalState, action) => {
switch (action.type) {
- case Types.NEW_IMAGE:
- return (state.find(a => action.uri && a.ref === action.uri))
- ? state
- : [ ...state, { ref: action.uri } ]
case Types.RESOLVE_IMAGE:
- return state.map(asset =>
- (action.data[asset.ref] && action.data[asset.ref][0])
- ? { ...asset, uri: action.data[asset.ref][0].uri }
- : asset
- ).slice(0, MAX_IMAGES_IN_CACHE)
+ return { ...state, ...action.image }
default:
return state
}
diff --git a/frontend/src/reducers/assets/index.spec.js b/frontend/src/reducers/assets/index.spec.js
index 45fd231a..cd93299d 100644
--- a/frontend/src/reducers/assets/index.spec.js
+++ b/frontend/src/reducers/assets/index.spec.js
@@ -3,41 +3,27 @@ import Types from 'constants/common'
describe('assets', () => {
it('handles default state', () => {
- expect(reducer(undefined, {})).toEqual([])
- })
-
- it('handles a new image', () => {
- expect(reducer(undefined, {
- type: Types.NEW_IMAGE,
- uri: '123456789asdfghj'
- })).toEqual([{ 'ref': '123456789asdfghj' }])
- })
-
- it('handles a the same image and does not add again', () => {
- expect(reducer([{ 'ref': '123456789asdfghj' }], {
- type: Types.NEW_IMAGE,
- uri: '123456789asdfghj'
- })).toEqual([{ 'ref': '123456789asdfghj' }])
+ expect(reducer(undefined, {})).toEqual({})
})
it('handles a resolving an image', () => {
- const assets = [
- { 'ref': '123456789asdfghj' },
- { 'ref': 'xdskjhdskjdhskjd' }
- ]
- const imageData = {
- '123456789asdfghj': [
- { uri: 'large image' },
- { uri: 'medium image' }
- ]
+ const assets = {
+ 'spotify1': 'path/to/1',
+ 'spotify2': 'path/to/2',
+ 'spotify4': 'path/to/4'
+ }
+ const image = {
+ 'spotify3': 'path/to/3'
}
expect(reducer(assets, {
type: Types.RESOLVE_IMAGE,
- data: imageData
- })).toEqual([
- { 'ref': '123456789asdfghj', 'uri': 'large image' },
- { 'ref': 'xdskjhdskjdhskjd' }
- ])
+ image
+ })).toEqual({
+ spotify1: 'path/to/1',
+ spotify2: 'path/to/2',
+ spotify3: 'path/to/3',
+ spotify4: 'path/to/4'
+ })
})
})
diff --git a/frontend/src/selectors/index.js b/frontend/src/selectors/index.js
index d29ba9d4..5ba1f6bb 100644
--- a/frontend/src/selectors/index.js
+++ b/frontend/src/selectors/index.js
@@ -1,5 +1,4 @@
import { createSelector } from 'reselect'
-import { findImageInCache } from 'utils/images'
const getCurrentTrack = (state) => state.track
const getTrackList = (state) => state.tracklist
@@ -9,7 +8,7 @@ export const getCurrentTrackImageInCache = createSelector(
[getCurrentTrack, getAssets],
(track, cache) => {
if (!track) { return null }
- return findImageInCache(track.album.uri, cache)
+ return track.album.image || cache[track.album.uri]
}
)
@@ -18,7 +17,7 @@ export const getTracklistImagesInCache = createSelector(
(tracklist, cache) => {
const images = {}
tracklist.forEach(track => {
- images[track.album.uri] = findImageInCache(track.album.uri, cache)
+ images[track.album.uri] = track.album.image || cache[track.album.uri]
})
return images
}
diff --git a/frontend/src/selectors/index.spec.js b/frontend/src/selectors/index.spec.js
index a8df32ff..3cd6665c 100644
--- a/frontend/src/selectors/index.spec.js
+++ b/frontend/src/selectors/index.spec.js
@@ -1,11 +1,11 @@
import * as selectors from './index'
describe('selectors', () => {
- const cache = [
- { ref: 'spotify:track:0c41pMosF5Kqwwegcps8ES' },
- { ref: 'spotify:track:0c41pMosF5Kqwweg123455', uri: 'path/to/file' },
- { ref: 'spotify:track:0c41pMosF5Kqwwegxxxxxx', uri: 'path/to/file1' }
- ]
+ const cache = {
+ 'spotify:track:0c41pMosF5Kqwwegcps8ES': null,
+ 'spotify:track:0c41pMosF5Kqwweg123455': 'path/to/file',
+ 'spotify:track:0c41pMosF5Kqwwegxxxxxx': 'path/to/file1'
+ }
describe('getCurrentTrackImageInCache', () => {
const track = { album: { uri: 'spotify:track:0c41pMosF5Kqwweg123455' } }
diff --git a/frontend/src/utils/images/index.js b/frontend/src/utils/images/index.js
deleted file mode 100644
index 315442bf..00000000
--- a/frontend/src/utils/images/index.js
+++ /dev/null
@@ -1,5 +0,0 @@
-export const findImageInCache = (uri, cache) => {
- const index = cache.findIndex(asset => asset.ref === uri)
- if (cache[index]) { return cache[index].uri }
- return null
-}
diff --git a/frontend/src/utils/images/index.spec.js b/frontend/src/utils/images/index.spec.js
deleted file mode 100644
index ec1ecc5c..00000000
--- a/frontend/src/utils/images/index.spec.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import * as images from './index'
-
-describe('images', () => {
- describe('findImageInCache', () => {
- const cache = [
- { ref: 'spotify:track:0c41pMosF5Kqwwegcps8ES' },
- { ref: 'spotify:track:0c41pMosF5Kqwweg123455', uri: 'path/to/file' }
- ]
-
- it('handles correctly finding an image', () => {
- const uri = 'spotify:track:0c41pMosF5Kqwweg123455'
- expect(images.findImageInCache(uri, cache)).toEqual('path/to/file')
- })
-
- it('handles correctly not finding an image', () => {
- const uri = 'spotify:track:xxxxx'
- expect(images.findImageInCache(uri, cache)).toBeNull()
- })
- })
-})
diff --git a/frontend/src/utils/on-message-handler/index.js b/frontend/src/utils/on-message-handler/index.js
index 1e4b1edd..ecc0a77b 100644
--- a/frontend/src/utils/on-message-handler/index.js
+++ b/frontend/src/utils/on-message-handler/index.js
@@ -34,7 +34,9 @@ const imageUriChooser = (track) => {
const addCurrentTrack = (track, store, progress) => {
store.dispatch(actions.addCurrentTrack(track))
- store.dispatch(actions.getImage(imageUriChooser(track)))
+ if (!track.image) {
+ store.dispatch(actions.getImage(imageUriChooser(track)))
+ }
const progressTimer = progress.set(0, track.length)
if (store.getState().jukebox.playbackState === MopidyApi.PLAYING) progressTimer.start()
}
@@ -42,7 +44,9 @@ const addCurrentTrack = (track, store, progress) => {
const addTrackList = (tracklist, store) => {
store.dispatch(actions.addTrackList(tracklist))
tracklist.forEach(item => {
- store.dispatch(actions.getImage(imageUriChooser(item.track)))
+ if (!item.track.image) {
+ store.dispatch(actions.getImage(imageUriChooser(item.track)))
+ }
})
}
diff --git a/frontend/src/utils/on-message-handler/index.spec.js b/frontend/src/utils/on-message-handler/index.spec.js
index 24a192ed..bee2698b 100644
--- a/frontend/src/utils/on-message-handler/index.spec.js
+++ b/frontend/src/utils/on-message-handler/index.spec.js
@@ -37,7 +37,7 @@ describe('onMessageHandler', () => {
it('checks track playing', () => {
const payload = {
data: {
- track: MockTrackListJson()[0].track
+ track: MockTrackListJson()[1].track
},
key: MopidyApi.PLAYBACK_GET_CURRENT_TRACK
}
@@ -55,7 +55,7 @@ describe('onMessageHandler', () => {
expect(actions[1]).toEqual({
key: 'mopidy::library.getImages',
params: [[payload.data.track.album.uri]],
- type: 'actionSend',
+ type: 'actionRequestImage',
uri: payload.data.track.album.uri
})
expect(progressStartMock.mock.calls.length).toEqual(1)
@@ -80,12 +80,7 @@ describe('onMessageHandler', () => {
track: payload.data.track,
type: 'actionAddCurrentTrack'
})
- expect(actions[1]).toEqual({
- key: 'mopidy::library.getImages',
- params: [[payload.data.track.album.uri]],
- type: 'actionSend',
- uri: payload.data.track.album.uri
- })
+ expect(actions.length).toEqual(1)
expect(progressStartMock.mock.calls.length).toEqual(0)
progressStartMock.mockClear()
})
@@ -102,14 +97,14 @@ describe('onMessageHandler', () => {
})
onMessageHandler(store, JSON.stringify(payload), progress)
const actions = store.getActions()
- expect(actions).toEqual([])
+ expect(actions.length).toEqual(0)
expect(progressStartMock.mock.calls.length).toEqual(0)
progressStartMock.mockClear()
})
})
describe('EVENT_TRACK_PLAYBACK_STARTED', () => {
- it('checks track playing', () => {
+ it('checks track playing with image provided in payload', () => {
const payload = {
data: {
track: MockTrackListJson()[0].track
@@ -127,10 +122,33 @@ describe('onMessageHandler', () => {
track: payload.data.track,
type: 'actionAddCurrentTrack'
})
+ expect(actions.length).toEqual(1)
+ expect(progressStartMock.mock.calls.length).toEqual(1)
+ progressStartMock.mockClear()
+ })
+
+ it('checks track playing with no image provided in payload', () => {
+ const payload = {
+ data: {
+ track: MockTrackListJson()[1].track
+ },
+ key: MopidyApi.EVENT_TRACK_PLAYBACK_STARTED
+ }
+ const store = mockStore({
+ jukebox: {
+ playbackState: 'playing'
+ }
+ })
+ onMessageHandler(store, JSON.stringify(payload), progress)
+ const actions = store.getActions()
+ expect(actions[0]).toEqual({
+ track: payload.data.track,
+ type: 'actionAddCurrentTrack'
+ })
expect(actions[1]).toEqual({
key: 'mopidy::library.getImages',
params: [[payload.data.track.album.uri]],
- type: 'actionSend',
+ type: 'actionRequestImage',
uri: payload.data.track.album.uri
})
expect(progressStartMock.mock.calls.length).toEqual(1)
@@ -195,7 +213,7 @@ describe('onMessageHandler', () => {
})
onMessageHandler(store, JSON.stringify(payload), progress)
const actions = store.getActions()
- expect(actions).toEqual([])
+ expect(actions.length).toEqual(0)
expect(progressStartMock.mock.calls.length).toEqual(0)
expect(progressStopMock.mock.calls.length).toEqual(0)
})
@@ -216,16 +234,17 @@ describe('onMessageHandler', () => {
})
expect(actions[1]).toEqual({
key: 'mopidy::library.getImages',
- params: [['spotify:album:5OVGwMCexoHavOar6v4al5']],
- type: 'actionSend',
- uri: 'spotify:album:5OVGwMCexoHavOar6v4al5'
+ params: [['spotify:album:5OVGwMCexoHavOar6vdunc']],
+ type: 'actionRequestImage',
+ uri: 'spotify:album:5OVGwMCexoHavOar6vdunc'
})
expect(actions[2]).toEqual({
key: 'mopidy::library.getImages',
- params: [['local:artist:md5:af20b04e7ff55f56afec2be1f36afe94']],
- type: 'actionSend',
- uri: 'local:artist:md5:af20b04e7ff55f56afec2be1f36afe94'
+ params: [['soundcloud:album:5OVGwMCexoHacompose']],
+ type: 'actionRequestImage',
+ uri: 'soundcloud:album:5OVGwMCexoHacompose'
})
+ expect(actions.length).toEqual(3)
})
})
@@ -233,9 +252,7 @@ describe('onMessageHandler', () => {
it('handles resolving', () => {
const payload = {
key: MopidyApi.LIBRARY_GET_IMAGES,
- data: {
- track: MockTrackListJson()[0].track
- }
+ image: { 'spotify1': 'path/to/url/1' }
}
const store = mockStore({})
onMessageHandler(store, JSON.stringify(payload), progress)