package org.openlmis.core.view.holder; import android.app.AlertDialog; import android.app.DatePickerDialog; import android.view.LayoutInflater; import android.view.View; import android.widget.DatePicker; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.openlmis.core.LMISTestRunner; import org.openlmis.core.R; import org.openlmis.core.exceptions.LMISException; import org.openlmis.core.manager.MovementReasonManager; import org.openlmis.core.model.StockCard; import org.openlmis.core.model.StockMovementItem; import org.openlmis.core.model.builder.StockCardBuilder; import org.openlmis.core.model.builder.StockMovementItemBuilder; import org.openlmis.core.model.builder.StockMovementViewModelBuilder; import org.openlmis.core.model.repository.StockRepository; import org.openlmis.core.utils.DateUtil; import org.openlmis.core.view.viewmodel.StockMovementViewModel; import org.robolectric.RuntimeEnvironment; import org.robolectric.shadows.ShadowAlertDialog; import org.robolectric.shadows.ShadowDatePickerDialog; import org.robolectric.shadows.ShadowToast; import java.text.ParseException; import java.util.Date; import roboguice.RoboGuice; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.roboguice.shaded.goole.common.collect.Lists.newArrayList; @RunWith(LMISTestRunner.class) public class StockMovementViewHolderTest { private StockMovementViewHolder viewHolder; private StockMovementViewModel viewModel; private StockCard stockCard; private View itemView; @Before public void setUp() throws LMISException, ParseException { itemView = LayoutInflater.from(RuntimeEnvironment.application).inflate(R.layout.item_stock_movement, null, false); viewHolder = new StockMovementViewHolder(itemView); viewModel = new StockMovementViewModelBuilder() .withMovementDate("2015-11-11") .withDocumentNo("12345") .withNegativeAdjustment(null) .withPositiveAdjustment(null) .withIssued("30") .withReceived(null) .withStockExistence("70") .withIsDraft(false) .withMovementReason(new MovementReasonManager.MovementReason(MovementReasonManager.MovementType.ISSUE, "ISSUE_1", "issue description")).build(); StockRepository stockRepository = RoboGuice.getInjector(RuntimeEnvironment.application).getInstance(StockRepository.class); stockCard = StockCardBuilder.saveStockCardWithOneMovement(stockRepository); } @Test public void shouldPopulateTextDataWhenPopulatingData() { viewModel.setRequested("999"); viewHolder.populate(viewModel, stockCard); assertEquals("12345", viewHolder.etDocumentNo.getText().toString()); assertEquals("2015-11-11", viewHolder.txMovementDate.getText().toString()); assertEquals("", viewHolder.etReceived.getText().toString()); assertEquals("", viewHolder.etNegativeAdjustment.getText().toString()); assertEquals("", viewHolder.etPositiveAdjustment.getText().toString()); assertEquals("30", viewHolder.etIssued.getText().toString()); assertEquals("70", viewHolder.txStockExistence.getText().toString()); assertEquals("999", viewHolder.etRequested.getText().toString()); assertEquals("issue description", viewHolder.txReason.getText().toString()); } @Test public void shouldDisableLineWhenPopulatingData() { viewHolder.populate(viewModel, stockCard); assertFalse(viewHolder.etDocumentNo.isEnabled()); assertFalse(viewHolder.etReceived.isEnabled()); assertFalse(viewHolder.etNegativeAdjustment.isEnabled()); assertFalse(viewHolder.etPositiveAdjustment.isEnabled()); assertFalse(viewHolder.etIssued.isEnabled()); } @Test public void shouldHideUnderline() { viewHolder.populate(viewModel, stockCard); assertNull(viewHolder.etIssued.getBackground()); assertNull(viewHolder.etPositiveAdjustment.getBackground()); assertNull(viewHolder.etNegativeAdjustment.getBackground()); assertNull(viewHolder.etReceived.getBackground()); assertNull(viewHolder.etDocumentNo.getBackground()); } @Test public void shouldSetFontColorRedIfNotIssueAdjustment() { viewModel.setReason(new MovementReasonManager.MovementReason(MovementReasonManager.MovementType.NEGATIVE_ADJUST, "negative_adjust", "negative_adjust description")); viewHolder.populate(viewModel, stockCard); int red = RuntimeEnvironment.application.getResources().getColor(R.color.color_red); assertEquals(red, viewHolder.txMovementDate.getCurrentTextColor()); assertEquals(red, viewHolder.txReason.getCurrentTextColor()); assertEquals(red, viewHolder.etDocumentNo.getCurrentTextColor()); assertEquals(red, viewHolder.etReceived.getCurrentTextColor()); assertEquals(red, viewHolder.etPositiveAdjustment.getCurrentTextColor()); assertEquals(red, viewHolder.etNegativeAdjustment.getCurrentTextColor()); assertEquals(red, viewHolder.txStockExistence.getCurrentTextColor()); } @Test public void shouldSetFontColorBlackIfIssueAdjustment() { viewModel.setReason(new MovementReasonManager.MovementReason(MovementReasonManager.MovementType.ISSUE, "ISSUE_1", "issue description")); viewHolder.populate(viewModel, stockCard); int black = RuntimeEnvironment.application.getResources().getColor(R.color.color_black); assertEquals(black, viewHolder.txMovementDate.getCurrentTextColor()); assertEquals(black, viewHolder.txReason.getCurrentTextColor()); assertEquals(black, viewHolder.etDocumentNo.getCurrentTextColor()); assertEquals(black, viewHolder.etReceived.getCurrentTextColor()); assertEquals(black, viewHolder.etPositiveAdjustment.getCurrentTextColor()); assertEquals(black, viewHolder.etNegativeAdjustment.getCurrentTextColor()); assertEquals(black, viewHolder.txStockExistence.getCurrentTextColor()); } @Test public void shouldShowMovementTypeDialogOnClick() { viewModel.setDraft(true); viewHolder.populate(viewModel, stockCard); viewHolder.txReason.performClick(); AlertDialog typeDialog = ShadowAlertDialog.getLatestAlertDialog(); assertNotNull(typeDialog); } @Test public void shouldShowMovementDateDialogOnClick() { viewModel.setDraft(true); viewHolder.populate(viewModel, stockCard); viewHolder.txMovementDate.performClick(); DatePickerDialog datePickerDialog = (DatePickerDialog) ShadowDatePickerDialog.getLatestDialog(); assertNotNull(datePickerDialog); } @Test public void shouldValidateMovementDateOnSelectionAndShowToastIfInvalid() throws ParseException, LMISException { viewHolder.populate(viewModel, stockCard); StockMovementViewHolder.MovementDateListener movementDateListener = viewHolder.new MovementDateListener(viewModel, new Date()); movementDateListener.onDateSet(mock(DatePicker.class), 2015, 11, 10); assertNotNull(ShadowToast.getLatestToast()); } @Test public void shouldValidateMovementDateOnSelectionAnd() throws ParseException, LMISException { viewHolder.populate(viewModel, stockCard); StockMovementViewHolder.MovementDateListener movementDateListener = viewHolder.new MovementDateListener(viewModel, DateUtil.parseString("11-11-2015", "MM-dd-YYYY")); movementDateListener.onDateSet(mock(DatePicker.class), 2015, 10, 15); assertEquals("15 Nov 2015", viewHolder.txMovementDate.getText().toString()); assertEquals("15 Nov 2015", viewModel.getMovementDate()); assertNull(ShadowToast.getLatestToast()); } @Test public void shouldOnlyEnableCurrentSelectedEditTextWhenChoseMovementTypeWhenToggleIsOn() throws ParseException, LMISException { viewModel.setDraft(true); viewHolder.populate(viewModel, stockCard); viewHolder.txMovementDate.setText(""); StockMovementViewHolder.MovementSelectListener listener = viewHolder.new MovementSelectListener(viewModel); MovementReasonManager.MovementReason receiveReason = new MovementReasonManager.MovementReason(MovementReasonManager.MovementType.RECEIVE, "DON", "Donations"); listener.onComplete(receiveReason); assertTrue(viewHolder.etReceived.isEnabled()); assertFalse(viewHolder.etPositiveAdjustment.isEnabled()); assertFalse(viewHolder.etNegativeAdjustment.isEnabled()); assertFalse(viewHolder.etIssued.isEnabled()); assertFalse(viewHolder.etRequested.isEnabled()); MovementReasonManager.MovementReason positiveReason = new MovementReasonManager.MovementReason(MovementReasonManager.MovementType.POSITIVE_ADJUST, "POSITIVE", "BOUGHT"); listener.onComplete(positiveReason); assertFalse(viewHolder.etReceived.isEnabled()); assertTrue(viewHolder.etPositiveAdjustment.isEnabled()); assertFalse(viewHolder.etNegativeAdjustment.isEnabled()); assertFalse(viewHolder.etIssued.isEnabled()); assertFalse(viewHolder.etRequested.isEnabled()); } @Test public void shouldEnableIssueAndRequestedEditTextWhenChoseIssueMovementTypeWhenToggleIsOn() throws ParseException, LMISException { StockMovementViewHolder stockMovementViewHolder = new StockMovementViewHolder(itemView); viewModel.setDraft(true); stockMovementViewHolder.populate(viewModel, stockCard); stockMovementViewHolder.txMovementDate.setText(""); StockMovementViewHolder.MovementSelectListener listener = stockMovementViewHolder.new MovementSelectListener(viewModel); MovementReasonManager.MovementReason receiveReason = new MovementReasonManager.MovementReason(MovementReasonManager.MovementType.ISSUE, "ISSUE_1", "issue description"); listener.onComplete(receiveReason); assertFalse(stockMovementViewHolder.etReceived.isEnabled()); assertFalse(stockMovementViewHolder.etPositiveAdjustment.isEnabled()); assertFalse(stockMovementViewHolder.etNegativeAdjustment.isEnabled()); assertTrue(stockMovementViewHolder.etIssued.isEnabled()); assertTrue(stockMovementViewHolder.etRequested.isEnabled()); } @Test public void shouldEnableMovementTypeAndReasonIfModelIsDraft() { viewModel.setDraft(true); viewHolder.populate(viewModel, stockCard); assertTrue(viewHolder.txMovementDate.isEnabled()); assertTrue(viewHolder.txReason.isEnabled()); } @Test public void shouldSetValueAfterTextChange() { viewHolder.populate(viewModel, stockCard); viewHolder.etIssued.setText("30"); assertEquals("30", viewModel.getIssued()); assertEquals("70", viewModel.getStockExistence()); assertEquals("70", viewHolder.txStockExistence.getText().toString()); } @Test public void shouldEnableIssueEditTextWhenModelWithIssueType() { viewModel.setDraft(true); viewHolder.populate(viewModel, stockCard); assertTrue(viewHolder.etIssued.isEnabled()); } @Test public void shouldEnableReceivedEditTextWhenModelWithReceivedType() { MovementReasonManager.MovementReason receivedReason = new MovementReasonManager.MovementReason(MovementReasonManager.MovementType.RECEIVE, "RECEIVE_1", "receive description"); viewModel.setDraft(true); viewModel.setReason(receivedReason); viewHolder.populate(viewModel, stockCard); assertTrue(viewHolder.etReceived.isEnabled()); } @Test public void shouldEnableNegativeAdjustmentEditTextWhenModelWithNegativeAdjustmentType() { MovementReasonManager.MovementReason negativeReason = new MovementReasonManager.MovementReason(MovementReasonManager.MovementType.NEGATIVE_ADJUST, "NEGATIVE_1", "negative adjustment description"); viewModel.setDraft(true); viewModel.setReason(negativeReason); viewHolder.populate(viewModel, stockCard); assertTrue(viewHolder.etNegativeAdjustment.isEnabled()); } @Test public void shouldClearDocumentNumberWhenReselectReason() { viewHolder.populate(viewModel, stockCard); viewHolder.etDocumentNo.setText("888"); StockMovementViewHolder.MovementSelectListener listener = viewHolder.new MovementSelectListener(viewModel); MovementReasonManager.MovementReason receiveReason = new MovementReasonManager.MovementReason(MovementReasonManager.MovementType.RECEIVE, "DON", "Donations"); listener.onComplete(receiveReason); assertThat(viewHolder.etDocumentNo.getText().toString(), is("")); } @Test public void shouldClearInputWhenReSelectSameReason() { viewHolder.populate(viewModel, stockCard); StockMovementViewHolder.MovementSelectListener listener = viewHolder.new MovementSelectListener(viewModel); MovementReasonManager.MovementReason receiveReason = new MovementReasonManager.MovementReason(MovementReasonManager.MovementType.RECEIVE, "DON", "Donations"); listener.onComplete(receiveReason); viewHolder.etReceived.setText("10"); listener.onComplete(receiveReason); assertThat(viewHolder.etReceived.getText().toString(), is("")); } @Test public void shouldEnablePositiveAdjustmentEditTextWhenModelWithPositiveAdjustmentType() { MovementReasonManager.MovementReason positiveReason = new MovementReasonManager.MovementReason(MovementReasonManager.MovementType.POSITIVE_ADJUST, "POSITIVE_1", "positive adjustment description"); viewModel.setDraft(true); viewModel.setReason(positiveReason); viewHolder.populate(viewModel, stockCard); assertTrue(viewHolder.etPositiveAdjustment.isEnabled()); } @Test public void shouldNotClearInputWhenRotate() { viewHolder.populate(viewModel, stockCard); MovementReasonManager.MovementReason positiveReason = new MovementReasonManager.MovementReason(MovementReasonManager.MovementType.POSITIVE_ADJUST, "POSITIVE_1", "positive adjustment description"); viewModel.setDraft(true); viewModel.setReason(positiveReason); viewHolder.etPositiveAdjustment.setText("10"); viewHolder.populate(viewModel, stockCard); assertThat(viewHolder.etPositiveAdjustment.getText().toString(), is("10")); } @Test public void shouldResetTxReasonValueWhenReuseViewModel() { viewHolder.populate(viewModel, stockCard); assertEquals(viewHolder.txReason.getText().toString(), "issue description"); viewModel.setDraft(true); viewModel.setReason(null); viewHolder.populate(viewModel, stockCard); assertEquals(viewHolder.txReason.getText().toString(), ""); } @Test public void shouldResetTextColorWhenReselectReason() { viewHolder.populate(viewModel, stockCard); StockMovementViewHolder.MovementSelectListener listener = viewHolder.new MovementSelectListener(viewModel); MovementReasonManager.MovementReason receiveReason = new MovementReasonManager.MovementReason(MovementReasonManager.MovementType.POSITIVE_ADJUST, "INVENTORY_POSITIVE", "Inventory description..."); listener.onComplete(receiveReason); assertThat(viewHolder.txReason.getCurrentTextColor(), is(RuntimeEnvironment.application.getResources().getColor(R.color.color_red))); MovementReasonManager.MovementReason issueReason = new MovementReasonManager.MovementReason(MovementReasonManager.MovementType.ISSUE, "PAV", "PAV Description"); listener.onComplete(issueReason); assertThat(viewHolder.txReason.getCurrentTextColor(), is(RuntimeEnvironment.application.getResources().getColor(R.color.color_black))); } @Test public void shouldGetLatestMovementDateAsThePreviousMovementDate() throws ParseException { StockCard stockCard = new StockCard(); StockMovementItem stockMovementItem1 = new StockMovementItemBuilder().withMovementDate("2015-10-10").build(); StockMovementItem stockMovementItem2 = new StockMovementItemBuilder().withMovementDate("2015-11-12").build(); StockMovementItem stockMovementItem3 = new StockMovementItemBuilder().withMovementDate("2015-09-10").build(); stockCard.setStockMovementItemsWrapper(newArrayList(stockMovementItem1, stockMovementItem2, stockMovementItem3)); Date previousMovementDate = viewHolder.getPreviousMovementDate(stockCard); assertThat(DateUtil.formatDate(previousMovementDate), is("12 Nov 2015")); } }