package io.delphiplatform.api.v3.rdb.service.spotify import io.delphiplatform.api.v3.model.spotify.ChartTrackMetricsDimension import io.delphiplatform.api.v3.model.spotify.SpotifyChartBreakdown import io.delphiplatform.api.v3.model.spotify.SpotifyChartType import io.delphiplatform.api.v3.model.spotify.SpotifyTrackChartsSearchResult import io.delphiplatform.api.v3.rdb.entity.spotify.SpotifyChartDateTrackKey import io.delphiplatform.api.v3.rdb.entity.spotify.SpotifyChartEntity import io.delphiplatform.api.v3.rdb.entity.spotify.SpotifyChartTrackEntity import io.delphiplatform.api.v3.rdb.entity.spotify.SpotifyChartTrackId import io.delphiplatform.api.v3.view.util.Params import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test import org.mockito.kotlin.mock import org.mockito.kotlin.verify import org.mockito.kotlin.verifyNoMoreInteractions import org.mockito.kotlin.whenever import java.time.LocalDate internal class SpotifyTracksChartRemovalsServiceTest { private val chartTrackService: SpotifyChartTrackService = mock() private val tracksChartService: SpotifyTracksChartsService = mock() private val tracksChartChangesService: SpotifyTracksChartChangesService = mock() private val service = SpotifyTracksChartRemovalsService( chartTrackService, tracksChartService, tracksChartChangesService ) private val date1 = LocalDate.of(2020, 1, 1) private val date2 = LocalDate.of(2020, 1, 2) private val chart1 = "chart1" private val us = "US" private val isrc1 = "isrc1" private val isrc2 = "isrc2" private val track1 = "track1" private val track2 = "track2" private val track3 = "track3" @Test fun test_spotifyChartTracksRemovals_metricsDimensionTrackId() { val requestedDate = date2 val requestedPreviousDate = date1 val defaultDailyPrevDate = requestedDate.minusDays(1) val defaultWeeklyPrevDate = requestedDate.minusDays(7) val inputParams = Params.builder() .chartTrackMetricsDimension(ChartTrackMetricsDimension.TRACK_ID) .trackId(mutableListOf(track1)) .date(requestedDate) .previousDate(requestedPreviousDate) .build() whenever( tracksChartChangesService.getRequestedDateOrDefault( inputParams.date, inputParams.isrc, inputParams.trackId, ) ).thenReturn(requestedDate) whenever( tracksChartChangesService.getDefaultPreviousDateDaily(requestedDate) ).thenReturn(defaultDailyPrevDate) whenever( tracksChartChangesService.getDefaultPreviousDateWeekly(requestedDate) ).thenReturn(defaultWeeklyPrevDate) //track1 exists only for requestedDate and WONT be returned as removal val chartTrack1 = createChartTrack(requestedDate, track1, chart1, isrc1) whenever( chartTrackService.findTrackMetrics( inputParams.trackId, inputParams.isrc, requestedDate, inputParams.minPosition, inputParams.maxPosition, inputParams.minRank, inputParams.maxRank, inputParams.countryCode, inputParams.breakdowns, inputParams.types, inputParams.chartTrackMetricsDimension ) ).thenReturn( mutableListOf( chartTrack1 ) ) //prepare track1 id with date adjusted to requestedPreviousDate, just for mocking needs val excludedCharTrack = SpotifyChartDateTrackKey() excludedCharTrack.chartDate = requestedPreviousDate excludedCharTrack.spotifyChartId = chartTrack1.id.spotifyChartId excludedCharTrack.spotifyTrackId = chartTrack1.spotifyTrackId //track2 exists for requestedPreviousDate and WILL be returned as removal val delta = mutableListOf( createChartTrack(requestedPreviousDate, track2, chart1, isrc1) ) whenever( chartTrackService.findTrackMetricsByDateConsideringChartBreakdown( mutableSetOf(excludedCharTrack), inputParams.trackId, inputParams.isrc, requestedPreviousDate, defaultDailyPrevDate, defaultWeeklyPrevDate, inputParams.minPosition, inputParams.maxPosition, inputParams.minRank, inputParams.maxRank, inputParams.countryCode, inputParams.breakdowns, inputParams.types, inputParams.chartTrackMetricsDimension ) ).thenReturn(delta) val searchResults = mutableListOf(SpotifyTrackChartsSearchResult.builder().build()) whenever( tracksChartService.getSpotifyTrackChartsSearchResults( inputParams.trackStateIncludes, inputParams.chartTrackMetricsDimension, delta ) ).thenReturn(searchResults) val additions = service.getSpotifyChartTracksRemovals(inputParams) verify(chartTrackService).findTrackMetrics( inputParams.trackId, inputParams.isrc, requestedDate, inputParams.minPosition, inputParams.maxPosition, inputParams.minRank, inputParams.maxRank, inputParams.countryCode, inputParams.breakdowns, inputParams.types, inputParams.chartTrackMetricsDimension ) verify(chartTrackService).findTrackMetricsByDateConsideringChartBreakdown( mutableSetOf(excludedCharTrack), inputParams.trackId, inputParams.isrc, requestedPreviousDate, defaultDailyPrevDate, defaultWeeklyPrevDate, inputParams.minPosition, inputParams.maxPosition, inputParams.minRank, inputParams.maxRank, inputParams.countryCode, inputParams.breakdowns, inputParams.types, inputParams.chartTrackMetricsDimension ) verify(tracksChartService).getSpotifyTrackChartsSearchResults( inputParams.trackStateIncludes, inputParams.chartTrackMetricsDimension, delta ) Assertions.assertEquals(searchResults, additions) verifyNoMoreInteractions(tracksChartService, chartTrackService) } @Test fun test_spotifyChartTracksRemovals_metricsDimensionTrackId_emptyPreviousDate() { val requestedDate = date2 val defaultDailyPrevDate = requestedDate.minusDays(1) val defaultWeeklyPrevDate = requestedDate.minusDays(7) val inputParams = Params.builder() .chartTrackMetricsDimension(ChartTrackMetricsDimension.TRACK_ID) .trackId(mutableListOf(track1)) .date(requestedDate) .previousDate(null) .build() whenever( tracksChartChangesService.getRequestedDateOrDefault( inputParams.date, inputParams.isrc, inputParams.trackId, ) ).thenReturn(requestedDate) whenever( tracksChartChangesService.getDefaultPreviousDateDaily(requestedDate) ).thenReturn(defaultDailyPrevDate) whenever( tracksChartChangesService.getDefaultPreviousDateWeekly(requestedDate) ).thenReturn(defaultWeeklyPrevDate) //track1 exists only for requestedDate and WONT be returned as removal val chartTrack1 = createChartTrack(requestedDate, track1, chart1, isrc1) whenever( chartTrackService.findTrackMetrics( inputParams.trackId, inputParams.isrc, requestedDate, inputParams.minPosition, inputParams.maxPosition, inputParams.minRank, inputParams.maxRank, inputParams.countryCode, inputParams.breakdowns, inputParams.types, inputParams.chartTrackMetricsDimension ) ).thenReturn( mutableListOf( chartTrack1 ) ) //prepare track1 id with date adjusted to requestedPreviousDate, just for mocking needs val excludedCharTrack = SpotifyChartDateTrackKey() excludedCharTrack.chartDate = defaultDailyPrevDate excludedCharTrack.spotifyChartId = chartTrack1.id.spotifyChartId excludedCharTrack.spotifyTrackId = chartTrack1.spotifyTrackId //track2 exists for requestedPreviousDate and WILL be returned as removal val delta = mutableListOf( createChartTrack(defaultDailyPrevDate, track2, chart1, isrc1) ) whenever( chartTrackService.findTrackMetricsByDateConsideringChartBreakdown( mutableSetOf(excludedCharTrack), inputParams.trackId, inputParams.isrc, null, defaultDailyPrevDate, defaultWeeklyPrevDate, inputParams.minPosition, inputParams.maxPosition, inputParams.minRank, inputParams.maxRank, inputParams.countryCode, inputParams.breakdowns, inputParams.types, inputParams.chartTrackMetricsDimension ) ).thenReturn(delta) val searchResults = mutableListOf(SpotifyTrackChartsSearchResult.builder().build()) whenever( tracksChartService.getSpotifyTrackChartsSearchResults( inputParams.trackStateIncludes, inputParams.chartTrackMetricsDimension, delta ) ).thenReturn(searchResults) val additions = service.getSpotifyChartTracksRemovals(inputParams) verify(chartTrackService).findTrackMetrics( inputParams.trackId, inputParams.isrc, requestedDate, inputParams.minPosition, inputParams.maxPosition, inputParams.minRank, inputParams.maxRank, inputParams.countryCode, inputParams.breakdowns, inputParams.types, inputParams.chartTrackMetricsDimension ) verify(chartTrackService).findTrackMetricsByDateConsideringChartBreakdown( mutableSetOf(excludedCharTrack), inputParams.trackId, inputParams.isrc, null, defaultDailyPrevDate, defaultWeeklyPrevDate, inputParams.minPosition, inputParams.maxPosition, inputParams.minRank, inputParams.maxRank, inputParams.countryCode, inputParams.breakdowns, inputParams.types, inputParams.chartTrackMetricsDimension ) verify(tracksChartService).getSpotifyTrackChartsSearchResults( inputParams.trackStateIncludes, inputParams.chartTrackMetricsDimension, delta ) Assertions.assertEquals(searchResults, additions) verifyNoMoreInteractions(tracksChartService, chartTrackService) } @Test fun test_spotifyChartTracksRemovals_metricsDimensionIsrc() { val requestedDate = date2 val requestedPreviousDate = date1 val defaultDailyPrevDate = requestedDate.minusDays(1) val defaultWeeklyPrevDate = requestedDate.minusDays(7) val inputParams = Params.builder() .chartTrackMetricsDimension(ChartTrackMetricsDimension.ISRC) .isrc(mutableListOf(isrc1)) .date(requestedDate) .previousDate(requestedPreviousDate) .build() whenever( tracksChartChangesService.getRequestedDateOrDefault( inputParams.date, inputParams.isrc, inputParams.trackId, ) ).thenReturn(requestedDate) whenever( tracksChartChangesService.getDefaultPreviousDateDaily(requestedDate) ).thenReturn(defaultDailyPrevDate) whenever( tracksChartChangesService.getDefaultPreviousDateWeekly(requestedDate) ).thenReturn(defaultWeeklyPrevDate) //track1 exists for requestedDate and WONT be returned as removal val chartTrack1 = createChartTrack(requestedDate, track1, chart1, isrc1) whenever( chartTrackService.findTrackMetrics( inputParams.trackId, inputParams.isrc, requestedDate, inputParams.minPosition, inputParams.maxPosition, inputParams.minRank, inputParams.maxRank, inputParams.countryCode, inputParams.breakdowns, inputParams.types, inputParams.chartTrackMetricsDimension ) ).thenReturn( mutableListOf( chartTrack1 ) ) //prepare track1 id with date adjusted to requestedPreviousDate, just for mocking needs val excludedCharTrack1 = SpotifyChartDateTrackKey() excludedCharTrack1.chartDate = requestedPreviousDate excludedCharTrack1.spotifyChartId = chartTrack1.id.spotifyChartId excludedCharTrack1.spotifyTrackId = chartTrack1.spotifyTrackId //track2 is a 'sibling by isrc' of track1 but 'exists' at requestedPreviousDate val chartTrack2 = createChartTrack(requestedPreviousDate, track2, chart1, isrc1) val excludedCharTrack2 = SpotifyChartDateTrackKey() excludedCharTrack2.chartDate = requestedPreviousDate excludedCharTrack2.spotifyChartId = chartTrack1.id.spotifyChartId excludedCharTrack2.spotifyTrackId = track2 whenever(chartTrackService.findTracksWithSameIsrcWithinChartForDate(mutableSetOf(chartTrack1.chartDateTrackKey), requestedPreviousDate)) .thenReturn(mutableSetOf(chartTrack2)) //track1 exists at requestedPreviousDate //track2 exists at requestedDate but is 'isrc sibling' of track1 //thus both will be excluded val excludedChartTrackIds = mutableSetOf(excludedCharTrack1, excludedCharTrack2) //track3 exists only for requestedDate and WILL be returned as addition val delta = mutableListOf(createChartTrack(requestedPreviousDate, track3, chart1, isrc2)) whenever( chartTrackService.findTrackMetricsByDateConsideringChartBreakdown( excludedChartTrackIds, inputParams.trackId, inputParams.isrc, requestedPreviousDate, defaultDailyPrevDate, defaultWeeklyPrevDate, inputParams.minPosition, inputParams.maxPosition, inputParams.minRank, inputParams.maxRank, inputParams.countryCode, inputParams.breakdowns, inputParams.types, inputParams.chartTrackMetricsDimension ) ).thenReturn(delta) val searchResults = mutableListOf(SpotifyTrackChartsSearchResult.builder().build()) whenever( tracksChartService.getSpotifyTrackChartsSearchResults( inputParams.trackStateIncludes, inputParams.chartTrackMetricsDimension, delta ) ).thenReturn(searchResults) val additions = service.getSpotifyChartTracksRemovals(inputParams) verify(chartTrackService).findTrackMetrics( inputParams.trackId, inputParams.isrc, requestedDate, inputParams.minPosition, inputParams.maxPosition, inputParams.minRank, inputParams.maxRank, inputParams.countryCode, inputParams.breakdowns, inputParams.types, inputParams.chartTrackMetricsDimension ) verify(chartTrackService).findTrackMetricsByDateConsideringChartBreakdown( excludedChartTrackIds, inputParams.trackId, inputParams.isrc, requestedPreviousDate, defaultDailyPrevDate, defaultWeeklyPrevDate, inputParams.minPosition, inputParams.maxPosition, inputParams.minRank, inputParams.maxRank, inputParams.countryCode, inputParams.breakdowns, inputParams.types, inputParams.chartTrackMetricsDimension ) verify(tracksChartService).getSpotifyTrackChartsSearchResults( inputParams.trackStateIncludes, inputParams.chartTrackMetricsDimension, delta ) verify(chartTrackService).findTracksWithSameIsrcWithinChartForDate(mutableSetOf(chartTrack1.chartDateTrackKey), requestedPreviousDate) Assertions.assertEquals(searchResults, additions) verifyNoMoreInteractions(tracksChartService, chartTrackService) } private fun createChartTrack( chartDate: LocalDate, trackId: String, chartId: String = chart1, isrc: String = isrc1 ): SpotifyChartTrackEntity { val spotifyChartTrackEntity = SpotifyChartTrackEntity() val spotifyChartTrackId = SpotifyChartTrackId() spotifyChartTrackId.chartDate = chartDate spotifyChartTrackId.spotifyChartId = chartId spotifyChartTrackId.currentPosition = 10 val spotifyChartDateTrackKey = SpotifyChartDateTrackKey() spotifyChartDateTrackKey.chartDate = chartDate spotifyChartDateTrackKey.spotifyChartId = chartId spotifyChartDateTrackKey.spotifyTrackId = trackId spotifyChartTrackEntity.id = spotifyChartTrackId spotifyChartTrackEntity.chartDateTrackKey = spotifyChartDateTrackKey spotifyChartTrackEntity.spotifyChartId = chartId spotifyChartTrackEntity.spotifyTrackId = trackId spotifyChartTrackEntity.chartDate = chartDate spotifyChartTrackEntity.spotifyCountryId = us spotifyChartTrackEntity.currentPosition = 10 spotifyChartTrackEntity.isExit = false spotifyChartTrackEntity.isEntry = false spotifyChartTrackEntity.isReentry = false spotifyChartTrackEntity.prevPosition = 20 spotifyChartTrackEntity.isrc = isrc spotifyChartTrackEntity.isrcPrevPosition = 15 spotifyChartTrackEntity.chart = SpotifyChartEntity() spotifyChartTrackEntity.chart.spotifyChartId = chartId spotifyChartTrackEntity.chart.spotifyCountryId = us spotifyChartTrackEntity.chart.type = SpotifyChartType.VIRAL spotifyChartTrackEntity.chart.breakdown = SpotifyChartBreakdown.DAILY return spotifyChartTrackEntity } }