package org.openlmis.core.presenter; import android.support.annotation.NonNull; import com.google.inject.AbstractModule; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.openlmis.core.LMISRepositoryUnitTest; import org.openlmis.core.LMISTestRunner; import org.openlmis.core.exceptions.LMISException; import org.openlmis.core.manager.MovementReasonManager; import org.openlmis.core.manager.SharedPreferenceMgr; import org.openlmis.core.model.DraftInventory; import org.openlmis.core.model.DraftLotItem; import org.openlmis.core.model.Inventory; 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.LotMovementViewModel; import org.openlmis.core.view.viewmodel.LotMovementViewModelBuilder; import org.openlmis.core.view.viewmodel.PhysicalInventoryViewModel; 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.Subscription; 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.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(LMISTestRunner.class) public class PhysicalInventoryPresenterTest extends LMISRepositoryUnitTest { private PhysicalInventoryPresenter presenter; StockRepository stockRepositoryMock; ProductRepository productRepositoryMock; InventoryPresenter.InventoryView view; private Product product; private StockCard stockCard; 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()); presenter = RoboGuice.getInjector(RuntimeEnvironment.application).getInstance(PhysicalInventoryPresenter.class); presenter.attachView(view); product = new Product(); product.setPrimaryName("Test Product"); product.setCode("ABC"); stockCard = buildDefaultStockCard(); RxAndroidPlugins.getInstance().reset(); RxAndroidPlugins.getInstance().registerSchedulersHook(new RxAndroidSchedulersHook() { @Override public Scheduler getMainThreadScheduler() { return Schedulers.immediate(); } }); } private StockCard buildDefaultStockCard() { StockCard stockCard = new StockCard(); stockCard.setStockOnHand(100); stockCard.setProduct(product); return stockCard; } @After public void tearDown() { RoboGuice.Util.reset(); } @Test public void shouldLoadPhysicalStockCardList() throws LMISException { StockCard stockCardVIA = StockCardBuilder.buildStockCard(); stockCardVIA.setProduct(new ProductBuilder().setPrimaryName("VIA Product").build()); StockCard stockCardMMIA = StockCardBuilder.buildStockCard(); stockCardMMIA.setProduct(new ProductBuilder().setPrimaryName("MMIA Product").build()); List<StockCard> stockCards = Arrays.asList(stockCardMMIA, stockCardVIA); when(stockRepositoryMock.list()).thenReturn(stockCards); TestSubscriber<List<InventoryViewModel>> subscriber = new TestSubscriber<>(); Observable<List<InventoryViewModel>> observable = presenter.loadInventory(); observable.subscribe(subscriber); subscriber.awaitTerminalEvent(); verify(stockRepositoryMock).list(); subscriber.assertNoErrors(); List<InventoryViewModel> receivedInventoryViewModels = subscriber.getOnNextEvents().get(0); assertEquals(receivedInventoryViewModels.size(), 2); } @Test public void shouldLoadPhysicalStockCardListWithoutDeactivatedOrKitProducts() throws LMISException { StockCard stockCardVIA = StockCardBuilder.buildStockCard(); stockCardVIA.setProduct(new ProductBuilder().setPrimaryName("VIA Product").setIsArchived(false).setIsActive(true).build()); StockCard stockCardMMIA = StockCardBuilder.buildStockCard(); stockCardMMIA.setProduct(new ProductBuilder().setPrimaryName("MMIA Product").setIsArchived(false).setIsActive(false).build()); StockCard kitStockCard = StockCardBuilder.buildStockCard(); kitStockCard.setProduct(new ProductBuilder().setPrimaryName("VIA Kit Product").setIsArchived(false).setIsActive(true).setIsKit(true).build()); List<StockCard> stockCards = Arrays.asList(stockCardMMIA, stockCardVIA, kitStockCard); when(stockRepositoryMock.list()).thenReturn(stockCards); TestSubscriber<List<InventoryViewModel>> subscriber = new TestSubscriber<>(); Observable<List<InventoryViewModel>> observable = presenter.loadInventory(); observable.subscribe(subscriber); subscriber.awaitTerminalEvent(); subscriber.assertNoErrors(); List<InventoryViewModel> receivedInventoryViewModels = subscriber.getOnNextEvents().get(0); assertEquals(1, receivedInventoryViewModels.size()); assertEquals("VIA Product", receivedInventoryViewModels.get(0).getProductName()); } @Test public void shouldMakePositiveAdjustment() throws LMISException { InventoryViewModel model = new InventoryViewModel(stockCard); model.getNewLotMovementViewModelList().add(new LotMovementViewModelBuilder().setExpiryDate("Jan 2015").setQuantity("120").build()); StockMovementItem item = presenter.calculateAdjustment(model, stockCard); assertThat(item.getMovementType(), is(MovementReasonManager.MovementType.POSITIVE_ADJUST)); assertThat(item.getMovementQuantity(), is(20L)); assertThat(item.getStockOnHand(), is(120L)); assertThat(item.getStockCard(), is(stockCard)); } @Test public void shouldMakeNegativeAdjustment() throws LMISException { InventoryViewModel model = new InventoryViewModel(stockCard); model.getNewLotMovementViewModelList().add(new LotMovementViewModelBuilder().setExpiryDate("Jan 2015").setQuantity("80").build()); StockMovementItem item = presenter.calculateAdjustment(model, stockCard); assertThat(item.getMovementType(), is(MovementReasonManager.MovementType.NEGATIVE_ADJUST)); assertThat(item.getMovementQuantity(), is(20L)); assertThat(item.getStockOnHand(), is(80L)); assertThat(item.getStockCard(), is(stockCard)); } @Test public void shouldCalculateStockAdjustment() throws LMISException { InventoryViewModel model = new InventoryViewModel(stockCard); model.getNewLotMovementViewModelList().add(new LotMovementViewModelBuilder().setExpiryDate("Jan 2015").setQuantity("100").build()); StockMovementItem item = presenter.calculateAdjustment(model, stockCard); assertThat(item.getMovementType(), is(MovementReasonManager.MovementType.PHYSICAL_INVENTORY)); assertThat(item.getMovementQuantity(), is(0L)); assertThat(item.getStockOnHand(), is(100L)); assertThat(item.getStockCard(), is(stockCard)); } @Test public void shouldRestoreDraftInventoryWithLDraftLotItems() throws Exception { ArrayList<InventoryViewModel> inventoryViewModels = getStockCardViewModels(); ArrayList<DraftInventory> draftInventories = new ArrayList<>(); DraftInventory draftInventory = new DraftInventory(); stockCard.setId(9); draftInventory.setStockCard(stockCard); draftInventory.setQuantity(20L); LotMovementViewModel lotMovementViewModel1 = new LotMovementViewModelBuilder().setLotNumber("test").setExpiryDate("Sep 2016").setQuantity("10").build(); LotMovementViewModel lotMovementViewModel2 = new LotMovementViewModelBuilder().setLotNumber("testNew").setExpiryDate("Sep 2016").setQuantity("10").build(); inventoryViewModels.get(0).setExistingLotMovementViewModelList(newArrayList(lotMovementViewModel1)); DraftLotItem draftLotItem1 = new DraftLotItem(lotMovementViewModel1, stockCard.getProduct(), false); DraftLotItem draftLotItem2 = new DraftLotItem(lotMovementViewModel2, stockCard.getProduct(), true); draftInventory.setDraftLotItemListWrapper(newArrayList(draftLotItem1, draftLotItem2)); draftInventories.add(draftInventory); when(mockInventoryRepository.queryAllDraft()).thenReturn(draftInventories); presenter.getInventoryViewModelList().addAll(inventoryViewModels); presenter.restoreDraftInventory(); assertThat(inventoryViewModels.get(0).getNewLotMovementViewModelList().get(0).getLotNumber(), is("testNew")); assertThat(inventoryViewModels.get(0).getExistingLotMovementViewModelList().get(0).getLotNumber(), is("test")); } private ArrayList<InventoryViewModel> getStockCardViewModels() { ArrayList<InventoryViewModel> inventoryViewModels = new ArrayList<>(); inventoryViewModels.add(buildInventoryViewModelWithOutDraft(9, "11", null)); InventoryViewModel inventoryViewModelWithOutDraft = buildInventoryViewModelWithOutDraft(3, "15", "11/02/2015"); inventoryViewModels.add(inventoryViewModelWithOutDraft); return inventoryViewModels; } @NonNull private InventoryViewModel buildInventoryViewModelWithOutDraft(int stockCardId, String quantity, String expireDate) { InventoryViewModel inventoryViewModelWithOutDraft = new PhysicalInventoryViewModel(buildDefaultStockCard()); inventoryViewModelWithOutDraft.setStockCardId(stockCardId); return inventoryViewModelWithOutDraft; } @Test public void shouldSetSignatureToViewModel() throws Exception { String signature = "signature"; presenter.getInventoryViewModelList().addAll(getStockCardViewModels()); TestSubscriber<Object> subscriber = new TestSubscriber<>(); Subscription subscription = presenter.doInventory(signature).subscribe(subscriber); subscriber.awaitTerminalEvent(); presenter.subscriptions.add(subscription); assertThat(presenter.getInventoryViewModelList().get(0).getSignature(), is(signature)); assertThat(presenter.getInventoryViewModelList().get(1).getSignature(), is(signature)); } @Test public void shouldUpdateLatestDoPhysicalInventoryTime() throws Exception { ArrayList<InventoryViewModel> inventoryViewModels = getStockCardViewModels(); TestSubscriber<List<InventoryViewModel>> subscriber = new TestSubscriber<>(); String sign = "test"; presenter.getInventoryViewModelList().clear(); presenter.getInventoryViewModelList().addAll(inventoryViewModels); Observable observable = presenter.doInventory(sign); observable.subscribe(subscriber); subscriber.awaitTerminalEvent(); subscriber.assertNoErrors(); verify(sharedPreferenceMgr).setLatestPhysicInventoryTime(anyString()); } @Test public void shouldSaveInventoryWhenCompletePhysicalInventory() throws Exception { TestSubscriber<List<InventoryViewModel>> subscriber = new TestSubscriber<>(); presenter.getInventoryViewModelList().clear(); presenter.getInventoryViewModelList().addAll(getStockCardViewModels()); String sign = "signature"; Observable observable = presenter.doInventory(sign); observable.subscribe(subscriber); subscriber.awaitTerminalEvent(); verify(mockInventoryRepository).save(any(Inventory.class)); } 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); } } @Test public void shouldGetCompleteCount() throws Exception { PhysicalInventoryViewModel inventoryViewModel = new PhysicalInventoryViewModel(stockCard); inventoryViewModel.setDone(true); presenter.inventoryViewModelList.add(inventoryViewModel); presenter.inventoryViewModelList.add(new PhysicalInventoryViewModel(stockCard)); presenter.inventoryViewModelList.add(new PhysicalInventoryViewModel(stockCard)); presenter.inventoryViewModelList.add(new PhysicalInventoryViewModel(stockCard)); assertEquals(1, presenter.getCompleteCount()); } }