package io.delphiplatform.api.v3.rdb.service.apple.music import io.delphiplatform.api.exception.DataLocalizationException import io.delphiplatform.api.v3.rdb.entity.apple.music.* import io.delphiplatform.api.v3.rdb.repository.apple.music.AppleMusicArtistLocalizedRepository import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows import org.mockito.kotlin.clearInvocations import org.mockito.kotlin.mock import org.mockito.kotlin.verify import org.mockito.kotlin.whenever import java.util.* internal class AppleMusicArtistServiceTest { private val repository: AppleMusicArtistLocalizedRepository = mock() private val service = AppleMusicArtistService(repository) private val COUNTRY_CODE = "US" @Test fun test_findArtists_byTwoChartTracks() { val artist1 = createArtist("artist1") val artist2 = createArtist("artist2") val artist3 = createArtist("artist3") val localizedArtist1 = createLocalizedArtist(artist1, COUNTRY_CODE) val localizedArtist2 = createLocalizedArtist(artist2, COUNTRY_CODE) val localizedArtist3 = createLocalizedArtist(artist3, COUNTRY_CODE) val track1 = createTrack("track1", mutableListOf(artist1, artist2)) val track2 = createTrack("track2", mutableListOf(artist2, artist3)) val localizedTrack1 = createLocalizedTrack(track1) val localizedTrack2 = createLocalizedTrack(track2) val chartTrack1 = createAppleMusicChartTrackEntity(track1, localizedTrack1) val chartTrack2 = createAppleMusicChartTrackEntity(track2, localizedTrack2) whenever( repository.findAllById( mutableSetOf(localizedArtist1.id, localizedArtist2.id, localizedArtist3.id) ) ).thenReturn(mutableListOf(localizedArtist1, localizedArtist2, localizedArtist3)) val artistsByTrackId = service.findArtistsByChartTrackEntities( mutableListOf(chartTrack1, chartTrack2) ) Assertions.assertEquals(2, artistsByTrackId.size) Assertions.assertEquals(2, artistsByTrackId.get(localizedTrack1.id)?.size) Assertions.assertEquals(2, artistsByTrackId.get(localizedTrack2.id)?.size) Assertions.assertEquals( mutableListOf(localizedArtist1, localizedArtist2), artistsByTrackId.get(localizedTrack1.id) ) Assertions.assertEquals( mutableListOf(localizedArtist2, localizedArtist3), artistsByTrackId.get(localizedTrack2.id) ) verify(repository).findAllById(mutableSetOf(localizedArtist1.id, localizedArtist2.id, localizedArtist3.id)) } @Test fun test_findArtists_missingLocalization() { val anotherCountryCode = "AU" val artist1 = createArtist("artist1") val artist2 = createArtist("artist2") //track has 2 artists but 'US' localization in created only for #1 val localizedArtist1 = createLocalizedArtist(artist1, COUNTRY_CODE) val track1 = createTrack("track1", mutableListOf(artist1, artist2)) val localizedTrack1 = createLocalizedTrack(track1) val chartTrack1 = createAppleMusicChartTrackEntity(track1, localizedTrack1) val localizedArtistIdsList = mutableSetOf( AppleMusicArtistLocalizedId(artist1.appleMusicArtistId, COUNTRY_CODE), AppleMusicArtistLocalizedId(artist2.appleMusicArtistId, COUNTRY_CODE) ) //mock main query for artists, return 'US' locale only for artist1 whenever( repository.findAllById(localizedArtistIdsList) ).thenReturn(mutableListOf(localizedArtist1)) /* CASE 1 - requested 'US' locale exists for artist1. No locale exists for artist2 */ //mock fallback query that looks for at least some locale for artist2 whenever( repository.findByArtistIds(Collections.singleton(artist2.appleMusicArtistId)) ).thenReturn(emptyList()) //no locale found for artist2 - exception is expected assertThrows { service.findArtistsByChartTrackEntities( mutableListOf(chartTrack1) ) } verify(repository).findAllById(localizedArtistIdsList) verify(repository).findByArtistIds(Collections.singleton(artist2.appleMusicArtistId)) clearInvocations(repository) /* CASE 2 - requested 'US' locale exists for artist1. Only another locale 'AU' exists for artist2 */ //there is only an 'AU' localization for artist #2 val fallbackLocaleForArtist2 = createLocalizedArtist(artist2, anotherCountryCode) //mock fallback query that looks for at least some locale for artist2 whenever( repository.findByArtistIds(Collections.singleton(artist2.appleMusicArtistId)) ).thenReturn(mutableListOf(fallbackLocaleForArtist2)) val artistsByTrackId = service.findArtistsByChartTrackEntities( mutableListOf(chartTrack1) ) Assertions.assertEquals(1, artistsByTrackId.size) val trackArtistsLocalized = artistsByTrackId.get(localizedTrack1.id) Assertions.assertEquals(2, trackArtistsLocalized?.size) val artist1Localized = trackArtistsLocalized?.find { it.id.appleMusicArtistId.equals("artist1") } val artist2Localized = trackArtistsLocalized?.find { it.id.appleMusicArtistId.equals("artist2") } //result - artist1 has locale for 'US' while artist2 has it only for 'AU' Assertions.assertEquals(artist1Localized?.id?.appleMusicCountryId, COUNTRY_CODE) Assertions.assertEquals(artist2Localized?.id?.appleMusicCountryId, anotherCountryCode) verify(repository).findAllById(localizedArtistIdsList) verify(repository).findByArtistIds(Collections.singleton(artist2.appleMusicArtistId)) } private fun createArtist(artistId: String): AppleMusicArtistEntity { val entity = AppleMusicArtistEntity() entity.appleMusicArtistId = artistId return entity } private fun createLocalizedArtist(artist: AppleMusicArtistEntity, countryCode: String): AppleMusicArtistLocalizedEntity { val entity = AppleMusicArtistLocalizedEntity() entity.id = AppleMusicArtistLocalizedId(artist.appleMusicArtistId, countryCode) return entity } private fun createLocalizedTrack(track: AppleMusicTrackEntity): AppleMusicTrackLocalizedEntity { val localizedEntity = AppleMusicTrackLocalizedEntity() localizedEntity.id = AppleMusicTrackLocalizedId(track.appleMusicTrackId, COUNTRY_CODE) localizedEntity.track = track localizedEntity.appleMusicCountryId = COUNTRY_CODE return localizedEntity } private fun createTrack(trackId: String, artists: MutableList): AppleMusicTrackEntity { val trackEntity = AppleMusicTrackEntity() trackEntity.appleMusicTrackId = trackId trackEntity.artists = artists return trackEntity } private fun createAppleMusicChartTrackEntity( track: AppleMusicTrackEntity, localizedTrack: AppleMusicTrackLocalizedEntity ): AppleMusicChartTrackEntity { val chartTrack = AppleMusicChartTrackEntity() chartTrack.appleMusicChartId = "chart1" chartTrack.appleMusicCountryId = COUNTRY_CODE chartTrack.track = track chartTrack.localizedTrack = localizedTrack return chartTrack } }