package org.openlmis.core.presenter;
import com.google.inject.AbstractModule;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.openlmis.core.LMISRepositoryUnitTest;
import org.openlmis.core.LMISTestRunner;
import org.openlmis.core.exceptions.LMISException;
import org.openlmis.core.manager.SharedPreferenceMgr;
import org.openlmis.core.model.Product;
import org.openlmis.core.model.StockCard;
import org.openlmis.core.model.StockMovementItem;
import org.openlmis.core.model.builder.ProductBuilder;
import org.openlmis.core.model.builder.StockCardBuilder;
import org.openlmis.core.model.repository.InventoryRepository;
import org.openlmis.core.model.repository.ProductRepository;
import org.openlmis.core.model.repository.StockRepository;
import org.openlmis.core.view.viewmodel.InventoryViewModel;
import org.openlmis.core.view.viewmodel.InventoryViewModelBuilder;
import org.openlmis.core.view.viewmodel.LotMovementViewModelBuilder;
import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import roboguice.RoboGuice;
import rx.Observable;
import rx.Scheduler;
import rx.android.plugins.RxAndroidPlugins;
import rx.android.plugins.RxAndroidSchedulersHook;
import rx.observers.TestSubscriber;
import rx.schedulers.Schedulers;
import static org.assertj.core.util.Lists.newArrayList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(LMISTestRunner.class)
public class InitialInventoryPresenterTest extends LMISRepositoryUnitTest {
private InitialInventoryPresenter initialInventoryPresenter;
StockRepository stockRepositoryMock;
ProductRepository productRepositoryMock;
InventoryPresenter.InventoryView view;
private Product product;
private SharedPreferenceMgr sharedPreferenceMgr;
private InventoryRepository mockInventoryRepository;
@Before
public void setup() throws Exception {
stockRepositoryMock = mock(StockRepository.class);
productRepositoryMock = mock(ProductRepository.class);
mockInventoryRepository = mock(InventoryRepository.class);
sharedPreferenceMgr = mock(SharedPreferenceMgr.class);
view = mock(InventoryPresenter.InventoryView.class);
RoboGuice.overrideApplicationInjector(RuntimeEnvironment.application, new MyTestModule());
initialInventoryPresenter = RoboGuice.getInjector(RuntimeEnvironment.application).getInstance(InitialInventoryPresenter.class);
initialInventoryPresenter.attachView(view);
product = new Product();
product.setPrimaryName("Test Product");
product.setCode("ABC");
RxAndroidPlugins.getInstance().reset();
RxAndroidPlugins.getInstance().registerSchedulersHook(new RxAndroidSchedulersHook() {
@Override
public Scheduler getMainThreadScheduler() {
return Schedulers.immediate();
}
});
}
@After
public void tearDown() {
RoboGuice.Util.reset();
}
@Test
public void shouldLoadMasterProductsList() throws LMISException {
StockCard stockCardVIA = StockCardBuilder.buildStockCard();
Product productVIA = new ProductBuilder().setPrimaryName("VIA Product").setCode("VIA Code").build();
stockCardVIA.setProduct(productVIA);
StockCard stockCardMMIA = StockCardBuilder.buildStockCard();
Product productMMIA = new ProductBuilder().setProductId(10L).setPrimaryName("MMIA Product").setCode("MMIA Code").setIsArchived(true).build();
stockCardMMIA.setProduct(productMMIA);
StockCard unknownAStockCard = StockCardBuilder.buildStockCard();
Product productUnknownA = new ProductBuilder().setPrimaryName("A Unknown Product").setCode("A Code").build();
unknownAStockCard.setProduct(productUnknownA);
StockCard unknownBStockCard = StockCardBuilder.buildStockCard();
Product productUnknownB = new ProductBuilder().setPrimaryName("B Unknown Product").setCode("B Code").build();
unknownBStockCard.setProduct(productUnknownB);
when(productRepositoryMock.listProductsArchivedOrNotInStockCard()).thenReturn(Arrays.asList(productMMIA, productVIA, productUnknownB, productUnknownA));
when(stockRepositoryMock.queryStockCardByProductId(10L)).thenReturn(stockCardMMIA);
TestSubscriber<List<InventoryViewModel>> subscriber = new TestSubscriber<>();
Observable<List<InventoryViewModel>> observable = initialInventoryPresenter.loadInventory();
observable.subscribe(subscriber);
subscriber.awaitTerminalEvent();
subscriber.assertNoErrors();
List<InventoryViewModel> receivedInventoryViewModels = subscriber.getOnNextEvents().get(0);
assertEquals(4, receivedInventoryViewModels.size());
}
@Test
public void shouldOnlyActivatedProductsInInventoryList() throws LMISException {
Product activeProduct1 = ProductBuilder.create().setPrimaryName("active product").setCode("P2").build();
Product activeProduct2 = ProductBuilder.create().setPrimaryName("active product").setCode("P3").build();
when(stockRepositoryMock.list()).thenReturn(new ArrayList<StockCard>());
when(productRepositoryMock.listProductsArchivedOrNotInStockCard()).thenReturn(Arrays.asList(activeProduct1, activeProduct2));
TestSubscriber<List<InventoryViewModel>> subscriber = new TestSubscriber<>();
Observable<List<InventoryViewModel>> observable = initialInventoryPresenter.loadInventory();
observable.subscribe(subscriber);
subscriber.awaitTerminalEvent();
subscriber.assertNoErrors();
List<InventoryViewModel> receivedInventoryViewModels = subscriber.getOnNextEvents().get(0);
assertEquals(2, receivedInventoryViewModels.size());
}
@Test
public void shouldInitStockCardAndCreateAInitInventoryMovementItem() throws LMISException {
StockCard stockcard = new StockCard();
stockcard.setProduct(product);
InventoryViewModel model = new InventoryViewModelBuilder(stockcard).setChecked(true).build();
InventoryViewModel model2 = new InventoryViewModelBuilder(product).setChecked(true).build();
model2.getNewLotMovementViewModelList().add(new LotMovementViewModelBuilder().setExpiryDate("Jan 2016").setQuantity("20").build());
model.getNewLotMovementViewModelList().add(new LotMovementViewModelBuilder().setExpiryDate("Feb 2015").setQuantity("2020").build());
model.getProduct().setArchived(true);
initialInventoryPresenter.getInventoryViewModelList().add(model);
initialInventoryPresenter.getInventoryViewModelList().add(model2);
initialInventoryPresenter.initOrArchiveBackStockCards();
verify(stockRepositoryMock, times(1)).updateStockCardWithProduct(any(StockCard.class));
verify(stockRepositoryMock, times(1)).addStockMovementAndUpdateStockCard(any(StockMovementItem.class));
}
@Test
public void shouldReInventoryArchivedStockCard() throws LMISException {
InventoryViewModel uncheckedModel = new InventoryViewModelBuilder(product)
.setChecked(false)
.build();
Product archivedProduct = new ProductBuilder().setPrimaryName("Archived product").setCode("BBC")
.setIsArchived(true).build();
StockCard archivedStockCard = new StockCardBuilder().setStockOnHand(0).setProduct(archivedProduct).build();
InventoryViewModel archivedViewModel = new InventoryViewModelBuilder(archivedStockCard)
.setChecked(true)
.build();
List<InventoryViewModel> inventoryViewModelList = newArrayList(uncheckedModel, archivedViewModel);
initialInventoryPresenter.getInventoryViewModelList().addAll(inventoryViewModelList);
initialInventoryPresenter.initOrArchiveBackStockCards();
assertFalse(archivedStockCard.getProduct().isArchived());
verify(stockRepositoryMock, times(1)).updateStockCardWithProduct(archivedStockCard);
}
@Test
public void shouldInitStockCardAndCreateAInitInventoryMovementItemWithLot() throws Exception {
product.setArchived(false);
InventoryViewModel model = new InventoryViewModelBuilder(product).setChecked(true).build();
initialInventoryPresenter.getInventoryViewModelList().add(model);
initialInventoryPresenter.initOrArchiveBackStockCards();
ArgumentCaptor<StockMovementItem> argument = ArgumentCaptor.forClass(StockMovementItem.class);
verify(stockRepositoryMock).addStockMovementAndUpdateStockCard(argument.capture());
}
public class MyTestModule extends AbstractModule {
@Override
protected void configure() {
bind(StockRepository.class).toInstance(stockRepositoryMock);
bind(ProductRepository.class).toInstance(productRepositoryMock);
bind(InventoryRepository.class).toInstance(mockInventoryRepository);
bind(SharedPreferenceMgr.class).toInstance(sharedPreferenceMgr);
}
}
}