package com.alorma.github.sdk.core.datasource.tags;
import com.alorma.github.sdk.bean.info.RepoInfo;
import com.alorma.github.sdk.core.BeanUtils;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import core.ApiClient;
import core.datasource.RestWrapper;
import core.datasource.SdkItem;
import core.repositories.releases.Release;
import core.repositories.releases.tags.RepositoryTagsService;
import core.repositories.releases.tags.Tag;
import core.repositories.releases.tags.TagsCloudDataSource;
import okhttp3.MediaType;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Response;
import retrofit2.mock.Calls;
import rx.observers.TestSubscriber;
import static com.alorma.github.sdk.core.BeanUtils.SORT_ORDER_ASK;
import static com.alorma.github.sdk.core.BeanUtils.TEST_PAGE;
import static com.alorma.github.sdk.core.BeanUtils.TEST_PAGE2;
import static com.alorma.github.sdk.core.BeanUtils.createRelease1;
import static com.alorma.github.sdk.core.BeanUtils.createRepoInfo1;
import static com.alorma.github.sdk.core.BeanUtils.createTag1;
import static com.alorma.github.sdk.core.BeanUtils.createTag2;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class TagsCloudDataSourceTest {
private TestRestWrapper testRestWrapper;
private TagsCloudDataSource tagsCloudDataSource;
@Mock
private RepositoryTagsService mockRepositoryTagsService;
SdkItem<RepoInfo> sdkItem;
SdkItem<RepoInfo> sdkItemWithPage;
RepoInfo repoInfo;
Call<List<Tag>> tagsCall1;
Response<List<Tag>> tagsResponse1;
Call<List<Tag>> tagsCall2;
Response<List<Tag>> tagsResponse2;
Call<Release> releaseResponse;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
repoInfo = createRepoInfo1();
List<Tag> listTags = new ArrayList<>();
listTags.add(createTag1());
listTags.add(createTag2());
tagsResponse1 = Response.success(listTags);
tagsCall1 = Calls.response(tagsResponse1);
List<Tag> listTagsReverse = new ArrayList<>();
listTagsReverse.add(createTag2());
listTagsReverse.add(createTag1());
tagsResponse2 = Response.success(listTagsReverse);
tagsCall2 = Calls.response(tagsResponse2);
Release release = createRelease1();
releaseResponse = Calls.response(release);
sdkItem = new SdkItem<>(repoInfo);
sdkItemWithPage = new SdkItem<>(TEST_PAGE, repoInfo);
testRestWrapper = new TestRestWrapper();
tagsCloudDataSource = new TagsCloudDataSource(testRestWrapper, SORT_ORDER_ASK);
}
@Test
public void execute_twoTagsAndFirstWithRelease_returnsProperRepositoryTags() {
// Given
when(mockRepositoryTagsService.tags(anyString(), anyString(), anyString()))
.thenReturn(tagsCall1);
when(mockRepositoryTagsService.release(anyString(), anyString(), eq(BeanUtils.TAG_1.TEST_TAG1)))
.thenReturn(releaseResponse);
when(mockRepositoryTagsService.release(anyString(), anyString(), eq(BeanUtils.TAG_2.TEST_TAG2)))
.thenReturn(Calls.response((Release) null));
// When
TestSubscriber<SdkItem<List<Tag>>> subscriber = new TestSubscriber<>();
tagsCloudDataSource.execute(sdkItem).subscribe(subscriber);
// Then
subscriber.awaitTerminalEvent();
subscriber.assertNoErrors();
verify(mockRepositoryTagsService)
.tags(BeanUtils.REPO_INFO_1.OWNER, BeanUtils.REPO_INFO_1.REPO, SORT_ORDER_ASK);
verify(mockRepositoryTagsService)
.release(eq(BeanUtils.REPO_INFO_1.OWNER), eq(BeanUtils.REPO_INFO_1.REPO), eq(BeanUtils.TAG_1.TEST_TAG1));
verify(mockRepositoryTagsService)
.release(eq(BeanUtils.REPO_INFO_1.OWNER), eq(BeanUtils.REPO_INFO_1.REPO), eq(BeanUtils.TAG_2.TEST_TAG2));
// Result
List<SdkItem<List<Tag>>> onNextEvents = subscriber.getOnNextEvents();
// was only one call to API
assertEquals(1, onNextEvents.size());
SdkItem<List<Tag>> sdkItem = onNextEvents.get(0);
// we have 2 tags on list
List<Tag> tags = sdkItem.getK();
assertEquals(2, tags.size());
// check tag 1
Tag tag1 = tags.get(0);
Release release1 = tag1.release;
checkRelease1(release1);
// check tag 1
Tag tag2 = tags.get(1);
checkTag2(tag2);
assertNull(tag2.release);
}
@Test
public void execute_twoTagsAndSecondWithRelease_returnsNextPageOfRepositoryTags() {
// Given
when(mockRepositoryTagsService.tags(anyString(), anyString(), eq(TEST_PAGE), anyString()))
.thenReturn(tagsCall2);
when(mockRepositoryTagsService.release(anyString(), anyString(), eq(BeanUtils.TAG_2.TEST_TAG2)))
.thenReturn(releaseResponse);
when(mockRepositoryTagsService.release(anyString(), anyString(), eq(BeanUtils.TAG_1.TEST_TAG1)))
.thenReturn(Calls.response((Release) null));
// When
TestSubscriber<SdkItem<List<Tag>>> subscriber = new TestSubscriber<>();
tagsCloudDataSource.execute(sdkItemWithPage).subscribe(subscriber);
// Then
subscriber.awaitTerminalEvent();
subscriber.assertNoErrors();
verify(mockRepositoryTagsService)
.tags(BeanUtils.REPO_INFO_1.OWNER, BeanUtils.REPO_INFO_1.REPO, TEST_PAGE, SORT_ORDER_ASK);
verify(mockRepositoryTagsService)
.release(eq(BeanUtils.REPO_INFO_1.OWNER), eq(BeanUtils.REPO_INFO_1.REPO), eq(BeanUtils.TAG_2.TEST_TAG2));
verify(mockRepositoryTagsService)
.release(eq(BeanUtils.REPO_INFO_1.OWNER), eq(BeanUtils.REPO_INFO_1.REPO), eq(BeanUtils.TAG_1.TEST_TAG1));
// Result
List<SdkItem<List<Tag>>> onNextEvents = subscriber.getOnNextEvents();
// was only one call to API
assertEquals(1, onNextEvents.size());
SdkItem<List<Tag>> sdkItem = onNextEvents.get(0);
// we have 2 tags on list
List<Tag> tags = sdkItem.getK();
assertEquals(2, tags.size());
assertEquals(TEST_PAGE2, (int) sdkItem.getPage());
// check tag 1
Tag tag2 = tags.get(0);
checkTag2(tag2);
Release release1 = tag2.release;
checkRelease1(release1);
// check tag 2
Tag tag1 = tags.get(1);
assertNull(tag1.release);
checkTag1(tag1);
}
@Test
public void execute_onlyRepositoryInfo_403ForbiddenError() {
// Given
when(mockRepositoryTagsService.tags(anyString(), anyString(), anyString()))
.thenThrow(get403ForbiddenError());
// When
TestSubscriber<SdkItem<List<Tag>>> subscriber = new TestSubscriber<>();
tagsCloudDataSource.execute(sdkItem).subscribe(subscriber);
//Then
subscriber.awaitTerminalEvent();
subscriber.assertError(HttpException.class);
verify(mockRepositoryTagsService)
.tags(BeanUtils.REPO_INFO_1.OWNER, BeanUtils.REPO_INFO_1.REPO, SORT_ORDER_ASK);
verify(mockRepositoryTagsService, never())
.release(anyString(), anyString(), anyString());
}
@Test
public void execute_twoTagsAndFirstWithRelease_IOExceptionOnFetchingReleases() throws IOException {
// Given
when(mockRepositoryTagsService.tags(anyString(), anyString(), anyString()))
.thenReturn(tagsCall1);
when(mockRepositoryTagsService.release(anyString(), anyString(), eq(BeanUtils.TAG_1.TEST_TAG1)))
.thenReturn(Calls.failure(new IOException()));
when(mockRepositoryTagsService.release(anyString(), anyString(), eq(BeanUtils.TAG_2.TEST_TAG2)))
.thenReturn(releaseResponse);
// When
TestSubscriber<SdkItem<List<Tag>>> subscriber = new TestSubscriber<>();
tagsCloudDataSource.execute(sdkItem).subscribe(subscriber);
// Then
subscriber.awaitTerminalEvent();
subscriber.assertNoErrors();
verify(mockRepositoryTagsService)
.tags(BeanUtils.REPO_INFO_1.OWNER, BeanUtils.REPO_INFO_1.REPO, SORT_ORDER_ASK);
verify(mockRepositoryTagsService)
.release(eq(BeanUtils.REPO_INFO_1.OWNER), eq(BeanUtils.REPO_INFO_1.REPO), eq(BeanUtils.TAG_1.TEST_TAG1));
verify(mockRepositoryTagsService)
.release(eq(BeanUtils.REPO_INFO_1.OWNER), eq(BeanUtils.REPO_INFO_1.REPO), eq(BeanUtils.TAG_2.TEST_TAG2));
// Result
List<SdkItem<List<Tag>>> onNextEvents = subscriber.getOnNextEvents();
// was only one call to API
assertEquals(1, onNextEvents.size());
SdkItem<List<Tag>> sdkItem = onNextEvents.get(0);
// we have 2 tags on list
List<Tag> tags = sdkItem.getK();
assertEquals(2, tags.size());
// check tag 1
Tag tag1 = tags.get(0);
assertNull(tag1.release);
checkTag1(tag1);
// check tag 2
Tag tag2 = tags.get(1);
checkRelease1(tag2.release);
checkTag2(tag2);
}
private HttpException get403ForbiddenError() {
return new HttpException(Response.error(403, ResponseBody.create(MediaType.parse("application/json"), "Forbidden")));
}
private void checkTag2(Tag tag2) {
assertEquals(BeanUtils.TAG_2.TEST_TAG2, tag2.getName());
assertEquals(BeanUtils.TAG_2.TEST_TAG2_ZIPBALL, tag2.getZipballUrl());
assertEquals(BeanUtils.TAG_2.TEST_TAG2_TARBALL, tag2.getTarballUrl());
assertEquals(BeanUtils.TAG_2.TEST_TAG2_SHA, tag2.getSha());
assertEquals(BeanUtils.TAG_2.TEST_TAG2_SHA_VALUE, tag2.getSha().getSha());
assertEquals(BeanUtils.TAG_2.TEST_TAG2_SHA_URL, tag2.getSha().getUrl());
}
private void checkTag1(Tag tag1) {
assertEquals(BeanUtils.TAG_1.TEST_TAG1, tag1.getName());
assertEquals(BeanUtils.TAG_1.TEST_TAG1_ZIPBALL, tag1.getZipballUrl());
assertEquals(BeanUtils.TAG_1.TEST_TAG1_TARBALL, tag1.getTarballUrl());
assertEquals(BeanUtils.TAG_1.TEST_TAG1_SHA, tag1.getSha());
assertEquals(BeanUtils.TAG_1.TEST_TAG1_SHA_VALUE, tag1.getSha().getSha());
assertEquals(BeanUtils.TAG_1.TEST_TAG1_SHA_URL, tag1.getSha().getUrl());
}
private void checkRelease1(Release release1) {
assertEquals(BeanUtils.RELEASE_1.ASSET_URL, release1.getAssetsUrl());
assertEquals(BeanUtils.RELEASE_1.UPLOAD_URL, release1.getUploadUrl());
assertEquals(BeanUtils.RELEASE_1.ZIPBALL, release1.getZipballUrl());
assertEquals(BeanUtils.RELEASE_1.TARBALL, release1.getTarballUrl());
}
private class TestRestWrapper extends RestWrapper {
public TestRestWrapper() {
super(null);
}
@Override
protected RepositoryTagsService get(ApiClient apiClient) {
return mockRepositoryTagsService;
}
@Override
public boolean isPaginated(Response response) {
if (isResponse2(response)) return true;
return false;
}
@Override
public Integer getPage(Response response) {
if (isResponse2(response)) return TEST_PAGE2;
return 0;
}
@Override
public Integer getLastPage(Response listResponse) {
return 3;
}
private boolean isResponse2(Response response) {
if (tagsResponse2.equals(response)) {
return true;
}
return false;
}
}
private class HttpException extends RuntimeException {
public HttpException(Response<Object> forbidden) {
}
}
}