/*
* Copyright � 2016 TIBCO Software,Inc.All rights reserved.
* http://community.jaspersoft.com/project/jaspermobile-android
*
* Unless you have purchased a commercial license agreement from TIBCO Jaspersoft,
* the following license terms apply:
*
* This program is part of TIBCO Jaspersoft Mobile for Android.
*
* TIBCO Jaspersoft Mobile is free software:you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation,either version 3of the License,or
* (at your option)any later version.
*
* TIBCO Jaspersoft Mobile is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY;without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with TIBCO Jaspersoft Mobile for Android.If not,see
* <http://www.gnu.org/licenses/lgpl>.
*/
package com.jaspersoft.android.jaspermobile.ui.presenter;
import android.support.annotation.NonNull;
import com.jaspersoft.android.jaspermobile.FakePostExecutionThread;
import com.jaspersoft.android.jaspermobile.FakePreExecutionThread;
import com.jaspersoft.android.jaspermobile.domain.PageRequest;
import com.jaspersoft.android.jaspermobile.domain.ReportPage;
import com.jaspersoft.android.jaspermobile.domain.ScreenCapture;
import com.jaspersoft.android.jaspermobile.domain.interactor.report.GetReportMultiPagePropertyCase;
import com.jaspersoft.android.jaspermobile.domain.interactor.report.GetReportPageContentCase;
import com.jaspersoft.android.jaspermobile.domain.interactor.report.GetReportTotalPagesPropertyCase;
import com.jaspersoft.android.jaspermobile.domain.interactor.report.ReloadReportCase;
import com.jaspersoft.android.jaspermobile.domain.interactor.report.RunReportCase;
import com.jaspersoft.android.jaspermobile.domain.interactor.report.UpdateReportCase;
import com.jaspersoft.android.jaspermobile.domain.interactor.resource.SaveScreenCaptureCase;
import com.jaspersoft.android.jaspermobile.network.RequestExceptionHandler;
import com.jaspersoft.android.jaspermobile.ui.contract.RestReportContract;
import com.jaspersoft.android.jaspermobile.ui.page.ReportPageState;
import com.jaspersoft.android.sdk.service.exception.ServiceException;
import com.jaspersoft.android.sdk.service.exception.StatusCodes;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import java.io.File;
import java.io.IOException;
import rx.Observable;
import rx.Subscriber;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
/**
* @author Tom Koptel
* @since 2.3
*/
public class ReportViewPresenterTest {
private static final String REPORT_URI = "my/uri";
private static final String PAGE_CONTENT = "page content";
private static final ReportPage PAGE = new ReportPage(PAGE_CONTENT.getBytes(), true);
private static final String CURRENT_PAGE = "10";
private static final String REQUESTED_PAGE = "11";
private static final PageRequest CURRENT_PAGE_REQUEST = new PageRequest.Builder().setUri(REPORT_URI).setRange(CURRENT_PAGE).asHtml().build();
private static final PageRequest NEW_PAGE_REQUEST = new PageRequest.Builder().setUri(REPORT_URI).setRange(REQUESTED_PAGE).asHtml().build();
private static final File SCREEN_CAPTURED_FILE = new File("my_file.jpg");
@Mock
RequestExceptionHandler mExceptionHandler;
@Mock
RestReportContract.View mView;
private ReportViewPresenter presenter;
private FakeGetReportShowControlsPropertyCase mFakeGetReportShowControlsPropertyCase;
private FakeGetReportPageContentCase mFakeGetReportPageContentCase;
private FakeGetReportMultiPagePropertyCase mFakeGetReportMultiPagePropertyCase;
private FakeGetReportTotalPagesPropertyCase mFakeGetReportTotalPagesPropertyCase;
private FakeRunReportCase mFakeRunReportCase;
private FakeUpdateReportCase mFakeUpdateReportCase;
private FakeReloadReportCase mFakeReloadReportCase;
private FakeFlushReportCachesCase mFakeFlushReportCachesCase;
private FakeFlushInputControlsCase mFakeFlushInputControlsCase;
private FakeSaveScreenCaptureCase mFakeSaveScreenCaptureCase;
private ReportPageState mReportPageState;
@Before
public void setUp() throws Exception {
initMocks(this);
setupMocks();
presenter = new ReportViewPresenter(
REPORT_URI,
FakePostExecutionThread.create(),
mExceptionHandler,
mFakeGetReportShowControlsPropertyCase,
mFakeGetReportMultiPagePropertyCase,
mFakeGetReportTotalPagesPropertyCase,
mFakeGetReportPageContentCase,
mFakeRunReportCase,
mFakeUpdateReportCase,
mFakeReloadReportCase,
mFakeFlushReportCachesCase,
mFakeFlushInputControlsCase,
mFakeSaveScreenCaptureCase
);
presenter.injectView(mView);
}
@Test
public void should_handle_screen_capture_error() throws Exception {
when(mExceptionHandler.extractMessage(any(Throwable.class))).thenReturn("Opps!");
when(mFakeSaveScreenCaptureCase.buildUseCaseObservable(any(ScreenCapture.class)))
.thenReturn(Observable.<File>error(new IOException()));
presenter.shareReport(null);
verify(mView).showError("Opps!");
}
@Test
public void should_handle_screen_capture_success() throws Exception {
presenter.shareReport(null);
verify(mView).navigateToAnnotationPage(SCREEN_CAPTURED_FILE);
}
@Test
@SuppressWarnings("unchecked")
public void should_show_filters_page_if_check_for_controls_was_positive() throws Exception {
mFakeGetReportShowControlsPropertyCase.setNeedParams(true);
presenter.init();
verify(mView).showLoading();
verify(mFakeGetReportShowControlsPropertyCase).execute(eq(REPORT_URI), any(Subscriber.class));
verify(mView).setFilterActionVisibility(true);
verify(mView).hideLoading();
verify(mView).showInitialFiltersPage();
}
@Test
@SuppressWarnings("unchecked")
public void should_load_current_page_if_controls_page_shown() throws Exception {
mReportPageState.setControlsPageShown(true);
presenter.init();
verify(mFakeGetReportPageContentCase).execute(eq(CURRENT_PAGE_REQUEST), any(Subscriber.class));
verify(mReportPageState).setCurrentPage(CURRENT_PAGE);
verify(mView).showPage(PAGE_CONTENT);
verify(mFakeGetReportMultiPagePropertyCase).execute(anyString(), any(Subscriber.class));
verify(mFakeGetReportTotalPagesPropertyCase).execute(eq(REPORT_URI), any(Subscriber.class));
}
@Test
@SuppressWarnings("unchecked")
public void should_perform_load_page_action() throws Exception {
PageRequest _10page = new PageRequest.Builder()
.setUri(REPORT_URI)
.setRange("10")
.asHtml()
.build();
presenter.loadPage("10");
verify(mView).showPageLoader(true);
verify(mFakeGetReportPageContentCase).execute(eq(_10page), any(Subscriber.class));
verify(mReportPageState).setRequestedPage("10");
verify(mReportPageState).setCurrentPage("10");
verify(mView).showCurrentPage(10);
verify(mView).showPage(PAGE_CONTENT);
}
@Test
@SuppressWarnings("unchecked")
public void should_perform_run_report_action() throws Exception {
presenter.runReport();
verify(mFakeGetReportTotalPagesPropertyCase).execute(eq(REPORT_URI), any(Subscriber.class));
verify(mView).showLoading();
verify(mReportPageState).setCurrentPage("1");
verify(mView).showCurrentPage(1);
verify(mView).showPage(PAGE_CONTENT);
verify(mView, times(3)).hideLoading(); // we are invoking 2 additional calls during run
verify(mFakeGetReportMultiPagePropertyCase).execute(anyString(), any(Subscriber.class));
}
@Test
@SuppressWarnings("unchecked")
public void should_perform_update_report_action() throws Exception {
presenter.updateReport();
verify(mFakeUpdateReportCase).execute(eq(REPORT_URI), any(Subscriber.class));
verify(mView).resetPaginationControl();
verify(mReportPageState).setCurrentPage("1");
verify(mView).showCurrentPage(1);
verify(mView).showPage(PAGE_CONTENT);
}
@Test
@SuppressWarnings("unchecked")
public void should_perform_refresh_report_action() throws Exception {
presenter.refresh();
PageRequest _1page = new PageRequest.Builder()
.setUri(REPORT_URI)
.setRange("1")
.asHtml()
.build();
verify(mView).showLoading();
verify(mFakeReloadReportCase).execute(eq(_1page), any(Subscriber.class));
verify(mView, times(3)).hideLoading(); // we are invoking 2 additional calls during refresh
verify(mView).resetPaginationControl();
verify(mReportPageState).setCurrentPage("1");
verify(mView).showCurrentPage(1);
verify(mView).showPage(PAGE_CONTENT);
}
@Test
public void should_un_subscribe_from_use_cases_on_destroy_action() throws Exception {
presenter.destroy();
verify(mFakeGetReportShowControlsPropertyCase).unsubscribe();
verify(mFakeGetReportMultiPagePropertyCase).unsubscribe();
verify(mFakeGetReportTotalPagesPropertyCase).unsubscribe();
verify(mFakeGetReportPageContentCase).unsubscribe();
verify(mFakeRunReportCase).unsubscribe();
verify(mFakeUpdateReportCase).unsubscribe();
verify(mFakeReloadReportCase).unsubscribe();
verify(mFakeFlushReportCachesCase).execute(REPORT_URI);
verify(mFakeFlushInputControlsCase).execute(REPORT_URI);
}
@Test
public void should_handle_not_empty_pages_case() throws Exception {
mFakeGetReportTotalPagesPropertyCase.setPages(10);
presenter.loadTotalPagesProperty();
verify(mView).showTotalPages(10);
verify(mView).setSaveActionVisibility(true);
verify(mView).reloadMenu();
verify(mFakeGetReportPageContentCase).execute(eq(CURRENT_PAGE_REQUEST), any(Subscriber.class));
}
@Test
public void should_handle_empty_pages_case() throws Exception {
mFakeGetReportTotalPagesPropertyCase.setPages(0);
presenter.loadTotalPagesProperty();
verify(mView).showEmptyPageMessage();
verify(mView).setSaveActionVisibility(false);
verify(mView).reloadMenu();
}
@Test
public void should_toggle_pagination_control_if_multi_page_loaded() throws Exception {
mFakeGetReportMultiPagePropertyCase.setIsMultiPage(false);
presenter.loadMultiPageProperty();
verify(mView).showPaginationControl(false);
}
@Test
public void should_hide_error_showing_page() throws Exception {
presenter.showPage("1", PAGE);
verify(mView).hideError();
verify(mReportPageState).setCurrentPage("1");
verify(mView).showCurrentPage(1);
verify(mView).showPage(PAGE_CONTENT);
}
@Test
public void should_handle_report_execution_invalidation_case() throws Exception {
ServiceException serviceException = new ServiceException("message", null, StatusCodes.REPORT_EXECUTION_INVALID);
presenter.handleError(serviceException);
verify(mFakeReloadReportCase).execute(eq(NEW_PAGE_REQUEST), any(Subscriber.class));
}
@Test
public void should_handle_report_page_out_of_range_case() throws Exception {
ServiceException serviceException = new ServiceException("message", null, StatusCodes.EXPORT_PAGE_OUT_OF_RANGE);
presenter.handleError(serviceException);
verify(mView).showPageOutOfRangeError();
verify(mFakeGetReportPageContentCase).execute(eq(CURRENT_PAGE_REQUEST), any(Subscriber.class));
}
private void setupMocks() {
ReportPageState state = new ReportPageState();
state.setCurrentPage(CURRENT_PAGE);
state.setRequestedPage(REQUESTED_PAGE);
mReportPageState = spy(state);
mFakeSaveScreenCaptureCase = spy(new FakeSaveScreenCaptureCase());
mFakeGetReportShowControlsPropertyCase = spy(new FakeGetReportShowControlsPropertyCase());
mFakeGetReportPageContentCase = spy(new FakeGetReportPageContentCase());
mFakeGetReportMultiPagePropertyCase = spy(new FakeGetReportMultiPagePropertyCase());
mFakeGetReportTotalPagesPropertyCase = spy(new FakeGetReportTotalPagesPropertyCase());
mFakeRunReportCase = spy(new FakeRunReportCase());
mFakeUpdateReportCase = spy(new FakeUpdateReportCase());
mFakeReloadReportCase = spy(new FakeReloadReportCase());
mFakeFlushReportCachesCase = spy(new FakeFlushReportCachesCase());
mFakeFlushInputControlsCase = spy(new FakeFlushInputControlsCase());
when(mView.getState()).thenReturn(mReportPageState);
}
private static class FakeGetReportTotalPagesPropertyCase extends GetReportTotalPagesPropertyCase {
private int mPages;
public FakeGetReportTotalPagesPropertyCase() {
super(FakePreExecutionThread.create(), FakePostExecutionThread.create(), null, null);
}
public void setPages(int pages) {
mPages = pages;
}
@Override
protected Observable<Integer> buildUseCaseObservable(String reportUri) {
return Observable.just(mPages);
}
}
private static class FakeUpdateReportCase extends UpdateReportCase {
public FakeUpdateReportCase() {
super(FakePreExecutionThread.create(), FakePostExecutionThread.create(), null, null);
}
@Override
protected Observable<ReportPage> buildUseCaseObservable(String reportUri) {
return Observable.just(PAGE);
}
}
private static class FakeRunReportCase extends RunReportCase {
public FakeRunReportCase() {
super(FakePreExecutionThread.create(), FakePostExecutionThread.create(), null, null);
}
@Override
protected Observable<ReportPage> buildUseCaseObservable(String reportUri) {
return Observable.just(PAGE);
}
}
private static class FakeReloadReportCase extends ReloadReportCase {
public FakeReloadReportCase() {
super(FakePreExecutionThread.create(), FakePostExecutionThread.create(), null, null);
}
@Override
protected Observable<ReportPage> buildUseCaseObservable(PageRequest request) {
return Observable.just(PAGE);
}
}
private static class FakeGetReportMultiPagePropertyCase extends GetReportMultiPagePropertyCase {
private boolean mFakeResult;
public FakeGetReportMultiPagePropertyCase() {
super(FakePreExecutionThread.create(), FakePostExecutionThread.create(), null, null);
}
public void setIsMultiPage(boolean fakeResult) {
mFakeResult = fakeResult;
}
@Override
protected Observable<Boolean> buildUseCaseObservable(String reportUri) {
return Observable.just(mFakeResult);
}
}
private static class FakeGetReportPageContentCase extends GetReportPageContentCase {
public FakeGetReportPageContentCase() {
super(FakePreExecutionThread.create(), FakePostExecutionThread.create(), null, null);
}
@Override
protected Observable<ReportPage> buildUseCaseObservable(@NonNull PageRequest request) {
return Observable.just(PAGE);
}
}
private class FakeSaveScreenCaptureCase extends SaveScreenCaptureCase {
public FakeSaveScreenCaptureCase() {
super(FakePreExecutionThread.create(), FakePostExecutionThread.create(), null);
}
@Override
protected Observable<File> buildUseCaseObservable(ScreenCapture capture) {
return Observable.just(
SCREEN_CAPTURED_FILE
);
}
}
}