content: /*
   * Copyright 2016, The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package <%= appPackage %>.tasks;
  
  import <%= appPackage %>.data.Task;
  import <%= appPackage %>.data.source.TasksDataSource.LoadTasksCallback;
  import <%= appPackage %>.data.source.TasksRepository;
  import com.google.common.collect.Lists;
  
  import org.junit.Before;
  import org.junit.Test;
  import org.mockito.ArgumentCaptor;
  import org.mockito.Captor;
  import org.mockito.InOrder;
  import org.mockito.Mock;
  import org.mockito.MockitoAnnotations;
  
  import java.util.List;
  
  import static org.junit.Assert.assertTrue;
  import static org.mockito.Matchers.any;
  import static org.mockito.Mockito.inOrder;
  import static org.mockito.Mockito.verify;
  import static org.mockito.Mockito.when;
  
  /**
   * Unit tests for the implementation of {@link TasksPresenter}
   */
  public class TasksPresenterTest {
  
      private static List<Task> TASKS;
  
      @Mock
      private TasksRepository mTasksRepository;
  
      @Mock
      private TasksContract.View mTasksView;
  
      /**
       * {@link ArgumentCaptor} is a powerful Mockito API to capture argument values and use them to
       * perform further actions or assertions on them.
       */
      @Captor
      private ArgumentCaptor<LoadTasksCallback> mLoadTasksCallbackCaptor;
  
      private TasksPresenter mTasksPresenter;
  
      @Before
      public void setupTasksPresenter() {
          // Mockito has a very convenient way to inject mocks by using the @Mock annotation. To
          // inject the mocks in the test the initMocks method needs to be called.
          MockitoAnnotations.initMocks(this);
  
          // Get a reference to the class under test
          mTasksPresenter = new TasksPresenter(mTasksRepository, mTasksView);
  
          // The presenter won't update the view unless it's active.
          when(mTasksView.isActive()).thenReturn(true);
  
          // We start the tasks to 3, with one active and two completed
          TASKS = Lists.newArrayList(new Task("Title1", "Description1"),
                  new Task("Title2", "Description2", true), new Task("Title3", "Description3", true));
      }
  
      @Test
      public void createPresenter_setsThePresenterToView() {
          // Get a reference to the class under test
          mTasksPresenter = new TasksPresenter(mTasksRepository, mTasksView);
  
          // Then the presenter is set to the view
          verify(mTasksView).setPresenter(mTasksPresenter);
      }
  
      @Test
      public void loadAllTasksFromRepositoryAndLoadIntoView() {
          // Given an initialized TasksPresenter with initialized tasks
          // When loading of Tasks is requested
          mTasksPresenter.setFiltering(TasksFilterType.ALL_TASKS);
          mTasksPresenter.loadTasks(true);
  
          // Callback is captured and invoked with stubbed tasks
          verify(mTasksRepository).getTasks(mLoadTasksCallbackCaptor.capture());
          mLoadTasksCallbackCaptor.getValue().onTasksLoaded(TASKS);
  
          // Then progress indicator is shown
          InOrder inOrder = inOrder(mTasksView);
          inOrder.verify(mTasksView).setLoadingIndicator(true);
          // Then progress indicator is hidden and all tasks are shown in UI
          inOrder.verify(mTasksView).setLoadingIndicator(false);
          ArgumentCaptor<List> showTasksArgumentCaptor = ArgumentCaptor.forClass(List.class);
          verify(mTasksView).showTasks(showTasksArgumentCaptor.capture());
          assertTrue(showTasksArgumentCaptor.getValue().size() == 3);
      }
  
      @Test
      public void loadActiveTasksFromRepositoryAndLoadIntoView() {
          // Given an initialized TasksPresenter with initialized tasks
          // When loading of Tasks is requested
          mTasksPresenter.setFiltering(TasksFilterType.ACTIVE_TASKS);
          mTasksPresenter.loadTasks(true);
  
          // Callback is captured and invoked with stubbed tasks
          verify(mTasksRepository).getTasks(mLoadTasksCallbackCaptor.capture());
          mLoadTasksCallbackCaptor.getValue().onTasksLoaded(TASKS);
  
          // Then progress indicator is hidden and active tasks are shown in UI
          verify(mTasksView).setLoadingIndicator(false);
          ArgumentCaptor<List> showTasksArgumentCaptor = ArgumentCaptor.forClass(List.class);
          verify(mTasksView).showTasks(showTasksArgumentCaptor.capture());
          assertTrue(showTasksArgumentCaptor.getValue().size() == 1);
      }
  
      @Test
      public void loadCompletedTasksFromRepositoryAndLoadIntoView() {
          // Given an initialized TasksPresenter with initialized tasks
          // When loading of Tasks is requested
          mTasksPresenter.setFiltering(TasksFilterType.COMPLETED_TASKS);
          mTasksPresenter.loadTasks(true);
  
          // Callback is captured and invoked with stubbed tasks
          verify(mTasksRepository).getTasks(mLoadTasksCallbackCaptor.capture());
          mLoadTasksCallbackCaptor.getValue().onTasksLoaded(TASKS);
  
          // Then progress indicator is hidden and completed tasks are shown in UI
          verify(mTasksView).setLoadingIndicator(false);
          ArgumentCaptor<List> showTasksArgumentCaptor = ArgumentCaptor.forClass(List.class);
          verify(mTasksView).showTasks(showTasksArgumentCaptor.capture());
          assertTrue(showTasksArgumentCaptor.getValue().size() == 2);
      }
  
      @Test
      public void clickOnFab_ShowsAddTaskUi() {
          // When adding a new task
          mTasksPresenter.addNewTask();
  
          // Then add task UI is shown
          verify(mTasksView).showAddTask();
      }
  
      @Test
      public void clickOnTask_ShowsDetailUi() {
          // Given a stubbed active task
          Task requestedTask = new Task("Details Requested", "For this task");
  
          // When open task details is requested
          mTasksPresenter.openTaskDetails(requestedTask);
  
          // Then task detail UI is shown
          verify(mTasksView).showTaskDetailsUi(any(String.class));
      }
  
      @Test
      public void completeTask_ShowsTaskMarkedComplete() {
          // Given a stubbed task
          Task task = new Task("Details Requested", "For this task");
  
          // When task is marked as complete
          mTasksPresenter.completeTask(task);
  
          // Then repository is called and task marked complete UI is shown
          verify(mTasksRepository).completeTask(task);
          verify(mTasksView).showTaskMarkedComplete();
      }
  
      @Test
      public void activateTask_ShowsTaskMarkedActive() {
          // Given a stubbed completed task
          Task task = new Task("Details Requested", "For this task", true);
          mTasksPresenter.loadTasks(true);
  
          // When task is marked as activated
          mTasksPresenter.activateTask(task);
  
          // Then repository is called and task marked active UI is shown
          verify(mTasksRepository).activateTask(task);
          verify(mTasksView).showTaskMarkedActive();
      }
  
      @Test
      public void unavailableTasks_ShowsError() {
          // When tasks are loaded
          mTasksPresenter.setFiltering(TasksFilterType.ALL_TASKS);
          mTasksPresenter.loadTasks(true);
  
          // And the tasks aren't available in the repository
          verify(mTasksRepository).getTasks(mLoadTasksCallbackCaptor.capture());
          mLoadTasksCallbackCaptor.getValue().onDataNotAvailable();
  
          // Then an error message is shown
          verify(mTasksView).showLoadingTasksError();
      }
  }
  