package org.openlmis.referencedata.domain;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.mockito.Mock;
import org.openlmis.referencedata.repository.ProductCategoryRepository;
import org.openlmis.referencedata.repository.ProgramRepository;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.springframework.test.util.ReflectionTestUtils;

import java.util.UUID;

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(BlockJUnit4ClassRunner.class)
public class ProgramProductBuilderTest {

  @Mock
  private ProgramRepository programRepository;

  @Mock
  private ProductCategoryRepository productCategoryRepository;

  private ProgramProduct programProduct;
  private OrderableProduct orderableProduct;
  private ProgramProductBuilder programProductBuilder;

  private Program program;
  private ProductCategory productCategory;

  @Before
  public void setUp() {
    program = new Program("SuperProgram");
    program.setId(UUID.randomUUID());

    when(programRepository.findOne(program.getId())).thenReturn(program);

    productCategory = ProductCategory.createNew(Code.code("SuperCategoryCode"));
    productCategory.setId(UUID.randomUUID());

    when(productCategoryRepository.findOne(productCategory.getId())).thenReturn(productCategory);

    orderableProduct = GlobalProduct.newGlobalProduct("SuperCode123", "each",
        "SuperName123", "SuperDescription", 10, 5, false);

    programProductBuilder = new ProgramProductBuilder(program.getId());
    ReflectionTestUtils.setField(programProductBuilder, "currencyCode", "USD");
    programProductBuilder.setProgramRepository(programRepository);
    programProductBuilder.setProductCategoryRepository(productCategoryRepository);
    programProductBuilder.setProductCategoryId(productCategory.getId());

    programProduct = programProductBuilder.createProgramProduct(orderableProduct);
  }

  @Test
  public void programProductShouldBeCreated() {
    assertNotNull(programProduct);
  }

  @Test
  public void isForProgramShouldBeTrue() {
    assertTrue(programProduct.isForProgram(program));
  }

  @Test
  public void productCategoryShouldBeSet() {
    assertNotNull(programProduct.getProductCategory().getId());
  }

}

@@ -33,24 +33,69 @@
 ta.domain;%0A%0A
+import static org.junit.Assert.assertEquals;%0A
 import stati
@@ -208,24 +208,89 @@
 kito.when;%0A%0A
+import org.joda.money.CurrencyUnit;%0Aimport org.joda.money.Money;%0A
 import org.j
@@ -741,16 +741,45 @@
 Utils;%0A%0A
+import java.math.BigDecimal;%0A
 import j
@@ -1084,32 +1084,33 @@
 programProduct;%0A
+%0A
   private Ordera
@@ -1193,17 +1193,16 @@
 uilder;%0A
-%0A
   privat
@@ -1264,16 +1264,70 @@
 egory;%0A%0A
+  private static final String CURRENCY_CODE = %22USD%22;%0A%0A
   @Befor
@@ -2018,21 +2018,29 @@
 yCode%22, 
-%22USD%22
+CURRENCY_CODE
 );%0A    p
@@ -2253,24 +2253,84 @@
 y.getId());%0A
+  %7D%0A%0A  @Test%0A  public void programProductShouldBeCreated() %7B
 %0A    program
@@ -2393,32 +2393,67 @@
 erableProduct);%0A
+    assertNotNull(programProduct);%0A
   %7D%0A%0A  @Test%0A  p
@@ -2496,283 +2496,1134 @@
 ated
-() %7B%0A    assertNotNull(programProduct);%0A  %7D%0A%0A  @Test%0A  public void isForProgramShouldBeTrue() %7B%0A    assertTrue(programProduct.isForProgram(program));%0A  %7D%0A%0A  @Test%0A  public void productCategoryShouldBeSet() %7B%0A    assertNotNull(programProduct.getProductCategory().getId());%0A  %7D%0A
+WithPricePerPack() %7B%0A    Money money = Money.of(CurrencyUnit.USD, 10);%0A    programProductBuilder.setPricePerPack(money);%0A%0A    programProduct = programProductBuilder.createProgramProduct(orderableProduct);%0A    pricePerPackEquals(new BigDecimal(%2210.00%22));%0A  %7D%0A%0A  @Test%0A  public void programProductShouldBeCreatedWithPricePerPackZeroIfNotSpecified() %7B%0A    programProduct = programProductBuilder.createProgramProduct(orderableProduct);%0A    pricePerPackEquals(new BigDecimal(%220.00%22));%0A  %7D%0A%0A  @Test%0A  public void isForProgramShouldBeTrue() %7B%0A    programProduct = programProductBuilder.createProgramProduct(orderableProduct);%0A    assertTrue(programProduct.isForProgram(program));%0A  %7D%0A%0A  @Test%0A  public void productCategoryShouldBeSet() %7B%0A    programProduct = programProductBuilder.createProgramProduct(orderableProduct);%0A    assertNotNull(programProduct.getProductCategory().getId());%0A  %7D%0A%0A  private void pricePerPackEquals(BigDecimal expected) %7B%0A    assertEquals(expected, programProduct.getPricePerPack().getAmount());%0A    assertEquals(CurrencyUnit.of(CURRENCY_CODE),%0A        programProduct.getPricePerPack().getCurrencyUnit());%0A  %7D
 %0A%7D%0A

add unit tests that verify that pricePerPack was set properly when creating program product