From 7c87373542013b3528e0a93203e519e3cef5bf59 Mon Sep 17 00:00:00 2001 From: Trikidou Eleonora Date: Thu, 11 Jul 2024 08:51:23 +0300 Subject: [PATCH 1/3] feat: add files to introduce new functionality --- .../spotify/api/impl/MarketApiRetrofit.java | 59 +++++++++++++++++++ .../spotify/api/interfaces/MarketApi.java | 8 +++ .../java/spotify/api/spotify/SpotifyApi.java | 9 ++- .../factories/RetrofitHttpServiceFactory.java | 4 ++ .../spotify/models/markets/MarketFull.java | 13 ++++ .../retrofit/services/MarketService.java | 12 ++++ 6 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 src/main/java/spotify/api/impl/MarketApiRetrofit.java create mode 100644 src/main/java/spotify/api/interfaces/MarketApi.java create mode 100644 src/main/java/spotify/models/markets/MarketFull.java create mode 100644 src/main/java/spotify/retrofit/services/MarketService.java diff --git a/src/main/java/spotify/api/impl/MarketApiRetrofit.java b/src/main/java/spotify/api/impl/MarketApiRetrofit.java new file mode 100644 index 0000000..4262d78 --- /dev/null +++ b/src/main/java/spotify/api/impl/MarketApiRetrofit.java @@ -0,0 +1,59 @@ +package spotify.api.impl; + +import java.io.IOException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import retrofit2.Call; +import retrofit2.Response; +import spotify.api.enums.HttpStatusCode; +import spotify.api.interfaces.MarketApi; +import spotify.exceptions.HttpRequestFailedException; +import spotify.factories.RetrofitHttpServiceFactory; +import spotify.models.markets.MarketFull; +import spotify.retrofit.services.MarketService; +import spotify.utils.LoggingUtil; +import spotify.utils.ResponseChecker; + + +public class MarketApiRetrofit implements MarketApi { + + private final Logger logger = LoggerFactory.getLogger(MarketApiRetrofit.class); + private final String accessToken; + private final MarketService marketService; + + + public MarketApiRetrofit(final String accessToken) { + this(accessToken, RetrofitHttpServiceFactory.getMarketService()); + } + + public MarketApiRetrofit(final String accessToken, final MarketService marketService) { + this.accessToken = accessToken; + this.marketService = marketService; + } + + + @Override + public MarketFull getMarkets(){ + logger.trace("Constructing HTTP call to fetch markets."); + Call httpCall = marketService.getMarkets("Bearer " + this.accessToken); + + try { + + logger.info("Executing HTTP call to fetch markets"); + logger.debug("Fetching markets...."); + LoggingUtil.logHttpCall(logger, httpCall); + Response response = httpCall.execute(); + + ResponseChecker.throwIfRequestHasNotBeenFulfilledCorrectly(response, HttpStatusCode.OK); + + logger.info("Markets fetched successfully."); + return response.body(); + + } catch (IOException ex) { + logger.error("HTTP request to fetch requested markets has failed."); + throw new HttpRequestFailedException(ex.getMessage()); + } + } +} diff --git a/src/main/java/spotify/api/interfaces/MarketApi.java b/src/main/java/spotify/api/interfaces/MarketApi.java new file mode 100644 index 0000000..2338771 --- /dev/null +++ b/src/main/java/spotify/api/interfaces/MarketApi.java @@ -0,0 +1,8 @@ +package spotify.api.interfaces; + +import spotify.models.markets.MarketFull; + +public interface MarketApi { + MarketFull getMarkets(); + +} \ No newline at end of file diff --git a/src/main/java/spotify/api/spotify/SpotifyApi.java b/src/main/java/spotify/api/spotify/SpotifyApi.java index 0827be3..4f8c854 100644 --- a/src/main/java/spotify/api/spotify/SpotifyApi.java +++ b/src/main/java/spotify/api/spotify/SpotifyApi.java @@ -20,6 +20,7 @@ import spotify.models.episodes.EpisodeFullCollection; import spotify.models.episodes.EpisodeSimplified; import spotify.models.generic.Image; +import spotify.models.markets.MarketFull; import spotify.models.paging.CursorBasedPaging; import spotify.models.paging.Paging; import spotify.models.players.CurrentlyPlayingObject; @@ -62,6 +63,7 @@ public class SpotifyApi { private PersonalizationApi personalizationApi; private PlayerApi playerApi; private SearchApi searchApi; + private MarketApi marketApi; public SpotifyApi(final String accessToken) { this.setup(accessToken); @@ -72,7 +74,6 @@ public void setApis(TrackApi trackApi, AlbumApi albumApi) { this.albumApi = albumApi; } - public TrackFull getTrack(String trackId, Map options) { logger.info("Requesting a track with id {}.", trackId); return trackApi.getTrack(trackId, options); @@ -103,6 +104,11 @@ public AlbumFull getAlbum(String albumId, Map options) { return albumApi.getAlbum(albumId, options); } + public MarketFull getMarket() { + logger.info("Requesting all available markets"); + return marketApi.getMarkets(); + } + public AlbumFullCollection getAlbums(List listOfAlbumIds, Map options) { logger.info("Requesting multiple albums."); return albumApi.getAlbums(listOfAlbumIds, options); @@ -460,5 +466,6 @@ private void setup(final String accessToken) { this.personalizationApi = new PersonalizationApiRetrofit(accessToken); this.playerApi = new PlayerApiRetrofit(accessToken); this.searchApi = new SearchApiRetrofit(accessToken); + this.marketApi = new MarketApiRetrofit(accessToken); } } diff --git a/src/main/java/spotify/factories/RetrofitHttpServiceFactory.java b/src/main/java/spotify/factories/RetrofitHttpServiceFactory.java index 8070f97..50252b7 100644 --- a/src/main/java/spotify/factories/RetrofitHttpServiceFactory.java +++ b/src/main/java/spotify/factories/RetrofitHttpServiceFactory.java @@ -80,4 +80,8 @@ private static T getRetrofitHttpService(final Class serviceClassToBeCreat return httpClient.create(serviceClassToBeCreatedFor); } + + public static MarketService getMarketService() { + return getRetrofitHttpService(MarketService.class, API_BASE_URL_HTTPS_WITH_VERSION); + } } diff --git a/src/main/java/spotify/models/markets/MarketFull.java b/src/main/java/spotify/models/markets/MarketFull.java new file mode 100644 index 0000000..b576da8 --- /dev/null +++ b/src/main/java/spotify/models/markets/MarketFull.java @@ -0,0 +1,13 @@ +package spotify.models.markets; + +import java.util.ArrayList; +import java.util.List; + +public class MarketFull { + + private List markets = new ArrayList() ; + public List getAllMarkets() { + return markets; + + } +} diff --git a/src/main/java/spotify/retrofit/services/MarketService.java b/src/main/java/spotify/retrofit/services/MarketService.java new file mode 100644 index 0000000..282a2ad --- /dev/null +++ b/src/main/java/spotify/retrofit/services/MarketService.java @@ -0,0 +1,12 @@ +package spotify.retrofit.services; + +import retrofit2.Call; +import retrofit2.http.GET; +import retrofit2.http.Header; +import spotify.models.markets.MarketFull; + +public interface MarketService { + @GET("markets") + Call getMarkets(@Header("Authorization") String accessToken); + +} From 59e255da1c8e2d41c32a6ed96b5965b248e58696 Mon Sep 17 00:00:00 2001 From: Trikidou Eleonora Date: Fri, 12 Jul 2024 10:21:18 +0300 Subject: [PATCH 2/3] feat: fix whitespace formatting and adding test for the functionality --- .../spotify/api/impl/MarketApiRetrofit.java | 7 +- .../java/spotify/api/spotify/SpotifyApi.java | 2 +- .../spotify/models/markets/MarketFull.java | 6 +- .../api/impl/MarketApiRetrofitTest.java | 85 +++++++++++++++++++ 4 files changed, 89 insertions(+), 11 deletions(-) create mode 100644 src/test/java/spotify/api/impl/MarketApiRetrofitTest.java diff --git a/src/main/java/spotify/api/impl/MarketApiRetrofit.java b/src/main/java/spotify/api/impl/MarketApiRetrofit.java index 4262d78..542cf05 100644 --- a/src/main/java/spotify/api/impl/MarketApiRetrofit.java +++ b/src/main/java/spotify/api/impl/MarketApiRetrofit.java @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import retrofit2.Call; import retrofit2.Response; import spotify.api.enums.HttpStatusCode; @@ -18,12 +17,10 @@ public class MarketApiRetrofit implements MarketApi { - private final Logger logger = LoggerFactory.getLogger(MarketApiRetrofit.class); private final String accessToken; private final MarketService marketService; - public MarketApiRetrofit(final String accessToken) { this(accessToken, RetrofitHttpServiceFactory.getMarketService()); } @@ -33,15 +30,13 @@ public MarketApiRetrofit(final String accessToken, final MarketService marketSer this.marketService = marketService; } - @Override public MarketFull getMarkets(){ logger.trace("Constructing HTTP call to fetch markets."); Call httpCall = marketService.getMarkets("Bearer " + this.accessToken); try { - - logger.info("Executing HTTP call to fetch markets"); + logger.info("Executing HTTP call to fetch markets."); logger.debug("Fetching markets...."); LoggingUtil.logHttpCall(logger, httpCall); Response response = httpCall.execute(); diff --git a/src/main/java/spotify/api/spotify/SpotifyApi.java b/src/main/java/spotify/api/spotify/SpotifyApi.java index 4f8c854..1a908a6 100644 --- a/src/main/java/spotify/api/spotify/SpotifyApi.java +++ b/src/main/java/spotify/api/spotify/SpotifyApi.java @@ -105,7 +105,7 @@ public AlbumFull getAlbum(String albumId, Map options) { } public MarketFull getMarket() { - logger.info("Requesting all available markets"); + logger.info("Requesting all available markets."); return marketApi.getMarkets(); } diff --git a/src/main/java/spotify/models/markets/MarketFull.java b/src/main/java/spotify/models/markets/MarketFull.java index b576da8..edbb803 100644 --- a/src/main/java/spotify/models/markets/MarketFull.java +++ b/src/main/java/spotify/models/markets/MarketFull.java @@ -1,12 +1,10 @@ package spotify.models.markets; -import java.util.ArrayList; import java.util.List; public class MarketFull { - - private List markets = new ArrayList() ; - public List getAllMarkets() { + private List markets; + public List getMarkets() { return markets; } diff --git a/src/test/java/spotify/api/impl/MarketApiRetrofitTest.java b/src/test/java/spotify/api/impl/MarketApiRetrofitTest.java new file mode 100644 index 0000000..2a69d25 --- /dev/null +++ b/src/test/java/spotify/api/impl/MarketApiRetrofitTest.java @@ -0,0 +1,85 @@ +package spotify.api.impl; + +import okhttp3.MediaType; +import okhttp3.Request; +import okhttp3.ResponseBody; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import retrofit2.Call; +import retrofit2.Response; +import spotify.exceptions.HttpRequestFailedException; +import spotify.exceptions.SpotifyActionFailedException; +import spotify.models.markets.MarketFull; +import spotify.retrofit.services.MarketService; + +import java.io.IOException; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + + +public class MarketApiRetrofitTest extends AbstractApiRetrofitTest { + private MarketApiRetrofit sut; + @Mock + private MarketService mockedMarketService; + @Mock + private Call mockedMarketFullCall; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + + sut = new MarketApiRetrofit(fakeAccessToken, mockedMarketService); + + when(mockedMarketService.getMarkets(anyString())).thenReturn(mockedMarketFullCall); + + when(mockedMarketFullCall.request()).thenReturn(new Request.Builder().url(fakeUrl).build()); + } + + @Test + void getMarketsUsesCorrectValuesToCreatHttpCall() throws IOException { + when(mockedMarketFullCall.execute()).thenReturn(Response.success(new MarketFull())); + + sut.getMarkets(); + verify(mockedMarketService).getMarkets(fakeAccessTokenWithBearer); + } + + @Test + void getMarketsExecutesHttpCall() throws IOException { + when(mockedMarketFullCall.execute()).thenReturn(Response.success(new MarketFull())); + + sut.getMarkets(); + verify(mockedMarketFullCall).execute(); + } + + @Test + void getMarketsThrowsSpotifyActionFailedExceptionWhenError() throws IOException { + when(mockedMarketFullCall.execute()) + .thenReturn( + Response.error( + 400, + ResponseBody.create(MediaType.get("application/json"), getJson("error.json")) + ) + ); + + Assertions.assertThrows(SpotifyActionFailedException.class, () -> sut.getMarkets()); + } + + @Test + void getMarketsThrowsHttpRequestFailedWhenHttpFails() throws IOException { + when(mockedMarketFullCall.execute()).thenThrow(IOException.class); + + Assertions.assertThrows(HttpRequestFailedException.class, () -> sut.getMarkets()); + } + + @Test + void getMarketsReturnsMarketFullWhenSuccessful() throws IOException { + when(mockedMarketFullCall.execute()).thenReturn(Response.success(new MarketFull())); + + Assertions.assertNotNull(sut.getMarkets()); + } +} From bd42c9687a47af11df5b8bf897639f681c352f65 Mon Sep 17 00:00:00 2001 From: Trikidou Eleonora Date: Fri, 12 Jul 2024 11:32:10 +0300 Subject: [PATCH 3/3] feat: get the list of markets where spotify is available. --- .github/PULL_REQUEST_TEMPLATE/pull_request_template.md | 2 +- src/main/java/spotify/models/markets/MarketFull.java | 2 +- src/main/java/spotify/retrofit/services/MarketService.java | 3 +-- src/test/java/spotify/api/impl/MarketApiRetrofitTest.java | 1 - 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md index 85ac1e3..d00c1ba 100644 --- a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -29,4 +29,4 @@ Please describe the tests that you ran to verify your changes. Provide instructi - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes -- [ ] Any dependent changes have been merged and published in downstream modules +- [ ] Any dependent changes have been merged and published in downstream modules \ No newline at end of file diff --git a/src/main/java/spotify/models/markets/MarketFull.java b/src/main/java/spotify/models/markets/MarketFull.java index edbb803..9150100 100644 --- a/src/main/java/spotify/models/markets/MarketFull.java +++ b/src/main/java/spotify/models/markets/MarketFull.java @@ -4,8 +4,8 @@ public class MarketFull { private List markets; + public List getMarkets() { return markets; - } } diff --git a/src/main/java/spotify/retrofit/services/MarketService.java b/src/main/java/spotify/retrofit/services/MarketService.java index 282a2ad..9737045 100644 --- a/src/main/java/spotify/retrofit/services/MarketService.java +++ b/src/main/java/spotify/retrofit/services/MarketService.java @@ -1,8 +1,7 @@ package spotify.retrofit.services; import retrofit2.Call; -import retrofit2.http.GET; -import retrofit2.http.Header; +import retrofit2.http.*; import spotify.models.markets.MarketFull; public interface MarketService { diff --git a/src/test/java/spotify/api/impl/MarketApiRetrofitTest.java b/src/test/java/spotify/api/impl/MarketApiRetrofitTest.java index 2a69d25..6ef3b2d 100644 --- a/src/test/java/spotify/api/impl/MarketApiRetrofitTest.java +++ b/src/test/java/spotify/api/impl/MarketApiRetrofitTest.java @@ -21,7 +21,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; - public class MarketApiRetrofitTest extends AbstractApiRetrofitTest { private MarketApiRetrofit sut; @Mock